#include maps/mp/gametypes/_weapon_utils; #include maps/mp/bots/_bot; #include maps/mp/_utility; #include common_scripts/utility; bot_combat_think( damage, attacker, direction ) { self allowattack( 0 ); self pressads( 0 ); for ( ;; ) { if ( self atgoal( "enemy_patrol" ) ) { self cancelgoal( "enemy_patrol" ); } self maps/mp/bots/_bot::bot_update_failsafe(); self maps/mp/bots/_bot::bot_update_crouch(); self maps/mp/bots/_bot::bot_update_crate(); if ( !bot_can_do_combat() ) { return; } difficulty = maps/mp/bots/_bot::bot_get_difficulty(); /# if ( bot_has_enemy() ) { if ( getDvarInt( "bot_IgnoreHumans" ) ) { if ( isplayer( self.bot.threat.entity ) && !self.bot.threat.entity is_bot() ) { self bot_combat_idle(); #/ } } } sight = bot_best_enemy(); bot_select_weapon(); ent = self.bot.threat.entity; pos = self.bot.threat.position; if ( !sight ) { if ( threat_is_player() ) { if ( distancesquared( self.origin, ent.origin ) < 65536 ) { prediction = self predictposition( ent, 4 ); height = ent getplayerviewheight(); self lookat( prediction + ( 0, 0, height ) ); self addgoal( ent.origin, 24, 4, "enemy_patrol" ); self allowattack( 0 ); wait 0,05; continue; } else self addgoal( self.origin, 24, 3, "enemy_patrol" ); if ( difficulty != "easy" && cointoss() ) { self bot_combat_throw_lethal( pos ); self bot_combat_throw_tactical( pos ); } bot_combat_dead(); self addgoal( pos, 24, 4, "enemy_patrol" ); } bot_combat_idle( damage, attacker, direction ); return; } else { if ( threat_dead() ) { bot_combat_dead(); return; } } bot_update_cover(); bot_combat_main(); if ( threat_is_turret() ) { bot_turret_set_dangerous( ent ); bot_combat_throw_smoke( ent.origin ); } if ( !threat_is_turret() || threat_is_ai_tank() && threat_is_equipment() ) { bot_combat_throw_emp( ent.origin ); bot_combat_throw_lethal( ent.origin ); } else { if ( threat_is_qrdrone() ) { bot_combat_throw_emp( ent.origin ); break; } else { if ( threat_requires_rocket( ent ) ) { self cancelgoal( "enemy_patrol" ); self addgoal( self.origin, 24, 4, "cover" ); } } } if ( difficulty == "easy" ) { wait 0,5; continue; } else if ( difficulty == "normal" ) { wait 0,25; continue; } else if ( difficulty == "hard" ) { wait 0,1; continue; } else { wait 0,05; } } } bot_can_do_combat() { if ( self ismantling() || self isonladder() ) { return 0; } return 1; } threat_dead() { if ( bot_has_enemy() ) { ent = self.bot.threat.entity; if ( threat_is_turret() ) { if ( isDefined( ent.dead ) ) { return ent.dead; } } else { if ( threat_is_qrdrone() ) { if ( isDefined( ent.crash_accel ) ) { return ent.crash_accel; } } } return !isalive( ent ); } return 1; } bot_can_reload() { weapon = self getcurrentweapon(); if ( weapon == "none" ) { return 0; } if ( !self getweaponammostock( weapon ) ) { return 0; } if ( !self isreloading() || self isswitchingweapons() && self isthrowinggrenade() ) { return 0; } return 1; } bot_combat_idle( damage, attacker, direction ) { self pressads( 0 ); self allowattack( 0 ); self allowsprint( 1 ); bot_clear_enemy(); weapon = self getcurrentweapon(); if ( bot_can_reload() ) { frac = 0,5; if ( bot_has_lmg() ) { frac = 0,25; } frac += randomfloatrange( -0,1, 0,1 ); if ( bot_weapon_ammo_frac() < frac ) { self pressusebutton( 0,1 ); } } if ( isDefined( damage ) ) { bot_patrol_near_enemy( damage, attacker, direction ); return; } self cancelgoal( "cover" ); self cancelgoal( "flee" ); } bot_combat_dead( damage ) { difficulty = maps/mp/bots/_bot::bot_get_difficulty(); switch( difficulty ) { case "easy": wait 0,75; break; case "normal": wait 0,5; break; case "hard": wait 0,25; break; case "fu": wait 0,1; break; } self allowattack( 0 ); switch( difficulty ) { case "easy": case "normal": wait 1; break; case "hard": wait_endon( 0,5, "damage" ); break; case "fu": wait_endon( 0,25, "damage" ); break; } bot_clear_enemy(); } bot_combat_main() { weapon = self getcurrentweapon(); currentammo = self getweaponammoclip( weapon ) + self getweaponammostock( weapon ); if ( !currentammo || bot_has_melee_weapon() ) { if ( threat_is_player() || threat_is_dog() ) { bot_combat_melee( weapon ); } return; } time = getTime(); if ( !bot_should_hip_fire() ) { ads = self.bot.threat.dot > 0,96; } difficulty = maps/mp/bots/_bot::bot_get_difficulty(); if ( ads ) { self pressads( 1 ); } else { self pressads( 0 ); } if ( ads && self playerads() < 1 ) { ratio = int( floor( bot_get_converge_time() / bot_get_converge_rate() ) ); step = ratio % 50; self.bot.threat.time_aim_interval = ratio - step; self.bot.threat.time_aim_correct = time; ideal = bot_update_aim( 4 ); bot_update_lookat( ideal, 0 ); return; } frames = 4; frames += randomintrange( 0, 3 ); if ( difficulty != "fu" ) { if ( distancesquared( self.bot.threat.entity.origin, self.bot.threat.position ) > 225 ) { self.bot.threat.time_aim_correct = time; if ( time > self.bot.threat.time_first_sight ) { self.bot.threat.time_first_sight = time - 100; } } } if ( time >= self.bot.threat.time_aim_correct ) { self.bot.threat.time_aim_correct += self.bot.threat.time_aim_interval; frac = ( time - self.bot.threat.time_first_sight ) / bot_get_converge_time(); frac = clamp( frac, 0, 1 ); if ( !threat_is_player() ) { frac = 1; } self.bot.threat.aim_target = bot_update_aim( frames ); self.bot.threat.position = self.bot.threat.entity.origin; bot_update_lookat( self.bot.threat.aim_target, frac ); } if ( difficulty == "hard" || difficulty == "fu" ) { if ( bot_on_target( self.bot.threat.entity.origin, 30 ) ) { self allowattack( 1 ); } else { self allowattack( 0 ); } } else { if ( bot_on_target( self.bot.threat.aim_target, 45 ) ) { self allowattack( 1 ); } else { self allowattack( 0 ); } } if ( threat_is_equipment() ) { if ( bot_on_target( self.bot.threat.entity.origin, 3 ) ) { self allowattack( 1 ); } else { self allowattack( 0 ); } } if ( isDefined( self.stingerlockstarted ) && self.stingerlockstarted ) { self allowattack( self.stingerlockfinalized ); return; } if ( threat_is_player() ) { if ( self iscarryingturret() && self.bot.threat.dot > 0 ) { self pressattackbutton(); } if ( self.bot.threat.dot > 0 && distance2dsquared( self.origin, self.bot.threat.entity.origin ) < bot_get_melee_range_sq() ) { self addgoal( self.bot.threat.entity.origin, 24, 4, "enemy_patrol" ); self pressmelee(); } } if ( threat_using_riotshield() ) { self bot_riotshield_think( self.bot.threat.entity ); } else { if ( bot_has_shotgun() ) { self bot_shotgun_think(); } } } bot_combat_melee( weapon ) { if ( !threat_is_player() && !threat_is_dog() ) { threat_ignore( self.bot.threat.entity, 60 ); self bot_clear_enemy(); return; } self cancelgoal( "cover" ); self pressads( 0 ); self allowattack( 0 ); for ( ;; ) { if ( !isalive( self.bot.threat.entity ) ) { self bot_clear_enemy(); self cancelgoal( "enemy_patrol" ); return; } if ( self isthrowinggrenade() || self isswitchingweapons() ) { self cancelgoal( "enemy_patrol" ); return; } if ( !bot_has_melee_weapon() && self getweaponammoclip( weapon ) ) { self cancelgoal( "enemy_patrol" ); return; } frames = 4; prediction = self predictposition( self.bot.threat.entity, frames ); if ( !isplayer( self.bot.threat.entity ) ) { height = self.bot.threat.entity getcentroid()[ 2 ] - prediction[ 2 ]; return prediction + ( 0, 0, height ); } else { height = self.bot.threat.entity getplayerviewheight(); } self lookat( prediction + ( 0, 0, height ) ); distsq = distance2dsquared( self.origin, prediction ); dot = bot_dot_product( self.bot.threat.entity.origin ); if ( dot > 0 && distsq < bot_get_melee_range_sq() ) { if ( self.bot.threat.entity getstance() == "prone" ) { self setstance( "crouch" ); } if ( weapon == "knife_held_mp" ) { self pressattackbutton(); wait 0,1; break; } else { self pressmelee(); wait 0,1; } } goal = self getgoal( "enemy_patrol" ); if ( !isDefined( goal ) || distancesquared( prediction, goal ) > bot_get_melee_range_sq() ) { if ( !findpath( self.origin, prediction, undefined, 0, 1 ) ) { threat_ignore( self.bot.threat.entity, 10 ); self bot_clear_enemy(); self cancelgoal( "enemy_patrol" ); return; } if ( weapon == "riotshield_mp" ) { if ( maps/mp/bots/_bot::bot_get_difficulty() != "easy" ) { self setstance( "crouch" ); self allowsprint( 0 ); } } self addgoal( prediction, 4, 4, "enemy_patrol" ); } wait 0,05; } } bot_get_fov() { weapon = self getcurrentweapon(); reduction = 1; if ( weapon != "none" && isweaponscopeoverlay( weapon ) && self playerads() >= 1 ) { reduction = 0,25; } return self.bot.fov * reduction; } bot_get_converge_time() { difficulty = maps/mp/bots/_bot::bot_get_difficulty(); switch( difficulty ) { case "easy": return 3500; case "normal": return 2000; case "hard": return 1500; case "fu": return 100; } return 2000; } } } } } bot_get_converge_rate() { difficulty = maps/mp/bots/_bot::bot_get_difficulty(); switch( difficulty ) { case "easy": return 2; case "normal": return 4; case "hard": return 5; case "fu": return 7; } return 4; } } } } } bot_get_melee_range_sq() { difficulty = maps/mp/bots/_bot::bot_get_difficulty(); switch( difficulty ) { case "easy": return 1600; case "normal": return 4900; case "hard": return 4900; case "fu": return 4900; } return 4900; } } } } } bot_get_aim_error() { difficulty = maps/mp/bots/_bot::bot_get_difficulty(); switch( difficulty ) { case "easy": return 30; case "normal": return 20; case "hard": return 15; case "fu": return 2; } return 20; } } } } } bot_update_lookat( origin, frac ) { angles = vectorToAngle( origin - self.origin ); right = anglesToRight( angles ); error = bot_get_aim_error() * ( 1 - frac ); if ( cointoss() ) { error *= -1; } height = origin[ 2 ] - self.bot.threat.entity.origin[ 2 ]; height *= 1 - frac; if ( cointoss() ) { height *= -1; } end = origin + ( right * error ); end += ( 0, 0, height ); red = 1 - frac; green = frac; self lookat( end ); } bot_on_target( aim_target, radius ) { angles = self getplayerangles(); forward = anglesToForward( angles ); origin = self getplayercamerapos(); len = distance( aim_target, origin ); end = origin + ( forward * len ); if ( distance2dsquared( aim_target, end ) < ( radius * radius ) ) { return 1; } return 0; } bot_dot_product( origin ) { angles = self getplayerangles(); forward = anglesToForward( angles ); delta = origin - self getplayercamerapos(); delta = vectornormalize( delta ); dot = vectordot( forward, delta ); return dot; } bot_has_enemy() { return isDefined( self.bot.threat.entity ); } threat_is_player() { ent = self.bot.threat.entity; if ( isDefined( ent ) ) { return isplayer( ent ); } } threat_is_dog() { ent = self.bot.threat.entity; if ( isDefined( ent ) ) { return isai( ent ); } } threat_is_turret() { ent = self.bot.threat.entity; if ( isDefined( ent ) ) { return ent.classname == "auto_turret"; } } threat_is_ai_tank() { ent = self.bot.threat.entity; if ( isDefined( ent ) && isDefined( ent.targetname ) ) { return ent.targetname == "talon"; } } threat_is_qrdrone( ent ) { if ( !isDefined( ent ) ) { ent = self.bot.threat.entity; } if ( isDefined( ent ) && isDefined( ent.helitype ) ) { return ent.helitype == "qrdrone"; } } threat_using_riotshield() { if ( threat_is_player() ) { weapon = self.bot.threat.entity getcurrentweapon(); return weapon == "riotshield_mp"; } return 0; } threat_is_equipment() { ent = self.bot.threat.entity; if ( !isDefined( ent ) ) { return 0; } if ( threat_is_player() ) { return 0; } if ( isDefined( ent.model ) && ent.model == "t6_wpn_tac_insert_world" ) { return 1; } if ( isDefined( ent.name ) ) { return isweaponequipment( ent.name ); } } bot_clear_enemy() { self clearlookat(); self.bot.threat.entity = undefined; } bot_best_enemy() { fov = bot_get_fov(); ent = self.bot.threat.entity; if ( isDefined( ent ) ) { if ( isplayer( ent ) || isai( ent ) ) { dot = bot_dot_product( ent.origin ); if ( dot >= fov ) { if ( self botsighttracepassed( ent ) ) { self.bot.threat.time_recent_sight = getTime(); self.bot.threat.dot = dot; return 1; } } } } enemies = self getthreats( fov ); _a791 = enemies; _k791 = getFirstArrayKey( _a791 ); while ( isDefined( _k791 ) ) { enemy = _a791[ _k791 ]; if ( threat_should_ignore( enemy ) ) { } else if ( !isplayer( enemy ) && enemy.classname != "grenade" ) { if ( level.gametype == "hack" ) { if ( enemy.classname == "script_vehicle" ) { } } else if ( enemy.classname == "auto_turret" ) { if ( isDefined( enemy.dead ) || enemy.dead && isDefined( enemy.carried ) && enemy.carried ) { } else { if ( isDefined( enemy.turret_active ) && !enemy.turret_active ) { break; } } else { if ( threat_requires_rocket( enemy ) ) { if ( !bot_has_launcher() ) { break; } else origin = self getplayercamerapos(); angles = vectorToAngle( enemy.origin - origin ); if ( angles[ 0 ] < 290 ) { threat_ignore( enemy, 3,5 ); break; } } } else { if ( self botsighttracepassed( enemy ) ) { self.bot.threat.entity = enemy; self.bot.threat.time_first_sight = getTime(); self.bot.threat.time_recent_sight = getTime(); self.bot.threat.dot = bot_dot_product( enemy.origin ); self.bot.threat.position = enemy.origin; return 1; } } } } _k791 = getNextArrayKey( _a791, _k791 ); } return 0; } threat_requires_rocket( enemy ) { if ( !isDefined( enemy ) || isplayer( enemy ) ) { return 0; } if ( isDefined( enemy.helitype ) && enemy.helitype == "qrdrone" ) { return 0; } if ( isDefined( enemy.targetname ) ) { if ( enemy.targetname == "remote_mortar" ) { return 1; } else { if ( enemy.targetname == "uav" || enemy.targetname == "counteruav" ) { return 1; } } } if ( enemy.classname == "script_vehicle" && enemy.vehicleclass == "helicopter" ) { return 1; } return 0; } threat_is_warthog( enemy ) { if ( !isDefined( enemy ) || isplayer( enemy ) ) { return 0; } if ( enemy.classname == "script_vehicle" && enemy.vehicleclass == "plane" ) { return 1; } return 0; } threat_should_ignore( entity ) { ignore_time = self.bot.ignore_entity[ entity getentitynumber() ]; if ( isDefined( ignore_time ) ) { if ( getTime() < ignore_time ) { return 1; } } return 0; } threat_ignore( entity, secs ) { self.bot.ignore_entity[ entity getentitynumber() ] = getTime() + ( secs * 1000 ); } bot_update_aim( frames ) { ent = self.bot.threat.entity; prediction = self predictposition( ent, frames ); if ( bot_using_launcher() && !threat_requires_rocket( ent ) ) { return prediction - ( 0, 0, randomintrange( 0, 10 ) ); } if ( !threat_is_player() ) { height = ent getcentroid()[ 2 ] - prediction[ 2 ]; return prediction + ( 0, 0, height ); } height = ent getplayerviewheight(); if ( threat_using_riotshield() ) { dot = ent bot_dot_product( self.origin ); if ( dot > 0,8 && ent getstance() == "stand" ) { return prediction + vectorScale( ( 0, 0, 1 ), 5 ); } } torso = prediction + ( 0, 0, height / 1,6 ); return torso; } bot_update_cover() { if ( maps/mp/bots/_bot::bot_get_difficulty() == "easy" ) { return; } if ( bot_has_melee_weapon() ) { self cancelgoal( "cover" ); self cancelgoal( "flee" ); return; } if ( threat_using_riotshield() ) { self cancelgoal( "enemy_patrol" ); self cancelgoal( "flee" ); return; } enemy = self.bot.threat.entity; if ( threat_is_turret() && !bot_has_sniper() && !bot_has_melee_weapon() ) { goal = enemy turret_get_attack_node(); if ( isDefined( goal ) ) { self cancelgoal( "enemy_patrol" ); self addgoal( goal, 24, 3, "cover" ); } } if ( !isplayer( enemy ) ) { return; } dot = enemy bot_dot_product( self.origin ); if ( dot < 0,8 && !bot_has_shotgun() ) { self cancelgoal( "cover" ); self cancelgoal( "flee" ); return; } ammo_frac = bot_weapon_ammo_frac(); health_frac = bot_health_frac(); cover_score = dot - ammo_frac - health_frac; if ( bot_should_hip_fire() && !bot_has_shotgun() ) { cover_score += 1; } if ( cover_score > 0,25 ) { nodes = getnodesinradiussorted( self.origin, 1024, 256, 512, "Path", 8 ); nearest = bot_nearest_node( enemy.origin ); while ( isDefined( nearest ) && !self hasgoal( "flee" ) ) { _a1018 = nodes; _k1018 = getFirstArrayKey( _a1018 ); while ( isDefined( _k1018 ) ) { node = _a1018[ _k1018 ]; if ( !nodesvisible( nearest, node ) && !nodescanpath( nearest, node ) ) { self cancelgoal( "cover" ); self cancelgoal( "enemy_patrol" ); self addgoal( node, 24, 4, "flee" ); return; } _k1018 = getNextArrayKey( _a1018, _k1018 ); } } } else if ( cover_score > -0,25 ) { if ( self hasgoal( "cover" ) ) { return; } nodes = getnodesinradiussorted( self.origin, 512, 0, 256, "Cover" ); if ( !nodes.size ) { nodes = getnodesinradiussorted( self.origin, 256, 0, 256, "Path", 8 ); } nearest = bot_nearest_node( enemy.origin ); while ( isDefined( nearest ) ) { _a1048 = nodes; _k1048 = getFirstArrayKey( _a1048 ); while ( isDefined( _k1048 ) ) { node = _a1048[ _k1048 ]; if ( !canclaimnode( node, self.team ) ) { } else if ( node.type != "Path" && !within_fov( node.origin, node.angles, enemy.origin, bot_get_fov() ) ) { } else { if ( !nodescanpath( nearest, node ) && nodesvisible( nearest, node ) ) { if ( node.type == "Cover Left" ) { right = anglesToRight( node.angles ); dir = vectorScale( right, 16 ); node = node.origin - dir; } else { if ( node.type == "Cover Right" ) { right = anglesToRight( node.angles ); dir = vectorScale( right, 16 ); node = node.origin + dir; } } self cancelgoal( "flee" ); self cancelgoal( "enemy_patrol" ); self addgoal( node, 8, 4, "cover" ); return; } } _k1048 = getNextArrayKey( _a1048, _k1048 ); } } } else if ( bot_has_shotgun() ) { self addgoal( enemy.origin, 24, 4, "cover" ); } } bot_update_attack( enemy, dot_from, dot_to, sight, aim_target ) { self allowattack( 0 ); self pressads( 0 ); if ( sight == 0 ) { return; } weapon = self getcurrentweapon(); if ( weapon == "none" ) { return; } radius = 50; if ( dot_to > 0,9 ) { self pressads( 1 ); } ads = 1; if ( bot_should_hip_fire() ) { self pressads( 0 ); ads = 0; radius = 15; } if ( isweaponscopeoverlay( weapon ) && ads ) { if ( self playerads() < 1 ) { self.bot.time_ads = getTime(); } if ( getTime() < ( self.bot.time_ads + 1000 ) ) { return; } } if ( !ads || self playerads() >= 1 ) { self allowattack( 1 ); } } bot_weapon_ammo_frac() { if ( self isreloading() || self isswitchingweapons() ) { return 0; } weapon = self getcurrentweapon(); if ( weapon == "none" ) { return 1; } total = weaponclipsize( weapon ); if ( total <= 0 ) { return 1; } current = self getweaponammoclip( weapon ); return current / total; } bot_select_weapon() { if ( !self isthrowinggrenade() || self isswitchingweapons() && self isreloading() ) { return; } if ( !self isonground() ) { return; } ent = self.bot.threat.entity; if ( !isDefined( ent ) ) { return; } primaries = self getweaponslistprimaries(); weapon = self getcurrentweapon(); stock = self getweaponammostock( weapon ); clip = self getweaponammoclip( weapon ); if ( weapon == "none" ) { return; } if ( threat_requires_rocket( ent ) || threat_is_qrdrone() ) { if ( !bot_using_launcher() ) { _a1202 = primaries; _k1202 = getFirstArrayKey( _a1202 ); while ( isDefined( _k1202 ) ) { primary = _a1202[ _k1202 ]; if ( !self getweaponammoclip( primary ) && !self getweaponammostock( primary ) ) { } else { if ( primary == "smaw_mp" || primary == "fhj18_mp" ) { self switchtoweapon( primary ); return; } } _k1202 = getNextArrayKey( _a1202, _k1202 ); } } else if ( !clip && !stock && !threat_is_qrdrone() ) { threat_ignore( ent, 5 ); } return; } else { if ( weapon == "fhj18_mp" && !target_istarget( ent ) ) { _a1225 = primaries; _k1225 = getFirstArrayKey( _a1225 ); while ( isDefined( _k1225 ) ) { primary = _a1225[ _k1225 ]; if ( primary != weapon ) { self switchtoweapon( primary ); return; } _k1225 = getNextArrayKey( _a1225, _k1225 ); } return; } } while ( !clip ) { if ( stock ) { if ( weaponhasattachment( weapon, "fastreload" ) ) { return; } } _a1247 = primaries; _k1247 = getFirstArrayKey( _a1247 ); while ( isDefined( _k1247 ) ) { primary = _a1247[ _k1247 ]; if ( primary == weapon || primary == "fhj18_mp" ) { } else { if ( self getweaponammoclip( primary ) ) { self switchtoweapon( primary ); return; } } _k1247 = getNextArrayKey( _a1247, _k1247 ); } while ( bot_using_launcher() || bot_has_lmg() ) { _a1263 = primaries; _k1263 = getFirstArrayKey( _a1263 ); while ( isDefined( _k1263 ) ) { primary = _a1263[ _k1263 ]; if ( primary == weapon || primary == "fhj18_mp" ) { } else { self switchtoweapon( primary ); return; } _k1263 = getNextArrayKey( _a1263, _k1263 ); } } } } bot_has_shotgun() { weapon = self getcurrentweapon(); if ( weapon == "none" ) { return 0; } if ( weaponisdualwield( weapon ) ) { return 1; } if ( !bot_has_weapon_class( "spread" ) ) { return bot_has_weapon_class( "pistol spread" ); } } bot_has_crossbow() { weapon = self getcurrentweapon(); return weapon == "crossbow_mp"; } bot_has_launcher() { if ( self getweaponammoclip( "smaw_mp" ) > 0 || self getweaponammostock( "smaw_mp" ) > 0 ) { return 1; } if ( self getweaponammoclip( "fhj18_mp" ) > 0 || self getweaponammostock( "fhj18_mp" ) > 0 ) { return 1; } return 0; } bot_has_melee_weapon() { weapon = self getcurrentweapon(); if ( weapon == "fhj18_mp" ) { if ( isDefined( self.bot.threat.entity ) && !target_istarget( self.bot.threat.entity ) ) { return 1; } } if ( weapon != "riotshield_mp" ) { return weapon == "knife_held_mp"; } } bot_has_pistol() { if ( !bot_has_weapon_class( "pistol" ) ) { return bot_has_weapon_class( "pistol spread" ); } } bot_has_lmg() { return bot_has_weapon_class( "mg" ); } bot_has_sniper() { return bot_has_weapon_class( "sniper" ); } bot_using_launcher() { weapon = self getcurrentweapon(); if ( weapon != "smaw_mp" && weapon != "fhj18_mp" ) { return weapon == "usrpg_mp"; } } bot_has_minigun() { weapon = self getcurrentweapon(); if ( weapon != "minigun_mp" ) { return weapon == "inventory_minigun_mp"; } } bot_has_weapon_class( class ) { if ( self isreloading() ) { return 0; } weapon = self getcurrentweapon(); if ( weapon == "none" ) { return 0; } return weaponclass( weapon ) == class; } bot_health_frac() { return self.health / self.maxhealth; } bot_should_hip_fire() { enemy = self.bot.threat.entity; weapon = self getcurrentweapon(); if ( weapon == "none" ) { return 0; } if ( weaponisdualwield( weapon ) ) { return 1; } class = weaponclass( weapon ); if ( isplayer( enemy ) && class == "spread" ) { return 1; } distsq = distancesquared( self.origin, enemy.origin ); distcheck = 0; switch( class ) { case "mg": distcheck = 250; break; case "smg": distcheck = 350; break; case "spread": distcheck = 400; break; case "pistol": distcheck = 200; break; case "rocketlauncher": distcheck = 0; break; case "rifle": default: distcheck = 300; break; } if ( isweaponscopeoverlay( weapon ) ) { distcheck = 500; } return distsq < ( distcheck * distcheck ); } bot_patrol_near_enemy( damage, attacker, direction ) { if ( threat_is_warthog( attacker ) ) { return; } if ( threat_requires_rocket( attacker ) && !self bot_has_launcher() ) { return; } if ( isDefined( attacker ) ) { self bot_lookat_entity( attacker ); } if ( maps/mp/bots/_bot::bot_get_difficulty() == "easy" ) { return; } if ( !isDefined( attacker ) ) { attacker = self maps/mp/bots/_bot::bot_get_closest_enemy( self.origin, 1 ); } if ( !isDefined( attacker ) ) { return; } if ( attacker.classname == "auto_turret" ) { self bot_turret_set_dangerous( attacker ); } node = bot_nearest_node( attacker.origin ); if ( !isDefined( node ) ) { nodes = getnodesinradiussorted( attacker.origin, 1024, 0, 512, "Path", 8 ); if ( nodes.size ) { node = nodes[ 0 ]; } } if ( isDefined( node ) ) { if ( isDefined( damage ) ) { self addgoal( node, 24, 4, "enemy_patrol" ); return; } else { self addgoal( node, 24, 2, "enemy_patrol" ); } } } bot_nearest_node( origin ) { node = getnearestnode( origin ); if ( isDefined( node ) ) { return node; } nodes = getnodesinradiussorted( origin, 256, 0, 256 ); if ( nodes.size ) { return nodes[ 0 ]; } return undefined; } bot_lookat_entity( entity ) { if ( isplayer( entity ) && entity getstance() != "prone" ) { if ( distancesquared( self.origin, entity.origin ) < 65536 ) { origin = entity getcentroid() + vectorScale( ( 0, 0, 1 ), 10 ); self lookat( origin ); return; } } offset = target_getoffset( entity ); if ( isDefined( offset ) ) { self lookat( entity.origin + offset ); } else { self lookat( entity getcentroid() ); } } bot_combat_throw_lethal( origin ) { weapons = self getweaponslist(); radius = 256; if ( self hasperk( "specialty_flakjacket" ) ) { radius *= 0,25; } if ( distancesquared( self.origin, origin ) < ( radius * radius ) ) { return 0; } _a1562 = weapons; _k1562 = getFirstArrayKey( _a1562 ); while ( isDefined( _k1562 ) ) { weapon = _a1562[ _k1562 ]; if ( self getweaponammostock( weapon ) <= 0 ) { } else { if ( weapon == "frag_grenade_mp" || weapon == "sticky_grenade_mp" ) { if ( self throwgrenade( weapon, origin ) ) { return 1; } } } _k1562 = getNextArrayKey( _a1562, _k1562 ); } return 0; } bot_combat_throw_tactical( origin ) { weapons = self getweaponslist(); if ( !self hasperk( "specialty_flashprotection" ) ) { if ( distancesquared( self.origin, origin ) < 422500 ) { return 0; } } _a1593 = weapons; _k1593 = getFirstArrayKey( _a1593 ); while ( isDefined( _k1593 ) ) { weapon = _a1593[ _k1593 ]; if ( self getweaponammostock( weapon ) <= 0 ) { } else { if ( weapon == "flash_grenade_mp" || weapon == "concussion_grenade_mp" ) { if ( self throwgrenade( weapon, origin ) ) { return 1; } } } _k1593 = getNextArrayKey( _a1593, _k1593 ); } return 0; } bot_combat_throw_smoke( origin ) { if ( self getweaponammostock( "willy_pete_mp" ) <= 0 ) { return 0; } time = getTime(); _a1621 = level.players; _k1621 = getFirstArrayKey( _a1621 ); while ( isDefined( _k1621 ) ) { player = _a1621[ _k1621 ]; if ( !isDefined( player.smokegrenadetime ) ) { } else if ( ( time - player.smokegrenadetime ) > 12000 ) { } else { if ( distancesquared( origin, player.smokegrenadeposition ) < 65536 ) { return 0; } } _k1621 = getNextArrayKey( _a1621, _k1621 ); } return self throwgrenade( "willy_pete_mp", origin ); } bot_combat_throw_emp( origin ) { if ( self getweaponammostock( "emp_mp" ) <= 0 ) { return 0; } return self throwgrenade( "emp_mp", origin ); } bot_combat_throw_proximity( origin ) { _a1654 = level.missileentities; _k1654 = getFirstArrayKey( _a1654 ); while ( isDefined( _k1654 ) ) { missile = _a1654[ _k1654 ]; if ( isDefined( missile ) && distancesquared( missile.origin, origin ) < 65536 ) { return 0; } _k1654 = getNextArrayKey( _a1654, _k1654 ); } return self throwgrenade( "proximity_grenade_mp", origin ); } bot_combat_tactical_insertion( origin ) { _a1667 = level.missileentities; _k1667 = getFirstArrayKey( _a1667 ); while ( isDefined( _k1667 ) ) { missile = _a1667[ _k1667 ]; if ( isDefined( missile ) && distancesquared( missile.origin, origin ) < 65536 ) { return 0; } _k1667 = getNextArrayKey( _a1667, _k1667 ); } return self throwgrenade( "tactical_insertion_mp", origin ); } bot_combat_toss_flash( origin ) { if ( maps/mp/bots/_bot::bot_get_difficulty() == "easy" ) { return 0; } if ( self getweaponammostock( "sensor_grenade_mp" ) <= 0 && self getweaponammostock( "proximity_grenade_mp" ) <= 0 && self getweaponammostock( "trophy_system_mp" ) <= 0 ) { return 0; } _a1690 = level.missileentities; _k1690 = getFirstArrayKey( _a1690 ); while ( isDefined( _k1690 ) ) { missile = _a1690[ _k1690 ]; if ( isDefined( missile ) && distancesquared( missile.origin, origin ) < 65536 ) { return 0; } _k1690 = getNextArrayKey( _a1690, _k1690 ); } self pressattackbutton( 2 ); return 1; } bot_combat_toss_frag( origin ) { if ( maps/mp/bots/_bot::bot_get_difficulty() == "easy" ) { return 0; } if ( self getweaponammostock( "bouncingbetty_mp" ) <= 0 && self getweaponammostock( "claymore_mp" ) <= 0 && self getweaponammostock( "satchel_charge_mp" ) <= 0 ) { return 0; } _a1714 = level.missileentities; _k1714 = getFirstArrayKey( _a1714 ); while ( isDefined( _k1714 ) ) { missile = _a1714[ _k1714 ]; if ( isDefined( missile ) && distancesquared( missile.origin, origin ) < 16384 ) { return 0; } _k1714 = getNextArrayKey( _a1714, _k1714 ); } self pressattackbutton( 1 ); return 1; } bot_shotgun_think() { if ( self isthrowinggrenade() || self isswitchingweapons() ) { return; } enemy = self.bot.threat.entity; weapon = self getcurrentweapon(); self allowattack( 0 ); distsq = distancesquared( enemy.origin, self.origin ); if ( threat_is_turret() ) { goal = enemy turret_get_attack_node(); if ( isDefined( goal ) ) { self cancelgoal( "enemy_patrol" ); self addgoal( goal, 24, 4, "cover" ); } if ( weapon != "none" && !weaponisdualwield( weapon ) && distsq < 65536 ) { self pressads( 1 ); } } else { if ( self getweaponammoclip( weapon ) && distsq < 90000 ) { self cancelgoal( "enemy_patrol" ); self addgoal( self.origin, 24, 4, "cover" ); } } dot = self bot_dot_product( self.bot.threat.aim_target ); if ( distsq < 250000 && dot > 0,98 ) { self allowattack( 1 ); return; } if ( maps/mp/bots/_bot::bot_get_difficulty() == "easy" ) { return; } if ( self threat_is_player() ) { dot = enemy bot_dot_product( self.origin ); if ( dot < 0,9 ) { return; } } else { return; } primaries = self getweaponslistprimaries(); weapon = self getcurrentweapon(); _a1793 = primaries; _k1793 = getFirstArrayKey( _a1793 ); while ( isDefined( _k1793 ) ) { primary = _a1793[ _k1793 ]; if ( primary == weapon ) { } else if ( !self getweaponammoclip( primary ) ) { } else if ( maps/mp/gametypes/_weapon_utils::isguidedrocketlauncherweapon( primary ) ) { } else class = weaponclass( primary ); if ( class != "spread" && class != "pistol spread" || class == "melee" && class == "item" ) { } else { if ( self switchtoweapon( primary ) ) { return; } } _k1793 = getNextArrayKey( _a1793, _k1793 ); } if ( self getweaponammostock( "willy_pete_mp" ) > 0 ) { self pressattackbutton( 2 ); return; } } bot_turret_set_dangerous( turret ) { if ( !level.teambased ) { return; } if ( isDefined( turret.dead ) || turret.dead && isDefined( turret.carried ) && turret.carried ) { return; } if ( isDefined( turret.turret_active ) && !turret.turret_active ) { return; } if ( turret.dangerous_nodes.size ) { return; } nearest = bot_turret_nearest_node( turret ); if ( !isDefined( nearest ) ) { return; } forward = anglesToForward( turret.angles ); if ( turret.turrettype == "sentry" ) { nodes = getvisiblenodes( nearest ); _a1868 = nodes; _k1868 = getFirstArrayKey( _a1868 ); while ( isDefined( _k1868 ) ) { node = _a1868[ _k1868 ]; dir = vectornormalize( node.origin - turret.origin ); dot = vectordot( forward, dir ); if ( dot >= 0,5 ) { turret turret_mark_node_dangerous( node ); } _k1868 = getNextArrayKey( _a1868, _k1868 ); } } else while ( turret.turrettype == "microwave" ) { nodes = getnodesinradius( turret.origin, level.microwave_radius, 0 ); _a1883 = nodes; _k1883 = getFirstArrayKey( _a1883 ); while ( isDefined( _k1883 ) ) { node = _a1883[ _k1883 ]; if ( !nodesvisible( nearest, node ) ) { } else { dir = vectornormalize( node.origin - turret.origin ); dot = vectordot( forward, dir ); if ( dot >= level.microwave_turret_cone_dot ) { turret turret_mark_node_dangerous( node ); } } _k1883 = getNextArrayKey( _a1883, _k1883 ); } } } bot_turret_nearest_node( turret ) { nodes = getnodesinradiussorted( turret.origin, 256, 0 ); forward = anglesToForward( turret.angles ); _a1906 = nodes; _k1906 = getFirstArrayKey( _a1906 ); while ( isDefined( _k1906 ) ) { node = _a1906[ _k1906 ]; dir = vectornormalize( node.origin - turret.origin ); dot = vectordot( forward, dir ); if ( dot > 0,5 ) { return node; } _k1906 = getNextArrayKey( _a1906, _k1906 ); } if ( nodes.size ) { return nodes[ 0 ]; } return undefined; } turret_mark_node_dangerous( node ) { _a1927 = level.teams; _k1927 = getFirstArrayKey( _a1927 ); while ( isDefined( _k1927 ) ) { team = _a1927[ _k1927 ]; if ( team == self.owner.team ) { } else { node setdangerous( team, 1 ); } _k1927 = getNextArrayKey( _a1927, _k1927 ); } self.dangerous_nodes[ self.dangerous_nodes.size ] = node; } turret_get_attack_node() { nearest = bot_nearest_node( self.origin ); if ( !isDefined( nearest ) ) { return undefined; } nodes = getnodesinradiussorted( self.origin, 512, 64 ); forward = anglesToForward( self.angles ); _a1952 = nodes; _k1952 = getFirstArrayKey( _a1952 ); while ( isDefined( _k1952 ) ) { node = _a1952[ _k1952 ]; if ( !nodesvisible( node, nearest ) ) { } else { dir = vectornormalize( node.origin - self.origin ); dot = vectordot( forward, dir ); if ( dot < 0,5 ) { return node; } } _k1952 = getNextArrayKey( _a1952, _k1952 ); } return undefined; } bot_riotshield_think( enemy ) { dot = enemy bot_dot_product( self.origin ); if ( !bot_has_crossbow() && !bot_using_launcher() && enemy getstance() != "stand" ) { if ( dot > 0,8 ) { self allowattack( 0 ); } } forward = anglesToForward( enemy.angles ); origin = enemy.origin + ( forward * randomintrange( 256, 512 ) ); if ( self bot_combat_throw_lethal( origin ) ) { return; } if ( self bot_combat_throw_tactical( origin ) ) { return; } if ( self throwgrenade( "proximity_grenade_mp", origin ) ) { return; } if ( self atgoal( "cover" ) ) { self.bot.threat.update_riotshield = 0; } if ( getTime() > self.bot.threat.update_riotshield ) { self thread bot_riotshield_dangerous_think( enemy ); self.bot.threat.update_riotshield = getTime() + randomintrange( 5000, 7500 ); } } bot_riotshield_dangerous_think( enemy, goal ) { nearest = bot_nearest_node( enemy.origin ); if ( !isDefined( nearest ) ) { threat_ignore( enemy, 10 ); return; } nodes = getnodesinradius( enemy.origin, 768, 0 ); if ( !nodes.size ) { threat_ignore( enemy, 10 ); return; } nodes = array_randomize( nodes ); forward = anglesToForward( enemy.angles ); _a2037 = nodes; _k2037 = getFirstArrayKey( _a2037 ); while ( isDefined( _k2037 ) ) { node = _a2037[ _k2037 ]; if ( !nodesvisible( node, nearest ) ) { } else { dir = vectornormalize( node.origin - enemy.origin ); dot = vectordot( forward, dir ); if ( dot < 0 ) { if ( distancesquared( self.origin, enemy.origin ) < 262144 ) { self addgoal( node, 24, 4, "cover" ); } else { self addgoal( node, 24, 3, "cover" ); } break; } } else { _k2037 = getNextArrayKey( _a2037, _k2037 ); } } if ( !level.teambased ) { return; } nodes = getnodesinradius( enemy.origin, 512, 0 ); _a2069 = nodes; _k2069 = getFirstArrayKey( _a2069 ); while ( isDefined( _k2069 ) ) { node = _a2069[ _k2069 ]; dir = vectornormalize( node.origin - enemy.origin ); dot = vectordot( forward, dir ); if ( dot >= 0,5 ) { node setdangerous( self.team, 1 ); } _k2069 = getNextArrayKey( _a2069, _k2069 ); } enemy wait_endon( 5, "death" ); _a2082 = nodes; _k2082 = getFirstArrayKey( _a2082 ); while ( isDefined( _k2082 ) ) { node = _a2082[ _k2082 ]; node setdangerous( self.team, 0 ); _k2082 = getNextArrayKey( _a2082, _k2082 ); } }