diff --git a/raw/scripts/mp/botwarfare-compiled.gsc b/raw/scripts/mp/botwarfare-compiled.gsc index 68e243e..9919903 100644 Binary files a/raw/scripts/mp/botwarfare-compiled.gsc and b/raw/scripts/mp/botwarfare-compiled.gsc differ diff --git a/raw/scripts/mp/botwarfare.gsc b/raw/scripts/mp/botwarfare.gsc index 2ad1596..cf0bfb1 100644 --- a/raw/scripts/mp/botwarfare.gsc +++ b/raw/scripts/mp/botwarfare.gsc @@ -5,6 +5,13 @@ The entry point and manager of the bots. */ +#include maps/mp/gametypes/_globallogic_utils; +#include maps/mp/bots/_bot_combat; +#include maps/mp/bots/_bot; +#include maps/mp/gametypes/_gameobjects; +#include maps/mp/_utility; +#include common_scripts/utility; + /* Entry point to the bots */ @@ -87,7 +94,7 @@ fixGamemodes() wait 0.25; if ( level.gametype == "sd" ) - level.bot_gametype = maps\mp\bots\_bot_sd::bot_sd_think; + level.bot_gametype = ::bot_sd_think; } /* @@ -930,3 +937,497 @@ is_bot() return false; } + + + + +// _bot_sd +// fix crash + +bot_sd_think() //checked changed to match cerberus output +{ + foreach ( zone in level.bombzones ) + { + if ( !isDefined( zone.nearest_node ) ) + { + nodes = getnodesinradiussorted( zone.trigger.origin, 256, 0 ); + /* + /# + assert( nodes.size ); + #/ + */ + zone.nearest_node = nodes[ 0 ]; + } + } + + zone = sd_get_planted_zone(); + + if ( isDefined( zone ) ) + { + self bot_sd_defender( zone, 1 ); + } + else if ( self.team == game[ "attackers" ] ) + { + if ( level.multibomb ) + { + self.isbombcarrier = 1; + } + + self bot_sd_attacker(); + } + else + { + zone = random( level.bombzones ); + self bot_sd_defender( zone ); + } +} + +bot_sd_attacker() //checked changed to match cerberus output +{ + level endon( "game_ended" ); + + if ( !level.multibomb && !isDefined( level.sdbomb.carrier ) && !level.bombplanted ) + { + self cancelgoal( "sd_protect_carrier" ); + + if ( !level.sdbomb maps\mp\gametypes\_gameobjects::isobjectawayfromhome() ) + { + if ( !self maps\mp\bots\_bot::bot_friend_goal_in_radius( "sd_pickup", level.sdbomb.curorigin, 64 ) ) + { + self addgoal( level.sdbomb.curorigin, 16, 4, "sd_pickup" ); + return; + } + } + else + { + self addgoal( level.sdbomb.curorigin, 16, 4, "sd_pickup" ); + return; + } + } + else + { + self cancelgoal( "sd_pickup" ); + } + + if ( is_true( self.isbombcarrier ) ) + { + goal = self getgoal( "sd_plant" ); + + if ( isDefined( goal ) ) + { + if ( distancesquared( self.origin, goal ) < 2304 ) + { + self setstance( "prone" ); + wait 0.5; + self pressusebutton( level.planttime + 1 ); + wait 0.5; + + if ( is_true( self.isplanting ) ) + { + wait ( level.planttime + 1 ); + } + + self pressusebutton( 0 ); + self setstance( "crouch" ); + wait 0.25; + self cancelgoal( "sd_plant" ); + self setstance( "stand" ); + } + + return; + } + else if ( getTime() > self.bot[ "patrol_update" ] ) + { + frac = sd_get_time_frac(); + + if ( ( randomint( 100 ) < ( frac * 100 ) ) || ( frac > 0.85 ) ) + { + zone = sd_get_closest_bomb(); + goal = sd_get_bomb_goal( zone.visuals[ 0 ] ); + + if ( isDefined( goal ) ) + { + if ( frac > 0.85 ) + { + self addgoal( goal, 24, 4, "sd_plant" ); + } + else + { + self addgoal( goal, 24, 3, "sd_plant" ); + } + } + } + + self.bot[ "patrol_update" ] = getTime() + randomintrange( 2500, 5000 ); + } + } + else if ( isDefined( level.sdbomb.carrier ) && !isplayer( level.sdbomb.carrier ) ) + { + if ( !isDefined( self.protectcarrier ) ) + { + if ( randomint( 100 ) > 70 ) + { + self.protectcarrier = 1; + } + else + { + self.protectcarrier = 0; + } + } + + if ( self.protectcarrier ) + { + goal = level.sdbomb.carrier getgoal( "sd_plant" ); + + if ( isDefined( goal ) ) + { + nodes = getnodesinradiussorted( goal, 256, 0 ); + + if ( isDefined( nodes ) && ( nodes.size > 0 ) && !isDefined( self getgoal( "sd_protect_carrier" ) ) ) + { + self addgoal( nodes[ randomint( nodes.size ) ], 24, 3, "sd_protect_carrier" ); + } + } + } + } +} + +bot_sd_defender( zone, isplanted ) //checked partially changed to match cerberus output did not use foreach see github for more info +{ + bot_sd_grenade(); + + if ( isDefined( isplanted ) && isplanted && self hasgoal( "sd_defend" ) ) + { + goal = self getgoal( "sd_defend" ); + planted = sd_get_planted_zone(); + + foreach ( zone in level.bombzones ) + { + if ( planted != zone && ( distance2d( goal, zone.nearest_node.origin ) < distance2d( goal, planted.nearest_node.origin ) ) ) + { + self cancelgoal( "sd_defend" ); + } + } + } + else if ( self atgoal( "sd_defend" ) || self bot_need_to_defuse() ) + { + bot_sd_defender_think( zone ); + + if ( self hasgoal( "sd_defend" ) ) + { + return; + } + } + + if ( self hasgoal( "enemy_patrol" ) ) + { + goal = self getgoal( "enemy_patrol" ); + closezone = sd_get_closest_bomb(); + + if ( distancesquared( goal, closezone.nearest_node.origin ) < 262144 ) + { + self clearlookat(); + self cancelgoal( "sd_defend" ); + return; + } + } + + if ( self hasgoal( "sd_defend" ) ) + { + self.bot[ "patrol_update" ] = getTime() + randomintrange( 2500, 5000 ); + return; + } + + if ( self hasgoal( "enemy_patrol" ) ) + { + return; + } + + nodes = getvisiblenodes( zone.nearest_node ); + best = undefined; + highest = -100; + i = 0; + + while ( i < nodes.size ) + { + if ( nodes[ i ].type == "BAD NODE" || !canclaimnode( nodes[ i ], self.team ) || ( distancesquared( nodes[ i ].origin, self.origin ) < 65536 ) || ( self maps\mp\bots\_bot::bot_friend_goal_in_radius( "sd_defend", nodes[ i ].origin, 256 ) > 0 ) ) + { + i++; + } + else + { + height = nodes[ i ].origin[ 2 ] - zone.nearest_node.origin[ 2 ]; + + if ( is_true( isplanted ) ) + { + dist = distance2d( nodes[ i ].origin, zone.nearest_node.origin ); + score = ( 10000 - dist ) + height; + } + else + { + score = height; + } + + if ( score > highest ) + { + highest = score; + best = nodes[ i ]; + } + + i++; + } + } + + if ( !isDefined( best ) ) + { + return; + } + + self addgoal( best, 24, 3, "sd_defend" ); +} + +bot_get_look_at() //checked matches cebrerus output +{ + enemy = self maps\mp\bots\_bot::bot_get_closest_enemy( self.origin, 1 ); + + if ( isDefined( enemy ) ) + { + node = getvisiblenode( self.origin, enemy.origin ); + + if ( isDefined( node ) && ( distancesquared( self.origin, node.origin ) > 16384 ) ) + { + return node.origin; + } + } + + enemies = self maps\mp\bots\_bot::bot_get_enemies( 0 ); + + if ( enemies.size ) + { + enemy = random( enemies ); + } + + if ( isDefined( enemy ) ) + { + node = getvisiblenode( self.origin, enemy.origin ); + + if ( isDefined( node ) && ( distancesquared( self.origin, node.origin ) > 16384 ) ) + { + return node.origin; + } + } + + zone = sd_get_closest_bomb(); + node = getvisiblenode( self.origin, zone.nearest_node.origin ); + + if ( isDefined( node ) && ( distancesquared( self.origin, node.origin ) > 16384 ) ) + { + return node.origin; + } + + forward = anglesToForward( self getplayerangles() ); + origin = self geteye() + ( forward * 1024 ); + return origin; +} + +bot_sd_defender_think( zone ) //checked matches cerberus output +{ + if ( self bot_need_to_defuse() ) + { + if ( self maps\mp\bots\_bot::bot_friend_goal_in_radius( "sd_defuse", level.sdbombmodel.origin, 16 ) > 0 ) + { + return; + } + + self clearlookat(); + goal = self getgoal( "sd_defuse" ); + + if ( isDefined( goal ) && ( distancesquared( self.origin, goal ) < 2304 ) ) + { + self setstance( "prone" ); + wait 0.5; + self pressusebutton( level.defusetime + 1 ); + wait 0.5; + + if ( is_true( self.isdefusing ) ) + { + wait ( level.defusetime + 1 ); + } + + self pressusebutton( 0 ); + self setstance( "crouch" ); + wait 0.25; + self cancelgoal( "sd_defuse" ); + self setstance( "stand" ); + return; + } + + if ( !isDefined( goal ) && ( distance2dsquared( self.origin, level.sdbombmodel.origin ) < 1000000 ) ) + { + self addgoal( level.sdbombmodel.origin, 24, 4, "sd_defuse" ); + } + + return; + } + + if ( getTime() > self.bot[ "patrol_update" ] ) + { + if ( cointoss() ) + { + self clearlookat(); + self cancelgoal( "sd_defend" ); + return; + } + + self.bot[ "patrol_update" ] = getTime() + randomintrange( 2500, 5000 ); + } + + if ( self hasgoal( "enemy_patrol" ) ) + { + goal = self getgoal( "enemy_patrol" ); + zone = sd_get_closest_bomb(); + + if ( distancesquared( goal, zone.nearest_node.origin ) < 262144 ) + { + self clearlookat(); + self cancelgoal( "sd_defend" ); + return; + } + } + + if ( getTime() > self.bot[ "lookat_update" ] ) + { + origin = self bot_get_look_at(); + z = 20; + + if ( distancesquared( origin, self.origin ) > 262144 ) + { + z = randomintrange( 16, 60 ); + } + + self lookat( origin + ( 0, 0, z ) ); + self.bot[ "lookat_update" ] = getTime() + randomintrange( 1500, 3000 ); + + if ( distancesquared( origin, self.origin ) > 65536 ) + { + dir = vectornormalize( self.origin - origin ); + dir = vectorScale( dir, 256 ); + origin += dir; + } + + self maps\mp\bots\_bot_combat::bot_combat_throw_proximity( origin ); + } +} + +bot_need_to_defuse() //checked changed at own discretion +{ + if ( level.bombplanted && self.team == game[ "defenders" ] ) + { + return 1; + } + + return 0; +} + +sd_get_bomb_goal( ent ) //checked changed to match cerberus output +{ + goals = []; + dir = anglesToForward( ent.angles ); + dir = vectorScale( dir, 32 ); + goals[ 0 ] = ent.origin + dir; + goals[ 1 ] = ent.origin - dir; + dir = anglesToRight( ent.angles ); + dir = vectorScale( dir, 48 ); + goals[ 2 ] = ent.origin + dir; + goals[ 3 ] = ent.origin - dir; + goals = array_randomize( goals ); + + foreach ( goal in goals ) + { + if ( findpath( self.origin, goal, 0 ) ) + { + return goal; + } + } + + return undefined; +} + +sd_get_time_frac() //checked matches cerberus output +{ + remaining = maps\mp\gametypes\_globallogic_utils::gettimeremaining(); + end = ( level.timelimit * 60 ) * 1000; + + if ( end == 0 ) + { + end = self.spawntime + 120000; + remaining = end - getTime(); + } + + return 1 - ( remaining / end ); +} + +sd_get_closest_bomb() //checked partially changed to match cerberus output did not use continue see github for more info +{ + best = undefined; + distsq = 9999999; + + foreach ( zone in level.bombzones ) + { + d = distancesquared( self.origin, zone.curorigin ); + + if ( !isDefined( best ) ) + { + best = zone; + distsq = d; + } + else if ( d < distsq ) + { + best = zone; + distsq = d; + } + } + + return best; +} + +sd_get_planted_zone() //checked changed to match cerberus output +{ + if ( level.bombplanted ) + { + foreach ( zone in level.bombzones ) + { + if ( zone.interactteam == "none" ) + { + return zone; + } + } + } + + return undefined; +} + +bot_sd_grenade() //checked changed to match cerberus output +{ + enemies = bot_get_enemies(); + + if ( !enemies.size ) + { + return; + } + + zone = sd_get_closest_bomb(); + + foreach ( enemy in enemies ) + { + if ( distancesquared( enemy.origin, zone.nearest_node.origin ) < 147456 ) + { + if ( !self maps\mp\bots\_bot_combat::bot_combat_throw_lethal( enemy.origin ) ) + { + self maps\mp\bots\_bot_combat::bot_combat_throw_tactical( enemy.origin ); + } + + return; + } + } +}