mirror of
https://github.com/InfinityLoader/IL-GSC.git
synced 2025-06-07 17:17:50 -05:00
1966 lines
33 KiB
Plaintext
1966 lines
33 KiB
Plaintext
/*******************************************************************
|
|
* Decompiled By: Bog
|
|
* Decompiled File: maps\mp\bots\_bot_combat.gsc
|
|
* Game: Call of Duty: Black Ops 2
|
|
* Platform: PC
|
|
* Function Count: 65
|
|
* Decompile Time: 16 ms
|
|
* Timestamp: 10/28/2023 12:10:25 AM
|
|
*******************************************************************/
|
|
|
|
#include common_scripts/utility;
|
|
#include maps/mp/_utility;
|
|
#include maps/mp/bots/_bot;
|
|
#include maps/mp/gametypes/_weapon_utils;
|
|
|
|
//Function Number: 1
|
|
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(#"D3EB879"))
|
|
{
|
|
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);
|
|
}
|
|
else if(threat_requires_rocket(ent))
|
|
{
|
|
self cancelgoal("enemy_patrol");
|
|
self addgoal(self.origin,24,4,"cover");
|
|
}
|
|
|
|
if(difficulty == "easy")
|
|
{
|
|
wait(0.5);
|
|
continue;
|
|
}
|
|
|
|
if(difficulty == "normal")
|
|
{
|
|
wait(0.25);
|
|
continue;
|
|
}
|
|
|
|
if(difficulty == "hard")
|
|
{
|
|
wait(0.1);
|
|
continue;
|
|
}
|
|
|
|
wait(0.05);
|
|
}
|
|
}
|
|
|
|
//Function Number: 2
|
|
bot_can_do_combat()
|
|
{
|
|
if(self ismantling() || self isonladder())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//Function Number: 3
|
|
threat_dead()
|
|
{
|
|
if(bot_has_enemy())
|
|
{
|
|
ent = self.bot.threat.entity;
|
|
if(threat_is_turret())
|
|
{
|
|
return IsDefined(ent.dead) && ent.dead;
|
|
}
|
|
else if(threat_is_qrdrone())
|
|
{
|
|
return IsDefined(ent.crash_accel) && ent.crash_accel;
|
|
}
|
|
|
|
return !isalive(ent);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//Function Number: 4
|
|
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;
|
|
}
|
|
|
|
//Function Number: 5
|
|
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 = 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");
|
|
}
|
|
|
|
//Function Number: 6
|
|
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();
|
|
}
|
|
|
|
//Function Number: 7
|
|
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();
|
|
ads = !bot_should_hip_fire() && 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 = 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_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();
|
|
}
|
|
}
|
|
|
|
//Function Number: 8
|
|
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);
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
|
|
//Function Number: 9
|
|
bot_get_fov()
|
|
{
|
|
weapon = self getcurrentweapon();
|
|
reduction = 1;
|
|
if(weapon != "none" && isweaponscopeoverlay(weapon) && self playerads() >= 1)
|
|
{
|
|
reduction = 0.25;
|
|
}
|
|
|
|
return self.bot.fov * reduction;
|
|
}
|
|
|
|
//Function Number: 10
|
|
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;
|
|
}
|
|
|
|
//Function Number: 11
|
|
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;
|
|
}
|
|
|
|
//Function Number: 12
|
|
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;
|
|
}
|
|
|
|
//Function Number: 13
|
|
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;
|
|
}
|
|
|
|
//Function Number: 14
|
|
bot_update_lookat(origin,frac)
|
|
{
|
|
angles = VectorToAngles(origin - self.origin);
|
|
right = AnglesToRight(angles);
|
|
error = bot_get_aim_error() * 1 - frac;
|
|
if(cointoss())
|
|
{
|
|
error = error * -1;
|
|
}
|
|
|
|
height = origin[2] - self.bot.threat.entity.origin[2];
|
|
height = height * 1 - frac;
|
|
if(cointoss())
|
|
{
|
|
height = height * -1;
|
|
}
|
|
|
|
end = origin + right * error;
|
|
end = end + (0,0,height);
|
|
red = 1 - frac;
|
|
green = frac;
|
|
self lookat(end);
|
|
}
|
|
|
|
//Function Number: 15
|
|
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;
|
|
}
|
|
}
|
|
|
|
//Function Number: 16
|
|
bot_dot_product(origin)
|
|
{
|
|
angles = self getplayerangles();
|
|
forward = AnglesToForward(angles);
|
|
delta = origin - self getplayercamerapos();
|
|
delta = vectornormalize(delta);
|
|
dot = vectordot(forward,delta);
|
|
return dot;
|
|
}
|
|
|
|
//Function Number: 17
|
|
bot_has_enemy()
|
|
{
|
|
return IsDefined(self.bot.threat.entity);
|
|
}
|
|
|
|
//Function Number: 18
|
|
threat_is_player()
|
|
{
|
|
ent = self.bot.threat.entity;
|
|
return IsDefined(ent) && isplayer(ent);
|
|
}
|
|
|
|
//Function Number: 19
|
|
threat_is_dog()
|
|
{
|
|
ent = self.bot.threat.entity;
|
|
return IsDefined(ent) && isai(ent);
|
|
}
|
|
|
|
//Function Number: 20
|
|
threat_is_turret()
|
|
{
|
|
ent = self.bot.threat.entity;
|
|
return IsDefined(ent) && ent.classname == "auto_turret";
|
|
}
|
|
|
|
//Function Number: 21
|
|
threat_is_ai_tank()
|
|
{
|
|
ent = self.bot.threat.entity;
|
|
return IsDefined(ent) && IsDefined(ent.targetname) && ent.targetname == "talon";
|
|
}
|
|
|
|
//Function Number: 22
|
|
threat_is_qrdrone(ent)
|
|
{
|
|
if(!(IsDefined(ent)))
|
|
{
|
|
ent = self.bot.threat.entity;
|
|
}
|
|
|
|
return IsDefined(ent) && IsDefined(ent.helitype) && ent.helitype == "qrdrone";
|
|
}
|
|
|
|
//Function Number: 23
|
|
threat_using_riotshield()
|
|
{
|
|
if(threat_is_player())
|
|
{
|
|
weapon = self.bot.threat.entity getcurrentweapon();
|
|
return weapon == "riotshield_mp";
|
|
}
|
|
}
|
|
|
|
//Function Number: 24
|
|
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;
|
|
}
|
|
|
|
return IsDefined(ent.name) && isweaponequipment(ent.name);
|
|
}
|
|
|
|
//Function Number: 25
|
|
bot_clear_enemy()
|
|
{
|
|
self clearlookat();
|
|
self.bot.threat.entity = undefined;
|
|
}
|
|
|
|
//Function Number: 26
|
|
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);
|
|
foreach(enemy in enemies)
|
|
{
|
|
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))
|
|
{
|
|
}
|
|
else if(threat_requires_rocket(enemy))
|
|
{
|
|
if(!(bot_has_launcher()))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
origin = self getplayercamerapos();
|
|
angles = VectorToAngles(enemy.origin - origin);
|
|
if(angles[0] < 290)
|
|
{
|
|
threat_ignore(enemy,3.5);
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//Function Number: 27
|
|
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;
|
|
}
|
|
}
|
|
|
|
//Function Number: 28
|
|
threat_is_warthog(enemy)
|
|
{
|
|
if(!IsDefined(enemy) || isplayer(enemy))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if(enemy.classname == "script_vehicle" && enemy.vehicleclass == "plane")
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
//Function Number: 29
|
|
threat_should_ignore(entity)
|
|
{
|
|
ignore_time = self.bot.ignore_entity[entity getentitynumber()];
|
|
if(IsDefined(ignore_time))
|
|
{
|
|
if(GetTime() < ignore_time)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Function Number: 30
|
|
threat_ignore(entity,secs)
|
|
{
|
|
self.bot.ignore_entity[entity getentitynumber()] = GetTime() + secs * 1000;
|
|
}
|
|
|
|
//Function Number: 31
|
|
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 5 + VectorScale((0,0,1));
|
|
}
|
|
}
|
|
|
|
torso = prediction + (0,0,height / 1.6);
|
|
return torso;
|
|
}
|
|
|
|
//Function Number: 32
|
|
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 = cover_score + 1;
|
|
}
|
|
|
|
if(cover_score > 0.25)
|
|
{
|
|
nodes = getnodesinradiussorted(self.origin,1024,256,512,"Path",8);
|
|
nearest = bot_nearest_node(enemy.origin);
|
|
if(IsDefined(nearest) && !self hasgoal("flee"))
|
|
{
|
|
foreach(node in nodes)
|
|
{
|
|
if(!nodesvisible(nearest,node) && !nodescanpath(nearest,node))
|
|
{
|
|
self cancelgoal("cover");
|
|
self cancelgoal("enemy_patrol");
|
|
self addgoal(node,24,4,"flee");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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);
|
|
if(IsDefined(nearest))
|
|
{
|
|
foreach(node in nodes)
|
|
{
|
|
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);
|
|
node = node.origin - dir;
|
|
}
|
|
else if(node.type == "Cover Right")
|
|
{
|
|
right = AnglesToRight(node.angles);
|
|
dir = VectorScale(right);
|
|
node = node.origin + dir;
|
|
}
|
|
|
|
self cancelgoal("flee");
|
|
self cancelgoal("enemy_patrol");
|
|
self addgoal(node,8,4,"cover");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(bot_has_shotgun())
|
|
{
|
|
self addgoal(enemy.origin,24,4,"cover");
|
|
}
|
|
}
|
|
|
|
//Function Number: 33
|
|
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);
|
|
}
|
|
}
|
|
|
|
//Function Number: 34
|
|
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;
|
|
}
|
|
|
|
//Function Number: 35
|
|
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()))
|
|
{
|
|
foreach(primary in primaries)
|
|
{
|
|
if(!self getweaponammoclip(primary) && !self getweaponammostock(primary))
|
|
{
|
|
}
|
|
else if(primary == "smaw_mp" || primary == "fhj18_mp")
|
|
{
|
|
self switchtoweapon(primary);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else if(!clip && !stock && !threat_is_qrdrone())
|
|
{
|
|
threat_ignore(ent,5);
|
|
}
|
|
|
|
return;
|
|
}
|
|
else if(weapon == "fhj18_mp" && !target_istarget(ent))
|
|
{
|
|
foreach(primary in primaries)
|
|
{
|
|
if(primary != weapon)
|
|
{
|
|
self switchtoweapon(primary);
|
|
return;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if(!(clip))
|
|
{
|
|
if(stock)
|
|
{
|
|
if(weaponhasattachment(weapon,"fastreload"))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
foreach(primary in primaries)
|
|
{
|
|
if(primary == weapon || primary == "fhj18_mp")
|
|
{
|
|
}
|
|
else if(self getweaponammoclip(primary))
|
|
{
|
|
self switchtoweapon(primary);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(bot_using_launcher() || bot_has_lmg())
|
|
{
|
|
foreach(primary in primaries)
|
|
{
|
|
if(primary == weapon || primary == "fhj18_mp")
|
|
{
|
|
}
|
|
else
|
|
{
|
|
self switchtoweapon(primary);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Function Number: 36
|
|
bot_has_shotgun()
|
|
{
|
|
weapon = self getcurrentweapon();
|
|
if(weapon == "none")
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if(weaponisdualwield(weapon))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return bot_has_weapon_class("spread") || bot_has_weapon_class("pistol spread");
|
|
}
|
|
|
|
//Function Number: 37
|
|
bot_has_crossbow()
|
|
{
|
|
weapon = self getcurrentweapon();
|
|
return weapon == "crossbow_mp";
|
|
}
|
|
|
|
//Function Number: 38
|
|
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;
|
|
}
|
|
}
|
|
|
|
//Function Number: 39
|
|
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;
|
|
}
|
|
}
|
|
|
|
return weapon == "riotshield_mp" || weapon == "knife_held_mp";
|
|
}
|
|
|
|
//Function Number: 40
|
|
bot_has_pistol()
|
|
{
|
|
return bot_has_weapon_class("pistol") || bot_has_weapon_class("pistol spread");
|
|
}
|
|
|
|
//Function Number: 41
|
|
bot_has_lmg()
|
|
{
|
|
return bot_has_weapon_class("mg");
|
|
}
|
|
|
|
//Function Number: 42
|
|
bot_has_sniper()
|
|
{
|
|
return bot_has_weapon_class("sniper");
|
|
}
|
|
|
|
//Function Number: 43
|
|
bot_using_launcher()
|
|
{
|
|
weapon = self getcurrentweapon();
|
|
return weapon == "smaw_mp" || weapon == "fhj18_mp" || weapon == "usrpg_mp";
|
|
}
|
|
|
|
//Function Number: 44
|
|
bot_has_minigun()
|
|
{
|
|
weapon = self getcurrentweapon();
|
|
return weapon == "minigun_mp" || weapon == "inventory_minigun_mp";
|
|
}
|
|
|
|
//Function Number: 45
|
|
bot_has_weapon_class(class)
|
|
{
|
|
if(self isreloading())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
weapon = self getcurrentweapon();
|
|
if(weapon == "none")
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return weaponclass(weapon) == class;
|
|
}
|
|
|
|
//Function Number: 46
|
|
bot_health_frac()
|
|
{
|
|
return self.health / self.maxhealth;
|
|
}
|
|
|
|
//Function Number: 47
|
|
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;
|
|
}
|
|
|
|
//Function Number: 48
|
|
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");
|
|
}
|
|
else
|
|
{
|
|
self addgoal(node,24,2,"enemy_patrol");
|
|
}
|
|
}
|
|
}
|
|
|
|
//Function Number: 49
|
|
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;
|
|
}
|
|
|
|
//Function Number: 50
|
|
bot_lookat_entity(entity)
|
|
{
|
|
if(isplayer(entity) && entity getstance() != "prone")
|
|
{
|
|
if(distancesquared(self.origin,entity.origin) < 65536)
|
|
{
|
|
origin = 10 + VectorScale((0,0,1));
|
|
self lookat(origin);
|
|
return;
|
|
}
|
|
}
|
|
|
|
offset = target_getoffset(entity);
|
|
if(IsDefined(offset))
|
|
{
|
|
self lookat(entity.origin + offset);
|
|
}
|
|
else
|
|
{
|
|
self lookat(entity getcentroid());
|
|
}
|
|
}
|
|
|
|
//Function Number: 51
|
|
bot_combat_throw_lethal(origin)
|
|
{
|
|
weapons = self getweaponslist();
|
|
radius = 256;
|
|
if(self hasperk("specialty_flakjacket"))
|
|
{
|
|
radius = radius * 0.25;
|
|
}
|
|
|
|
if(distancesquared(self.origin,origin) < radius * radius)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
foreach(weapon in weapons)
|
|
{
|
|
if(self getweaponammostock(weapon) <= 0)
|
|
{
|
|
}
|
|
else if(weapon == "frag_grenade_mp" || weapon == "sticky_grenade_mp")
|
|
{
|
|
if(self throwgrenade(weapon,origin))
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//Function Number: 52
|
|
bot_combat_throw_tactical(origin)
|
|
{
|
|
weapons = self getweaponslist();
|
|
if(!(self hasperk("specialty_flashprotection")))
|
|
{
|
|
if(distancesquared(self.origin,origin) < 422500)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
foreach(weapon in weapons)
|
|
{
|
|
if(self getweaponammostock(weapon) <= 0)
|
|
{
|
|
}
|
|
else if(weapon == "flash_grenade_mp" || weapon == "concussion_grenade_mp")
|
|
{
|
|
if(self throwgrenade(weapon,origin))
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//Function Number: 53
|
|
bot_combat_throw_smoke(origin)
|
|
{
|
|
if(self getweaponammostock("willy_pete_mp") <= 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
time = GetTime();
|
|
foreach(player in level.players)
|
|
{
|
|
if(!(IsDefined(player.smokegrenadetime)))
|
|
{
|
|
}
|
|
else if(time - player.smokegrenadetime > 12000)
|
|
{
|
|
}
|
|
else if(distancesquared(origin,player.smokegrenadeposition) < 65536)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return self throwgrenade("willy_pete_mp",origin);
|
|
}
|
|
|
|
//Function Number: 54
|
|
bot_combat_throw_emp(origin)
|
|
{
|
|
if(self getweaponammostock("emp_mp") <= 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return self throwgrenade("emp_mp",origin);
|
|
}
|
|
|
|
//Function Number: 55
|
|
bot_combat_throw_proximity(origin)
|
|
{
|
|
foreach(missile in level.missileentities)
|
|
{
|
|
if(IsDefined(missile) && distancesquared(missile.origin,origin) < 65536)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return self throwgrenade("proximity_grenade_mp",origin);
|
|
}
|
|
|
|
//Function Number: 56
|
|
bot_combat_tactical_insertion(origin)
|
|
{
|
|
foreach(missile in level.missileentities)
|
|
{
|
|
if(IsDefined(missile) && distancesquared(missile.origin,origin) < 65536)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return self throwgrenade("tactical_insertion_mp",origin);
|
|
}
|
|
|
|
//Function Number: 57
|
|
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;
|
|
}
|
|
|
|
foreach(missile in level.missileentities)
|
|
{
|
|
if(IsDefined(missile) && distancesquared(missile.origin,origin) < 65536)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
self pressattackbutton(2);
|
|
return 1;
|
|
}
|
|
|
|
//Function Number: 58
|
|
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;
|
|
}
|
|
|
|
foreach(missile in level.missileentities)
|
|
{
|
|
if(IsDefined(missile) && distancesquared(missile.origin,origin) < 16384)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
self pressattackbutton(1);
|
|
return 1;
|
|
}
|
|
|
|
//Function Number: 59
|
|
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();
|
|
foreach(primary in primaries)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(self getweaponammostock("willy_pete_mp") > 0)
|
|
{
|
|
self pressattackbutton(2);
|
|
}
|
|
}
|
|
|
|
//Function Number: 60
|
|
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);
|
|
foreach(node in nodes)
|
|
{
|
|
dir = vectornormalize(node.origin - turret.origin);
|
|
dot = vectordot(forward,dir);
|
|
if(dot >= 0.5)
|
|
{
|
|
turret turret_mark_node_dangerous(node);
|
|
}
|
|
}
|
|
}
|
|
else if(turret.turrettype == "microwave")
|
|
{
|
|
nodes = getnodesinradius(turret.origin,level.microwave_radius,0);
|
|
foreach(node in nodes)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Function Number: 61
|
|
bot_turret_nearest_node(turret)
|
|
{
|
|
nodes = getnodesinradiussorted(turret.origin,256,0);
|
|
forward = AnglesToForward(turret.angles);
|
|
foreach(node in nodes)
|
|
{
|
|
dir = vectornormalize(node.origin - turret.origin);
|
|
dot = vectordot(forward,dir);
|
|
if(dot > 0.5)
|
|
{
|
|
return node;
|
|
}
|
|
}
|
|
|
|
if(nodes.size)
|
|
{
|
|
return nodes[0];
|
|
}
|
|
}
|
|
|
|
//Function Number: 62
|
|
turret_mark_node_dangerous(node)
|
|
{
|
|
foreach(team in level.teams)
|
|
{
|
|
if(team == self.owner.team)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
node setdangerous(team,1);
|
|
}
|
|
}
|
|
|
|
self.dangerous_nodes[self.dangerous_nodes.size] = node;
|
|
}
|
|
|
|
//Function Number: 63
|
|
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);
|
|
foreach(node in nodes)
|
|
{
|
|
if(!(nodesvisible(node,nearest)))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
dir = vectornormalize(node.origin - self.origin);
|
|
dot = vectordot(forward,dir);
|
|
if(dot < 0.5)
|
|
{
|
|
return node;
|
|
}
|
|
}
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
//Function Number: 64
|
|
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);
|
|
}
|
|
}
|
|
|
|
//Function Number: 65
|
|
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);
|
|
foreach(node in nodes)
|
|
{
|
|
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");
|
|
continue;
|
|
}
|
|
|
|
self addgoal(node,24,3,"cover");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!(level.teambased))
|
|
{
|
|
return;
|
|
}
|
|
|
|
nodes = getnodesinradius(enemy.origin,512,0);
|
|
foreach(node in nodes)
|
|
{
|
|
dir = vectornormalize(node.origin - enemy.origin);
|
|
dot = vectordot(forward,dir);
|
|
if(dot >= 0.5)
|
|
{
|
|
node setdangerous(self.team,1);
|
|
}
|
|
}
|
|
|
|
enemy wait_endon(5,"death");
|
|
foreach(node in nodes)
|
|
{
|
|
node setdangerous(self.team,0);
|
|
}
|
|
} |