//changed includes to match cerberus output #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; 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 ( node[ i ].type == "BAD NODE" ) { i++; continue; } if ( !canclaimnode( node[ i ], self.team ) ) { i++; continue; } if ( distancesquared( node[ i ].origin, self.origin ) < 65536 ) { i++; continue; } if ( self maps/mp/bots/_bot::bot_friend_goal_in_radius( "sd_defend", node[ i ].origin, 256 ) > 0 ) { i++; continue; } height = node[ i ].origin[ 2 ] - zone.nearest_node.origin[ 2 ]; if ( isDefined( isplanted ) && isplanted ) { dist = distance2d( node[ i ].origin, zone.nearest_node.origin ); score = ( 10000 - dist ) + height; } else { score = height; } if ( score > highest ) { highest = score; best = node; } 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; } } }