64 this.havocbot_role(
this);
77 if(it.origin.z < this.origin.z)
80 if(it.origin.z - this.origin.z - this.view_ofs.z > 100)
83 if (pointcontents(it.origin + it.maxs +
'0 0 1') != CONTENT_EMPTY)
86 traceline(this.origin + this.view_ofs, ((it.absmin + it.absmax) * 0.5), true, this);
88 if(trace_fraction < 1)
91 if(!newgoal || vlen2(it.origin - this.origin) < vlen2(newgoal.origin - this.origin))
126 if(this.(weaponentity).
m_weapon != WEP_Null || slot == 0)
140 if(
STAT(WEAPONS,
this))
153 if(w == WEP_Null && slot != 0)
155 w.
wr_aim(w,
this, weaponentity);
157 this.(weaponentity).
lastfiredweapon = this.(weaponentity).m_weapon.m_id;
164 bot_aimdir(
this, this.
enemy.origin +
this.enemy.view_ofs -
this.origin -
this.view_ofs, 0);
190 if(this.(weaponentity).
m_weapon == WEP_Null && slot != 0)
196 CS(
this).impulse = IMP_weapon_reload.impulse;
204 if((
STAT(WEAPONS,
this) & (it.m_wepset)) && (it.spawnflags &
WEP_FLAG_RELOADABLE) && (
this.(weaponentity).weapon_load[it.m_id] < it.reloading_ammo))
217 bool can_run =
false;
225 while (deviation.y < -180) deviation.y = deviation.y + 360;
226 while (deviation.y > 180) deviation.y = deviation.y - 360;
233 float jump_distance = 52.661 + 0.606 * vel;
234 jump_distance += this.
origin.z - gco.z;
245 while (deviation.y < -180) deviation.y = deviation.y + 360;
246 while (deviation.y > 180) deviation.y = deviation.y - 360;
294 if (keyboard.x > trigger)
300 else if (keyboard.x < -trigger && sk > 1.5)
315 if (keyboard.y > trigger)
317 else if (keyboard.y < -trigger)
322 if (keyboard.z > trigger)
324 else if (keyboard.z < -trigger)
330 if (keyboard ==
'0 0 0')
340 CS(
this).movement =
CS(
this).movement + (keyboard -
CS(
this).movement) * blend;
351 if(distance_time < 0)
352 distance_time = -distance_time;
357 else if (
time - distance_time > 0.5)
373 float selected_dist2 = 0;
377 float dist2 = vlen2(this.origin - it.origin);
378 if (dist2 < 600 ** 2 && dist2 > selected_dist2)
381 selected_dist2 = vlen2(this.origin - selected.origin);
403 vector dst_down = dst_ahead -
'0 0 3000';
413 traceline(dst_ahead , dst_down,
true,
NULL);
433 tracebox(dst_ahead, this.
mins, this.
maxs, dst_down,
true,
this);
451 float dodge_enemy_factor = 1;
457 CS(
this).movement =
'0 0 0';
493 if(d < db || d < 500)
496 if (vel2 > (maxspeed * 0.3) ** 2)
544 if(it.wpflags & WAYPOINTFLAG_TELEPORT)
545 if(it.origin.z < this.origin.z - 100 && vdist(vec2(it.origin - this.origin), <, 100))
548 traceline(this.origin + this.view_ofs, ((it.absmin + it.absmax) * 0.5), true, this);
550 if(trace_fraction < 1)
553 if(!newgoal || ((random() < 0.8) && vlen2(it.origin - this.origin) > vlen2(newgoal.origin - this.origin)))
597 if(this.
velocity.z > 0 &&
this.origin.z -
this.lastteleport_origin.z > (
this.maxs.z -
this.mins.z) * 0.5)
600 if(
vdist(velxy, <, maxspeed * 0.2))
602 LOG_TRACE(
"Warning: ", this.
netname,
" got stuck on a jumppad (velocity in xy is ",
vtos(velxy),
"), trying to get out of it now");
619 #define ROCKETJUMP_DAMAGE() WEP_CVAR(WEP_DEVASTATOR, damage) * 0.8 \
620 * ((StatusEffects_active(STATUSEFFECT_Strength, this)) ? autocvar_g_balance_powerup_strength_selfdamage : 1) \
621 * ((StatusEffects_active(STATUSEFFECT_Shield, this)) ? autocvar_g_balance_powerup_invincible_takedamage : 1)
625 int action_for_trigger_hurt = 0;
627 action_for_trigger_hurt = 1;
632 action_for_trigger_hurt = 2;
635 action_for_trigger_hurt = 3;
637 if (action_for_trigger_hurt)
641 action_for_trigger_hurt = 0;
644 if(action_for_trigger_hurt == 1)
663 float xyspeed = xyvelocity *
dir;
665 if(xyspeed < (maxspeed / 2))
682 else if(action_for_trigger_hurt == 2)
690 if(this.(weaponentity).
m_weapon == WEP_Null && slot != 0)
695 CS(
this).movement_x = maxspeed;
716 else if(action_for_trigger_hurt == 3)
719 CS(
this).movement_x = maxspeed;
735 CS(
this).movement.z = v *
v_up;
743 bool locked_goal =
false;
760 this.
goalentity.bot_pickup_respawning =
false;
765 this.
goalentity.bot_pickup_respawning =
false;
793 bool goalcurrent_can_be_removed =
false;
799 goalcurrent_can_be_removed =
true;
807 if (
vdist(it.origin -
this.goalcurrent.death_origin, <, 50))
847 if (goalcurrent_can_be_removed)
859 if (old_goal.item_group &&
this.item_group != old_goal.item_group)
885 bool bunnyhop_forbidden =
false;
897 || (
this.absmin.z > destorg.z && destorg.x ==
this.origin.x && destorg.y ==
this.origin.y))
899 bunnyhop_forbidden =
true;
901 if(destorg.z >
this.origin.z)
906 diff = destorg - this.
origin;
912 destorg = this.origin;
913 diff =
dir =
'0 0 0';
917 if (
vdist(diff, <, 80))
920 destorg = this.origin;
921 diff =
dir =
'0 0 0';
929 diff = destorg - this.origin;
936 bool danger_detected =
false;
937 vector do_break =
'0 0 0';
952 else if(destorg.z >
this.origin.z)
965 if (destorg.z >
this.origin.z)
979 vector deviation =
'0 0 0';
981 if (current_speed < maxspeed * 0.2)
982 current_speed = maxspeed * 0.2;
986 while (deviation.y < -180) deviation.y += 360;
987 while (deviation.y > 180) deviation.y -= 360;
989 float turning =
false;
991 offset =
max(32, current_speed *
cos(deviation.y *
DEG2RAD) * 0.3) * flatdir;
992 vector actual_destorg = this.origin + offset;
996 &&
fabs(deviation.y) > 20 && current_speed > maxspeed * 0.4
1022 actual_destorg.x = destorg.x;
1023 actual_destorg.y = destorg.y;
1027 else if (
vdist(flat_diff, <, 32) && diff.z < -16)
1029 actual_destorg.x = destorg.x;
1030 actual_destorg.y = destorg.y;
1036 float dist =
vlen(
vec2(this.origin + offset - destorg));
1039 if (dist ** 2 >
vlen2(
vec2(next_goal_org - destorg)))
1040 actual_destorg = next_goal_org;
1042 actual_destorg =
vec2(destorg) + dist * next_dir;
1043 actual_destorg.z = this.origin.z;
1047 LABEL(jumpobstacle_check);
1048 dir = flatdir =
normalize(actual_destorg - this.origin);
1050 bool jump_forbidden =
false;
1051 if (!turning &&
fabs(deviation.y) > 50)
1052 jump_forbidden =
true;
1057 jump_forbidden =
true;
1060 if (!jump_forbidden)
1062 tracebox(this.origin, this.
mins, this.
maxs, actual_destorg,
false,
this);
1070 if (turning &&
fabs(deviation.y) > 5)
1073 actual_destorg = destorg;
1076 goto jumpobstacle_check;
1082 tracebox(this.origin + jump_height, this.
mins, this.
maxs, actual_destorg + jump_height,
false,
this);
1091 tracebox(this.origin + jump_height, this.
mins, this.
maxs, actual_destorg + jump_height,
false,
this);
1131 && current_speed > maxspeed * 0.9 &&
fabs(deviation.y) > 70)
1140 bool unreachable =
false;
1143 danger_detected =
true;
1152 danger_detected =
true;
1167 &&
vdist(flat_diff, <, 250) && this.origin.z - destorg.z > 120
1171 traceline(this.origin, this.origin -
'0 0 200',
true,
this);
1189 if (dodge.z > 0 &&
this.bot_moveskill == 0)
1193 traceline(this.origin, (this.
enemy.absmin +
this.enemy.absmax) * 0.5,
true,
NULL);
1207 float ladder_zdir = 0;
1210 if(this.
goalcurrent.origin.z +
this.goalcurrent.mins.z >
this.origin.z +
this.mins.z)
1212 if(this.origin.z +
this.mins.z <
this.ladder_entity.origin.z +
this.ladder_entity.maxs.z)
1217 if(this.origin.z +
this.mins.z >
this.ladder_entity.origin.z +
this.ladder_entity.mins.z)
1223 dir.z = ladder_zdir * 4;
1225 dir.z = ladder_zdir * 2;
1249 vector evadedanger =
'0 0 0';
1252 dir *= dodge_enemy_factor;
1259 if (
vdist(evadedanger, >, 20))
1261 if (
vdist(evadedanger, >, 40))
1262 do_break =
normalize(this.velocity) * -1;
1267 evadedanger =
'0 0 0';
1278 CS(
this).movement_z =
dir *
v_up * maxspeed;
1386 bool scan_transparent =
false;
1387 bool scan_secondary_targets =
false;
1388 bool have_secondary_targets =
false;
1391 scan_secondary_targets =
false;
1395 if(!scan_secondary_targets)
1397 if(it.classname ==
"misc_breakablemodel")
1399 have_secondary_targets = true;
1403 else if(it.classname !=
"misc_breakablemodel")
1406 vector v = (it.absmin + it.absmax) * 0.5;
1407 float distance =
vlen2(v - eye);
1416 float rating =
bound(50,
health + armor, 250) * distance;
1417 if (!
best || (rating < bestrating))
1419 traceline(eye, v,
true,
this);
1423 bestrating = rating;
1432 traceline(eye, v,
true,
this);
1436 bestrating = distance;
1442 if(!
best && have_secondary_targets && !scan_secondary_targets)
1444 scan_secondary_targets =
true;
1455 if(scan_transparent)
1461 scan_transparent =
true;
1469 if(
best &&
best.classname ==
"misc_breakablemodel")
1482 if (this.(weaponentity).
weapon_load[new_weapon] < 0)
1487 if(it.wr_checkammo1(it,
this, weaponentity) + it.wr_checkammo2(it,
this, weaponentity))
1527 if (this.(weaponentity).
m_weapon == WEP_Null)
1544 float af = ((this.weaponentity.m_weapon == WEP_Null) ? 0 :
ATTACK_FINISHED(
this, weaponentity));
1554 if(this.(weaponentity).
m_weapon.m_id ==
this.(weaponentity).lastfiredweapon)
1622 else if (this.
enemy)
1625 if (!this.
enemy.waterlevel)
1650 LOG_TRACE(
"Error: ", this.
netname,
" trying to walk to a non existent personal waypoint");
1733 LOG_TRACE(
"Error: Can't spawn personal waypoint at ",
vtos(pos));
1784 float danger, bestdanger, vl, d;
1791 if (head.owner !=
this)
1793 vl =
vlen(head.velocity);
1797 v = this.
origin - head.origin;
1799 if (d > (0 - head.bot_dodgerating))
1800 if (d < (vl * 0.2 + head.bot_dodgerating))
1804 v = v - (n * (v * n));
1805 danger = head.bot_dodgerating -
vlen(v);
1806 if (bestdanger < danger)
1808 bestdanger = danger;
1816 danger = head.bot_dodgerating -
vlen(head.origin -
this.origin);
1817 if (bestdanger < danger)
1819 bestdanger = danger;
void bot_aimdir(entity this, vector v, float maxfiredeviation)
const int WAYPOINTFLAG_CROUCH
const int WAYPOINTFLAG_LADDER
void navigation_goalrating_start(entity this)
const int WAYPOINTFLAG_TELEPORT
void navigation_goalrating_timeout_force(entity this)
bool navigation_goalrating_timeout_can_be_anticipated(entity this)
float bot_weapons_close[REGISTRY_MAX(Weapons)]
void set_tracewalk_dest(entity ent, vector org, bool fix_player_dest)
bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float end_height, float movemode)
float goalentity_lock_timeout
vector get_closer_dest(entity ent, vector org)
void navigation_routerating(entity this, entity e, float f, float rangebias)
float bot_weapons_mid[REGISTRY_MAX(Weapons)]
IntrusiveList g_bot_targets
void navigation_goalrating_timeout_expire(entity this, float seconds)
void navigation_goalrating_end(entity this)
float bot_weapons_far[REGISTRY_MAX(Weapons)]
const int WAYPOINTFLAG_JUMP
void waypoint_remove(entity wp)
bool bot_shouldattack(entity this, entity e)
IntrusiveList g_waypoints
#define MUTATOR_CALLHOOK(id,...)
const int AI_STATUS_JETPACK_LANDING
const int AI_STATUS_ATTACKING
const int AI_STATUS_OUT_JUMPPAD
const int AI_STATUS_JETPACK_FLYING
const int AI_STATUS_RUNNING
const int AI_STATUS_DANGER_AHEAD
float bot_rangepreference
const int AI_STATUS_WAYPOINT_PERSONAL_LINKING
const int AI_STATUS_ROAMING
float bot_strategytoken_taken
const int AI_STATUS_WAYPOINT_PERSONAL_REACHED
const int AI_STATUS_WAYPOINT_PERSONAL_GOING
const int AI_STATUS_OUT_WATER
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
virtual void wr_aim()
(SERVER) runs bot aiming code for this weapon
const int IT_UNLIMITED_AMMO
#define PHYS_INPUT_BUTTON_CROUCH(s)
float autocvar_sv_jumpvelocity
#define PHYS_INPUT_BUTTON_JUMP(s)
float autocvar_sv_maxspeed
#define PHYS_INPUT_BUTTON_JETPACK(s)
#define PHYS_INPUT_BUTTON_ATCK(s)
#define PHYS_INPUT_BUTTON_ATCK2(s)
float autocvar_g_jetpack_acceleration_side
cvar loopback
const vector PL_MIN_CONST
const vector PL_MAX_CONST
const float MOVE_NOMONSTERS
const float CONTENT_SOLID
const float CONTENT_WATER
float checkpvs(vector viewpos, entity viewee)
float trace_dphitq3surfaceflags
vector trace_plane_normal
const float CONTENT_SLIME
float autocvar_bot_ai_ignoregoal_timeout
bool autocvar_bot_debug_goalstack
float autocvar_bot_ai_bunnyhop_downward_pitch_max
float autocvar_bot_ai_keyboard_distance
float autocvar_bot_ai_bunnyhop_turn_angle_min
float autocvar_bot_ai_enemydetectioninterval
float autocvar_bot_ai_bunnyhop_turn_angle_max
float autocvar_bot_ai_enemydetectioninterval_stickingtoenemy
float autocvar_bot_ai_bunnyhop_turn_angle_reduction
bool autocvar_bot_ai_weapon_combo
float autocvar_bot_ai_bunnyhop_skilloffset
float autocvar_bot_ai_bunnyhop_dir_deviation_max
float autocvar_bot_ai_enemydetectionradius
float autocvar_bot_ai_weapon_combo_threshold
float autocvar_bot_ai_keyboard_threshold
float autocvar_bot_ai_chooseweaponinterval
entity havocbot_select_an_item_of_group(entity this, int gr)
float havocbot_resetgoal(entity this)
void havocbot_chooseenemy(entity this)
float havocbot_moveto(entity this, vector pos)
bool havocbot_chooseweapon_checkreload(entity this,.entity weaponentity, int new_weapon)
void havocbot_movetogoal(entity this)
int havocbot_checkdanger(entity this, vector dst_ahead)
void havocbot_chooseweapon(entity this,.entity weaponentity)
void havocbot_keyboard_movement(entity this, vector destorg)
vector havocbot_dodge(entity this)
#define ROCKETJUMP_DAMAGE()
void havocbot_aim(entity this)
bool havocbot_moveto_refresh_route(entity this)
void havocbot_bunnyhop(entity this, vector dir)
void havocbot_ai(entity this)
bool havocbot_checkgoaldistance(entity this, vector gco)
void havocbot_setupbot(entity this)
float havocbot_keyboardtime
float randomdirectiontime
float havocbot_keyboardskill
float havocbot_personal_waypoint_searchtime
entity havocbot_personal_waypoint
void havocbot_chooserole(entity this)
float bot_chooseweapontime
float havocbot_personal_waypoint_failcounter
float havocbot_stickenemy_time
float bot_stop_moving_timeout
float havocbot_chooseenemy_finished
bool tracebox_hits_trigger_hurt(vector start, vector e_min, vector e_max, vector end)
#define IL_EACH(this, cond, body)
#define ITEM_IS_LOOT(item)
Returns whether the item is loot.
#define FOREACH(list, cond, body)
float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig)
const int WATERLEVEL_SWIMMING
const int WATERLEVEL_WETFEET
bool navigation_routetogoal(entity this, entity e, vector startposition)
void navigation_clearroute(entity this)
void debuggoalstack(entity this)
void navigation_pushroute(entity this, entity e)
bool navigation_shortenpath(entity this)
int navigation_poptouchedgoals(entity this)
bool goalentity_shouldbefrozen
float bot_navigation_movemode
float goalcurrent_distance_2d
float goalcurrent_distance_time
vector navigation_jetpack_point
entity navigation_jetpack_goal
float goalcurrent_distance_z
float tracewalk_dest_height
#define crandom()
Returns a random number between -1.0 and 1.0.
#define REGISTRY_COUNT(id)
#define REGISTRY_GET(id, i)
float health
Legacy fields for the resources. To be removed.
bool bot_ispaused(entity this)
int bot_execute_commands(entity this)
#define CMD_STATUS_FINISHED
#define CMD_STATUS_EXECUTING
bool client_hasweapon(entity this, Weapon wpn,.entity weaponentity, float andammo, bool complain)
#define IS_INDEPENDENT_PLAYER(e)
ClientState CS(Client this)
bool StatusEffects_active(StatusEffect this, entity actor)
IntrusiveList g_teleporters
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
ERASEABLE vector point_line_vec(vector p, vector l0, vector ldir)
ERASEABLE float boxesoverlap(vector m1, vector m2, vector m3, vector m4)
requires that m2>m1 in all coordinates, and that m4>m3
bool waypoint_is_hardwiredlink(entity wp_from, entity wp_to)
entity waypoint_spawnpersonal(entity this, vector position)
#define WEP_CVAR(wep, name)
const int MAX_WEAPONSLOTS
const int WEP_FLAG_RELOADABLE
entity weaponentities[MAX_WEAPONSLOTS]
#define ATTACK_FINISHED(ent, w)
float weapon_load[REGISTRY_MAX(Weapons)]
WepSet g_weaponarena_weapons