55#define MAX_CHASE_DISTANCE 700
65 if (this.
goalentity.bot_pickup &&
time >
this.bot_strategytime - 5)
90 if (dropper && dropper.nearestwaypointtimeout && dropper.nearestwaypointtimeout <
time + 2)
107 if ((ent.classname !=
"waypoint") || ent.wpisbox)
109 vector wm1 = ent.origin + ent.mins;
110 vector wm2 = ent.origin + ent.maxs;
122 if ((ent.classname !=
"waypoint") || ent.wpisbox)
124 vector wm1 = ent.origin + ent.mins;
125 vector wm2 = ent.origin + ent.maxs;
142 fix_player_dest =
false;
161 tracebox(ent.origin, ent.mins, ent.maxs, ent.origin -
'0 0 700',
MOVE_NORMAL, ent);
180 vector closer_dest =
'0 0 0';
181 if ((ent.classname !=
"waypoint") || ent.wpisbox)
183 vector wm1 = ent.origin + ent.mins;
184 vector wm2 = ent.origin + ent.maxs;
185 closer_dest.x =
bound(wm1.x,
org.x, wm2.x);
186 closer_dest.y =
bound(wm1.y,
org.y, wm2.y);
187 closer_dest.z =
bound(wm1.z,
org.z, wm2.z);
197 closer_dest = ent.origin;
218 if(!ent.navigation_dynamicgoal)
234 tracebox(
org, m1, m2, top, movemode, e);
251 float RES_min_h =
org.z;
252 float RES_max_h = lim;
254 org.z = 0.5 * (RES_min_h + RES_max_h);
259 }
while (RES_max_h - RES_min_h >= 1);
264#define RESURFACE_LIMITED(org, lim) org = resurface_limited(org, lim, m1)
267#define NAV_SWIM_ONWATER 1
268#define NAV_SWIM_UNDERWATER 2
283 vector flatdir = end - start;
285 float flatdist =
vlen(flatdir);
288 bool ignorehazards =
false;
293 ignorehazards =
true;
308 end2.z += end_height;
321 tracebox(
org, m1, m2,
org -
eZ * (m2.z - m1.z), movemode, e);
340 if (
org.z > end2.z + 1)
342 tracebox(
org, m1, m2, end2, movemode, e);
344 if (
org.z > end2.z + 1)
347 else if (
org.z < end.z - 1)
353 tracebox(v, m1, m2, end, movemode, e);
363 if (
org.z < end.z - 1)
387 if (stepdist > flatdist)
395 fixed_end.z =
bound(end.z,
org.z, end2.z);
396 if (stepdist == flatdist) {
400 move =
org + (fixed_end -
org) * (stepdist / flatdist);
401 flatdist =
vlen(
vec2(fixed_end - move));
406 flatdist -= stepdist;
407 move =
org + flatdir * stepdist;
412 tracebox(
org, m1, m2, move, movemode, e);
477 tracebox(
org, m1, m2, move, movemode, e);
479 bool stepswum =
false;
486 if (flatdist > 0 && stepswim_move.z > end2.z +
stepheightvec.z)
487 stepswim_move.z = end2.z;
503 float org_z_prev =
org.z;
505 if(
org.z == org_z_prev)
562 tracebox(
org, m1, m2, move, movemode, e);
609 tracebox(
org, m1, m2, move, movemode, e);
657 traceline(
org, move, movemode, e);
665 nextmove = move + (flatdir * stepdist);
666 traceline( move, nextmove, movemode, e);
695 tracebox(move, m1, m2, move +
'0 0 -65536', movemode, e);
716 if(move.z >= end2.z &&
org.z < end2.z)
900 traceline(v,
org,
true, ent);
922 ent = ent.tag_entity;
924 vector pm1 = ent.origin + ent.mins;
925 vector pm2 = ent.origin + ent.maxs;
943 if(boxesoverlap(pm1, pm2, it.absmin, it.absmax))
945 if(walkfromwp && !ent.navigation_dynamicgoal)
946 waypoint_clearlinks(ent);
961 org += 0.5 * (ent.mins + ent.maxs);
996 if(!
best && !ent.navigation_dynamicgoal)
998 int solid_save = ent.solid;
1004 best = it.nearestwaypoint;
1008 ent.solid = solid_save;
1031 set_tracewalk_dest(it, this.origin, false);
1033 vector diff = tracewalk_dest - this.origin;
1034 diff.z = max(0, diff.z);
1035 if(vdist(diff, <, maxdist))
1037 it.wpconsidered = true;
1038 if (tracewalk(this, this.origin, this.mins, this.maxs,
1039 tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
1041 it.wpnearestpoint = tracewalk_dest;
1042 it.wpcost = waypoint_gettravelcost(this.origin, tracewalk_dest, this, it) + it.dmg;
1060 m1 = wp.origin + wp.mins;
1061 m2 = wp.origin + wp.maxs;
1062 v.x =
bound(m1_x, p.x, m2_x);
1063 v.y =
bound(m1_y, p.y, m2_y);
1064 v.z =
bound(m1_z, p.z, m2_z);
1069 cost += w.wp00mincost;
1072 if (wp.wpcost > cost)
1077 wp.wpnearestpoint = v;
1089 it.wpconsidered =
false;
1090 it.wpnearestpoint =
'0 0 0';
1091 it.wpcost = 10000000;
1096 if(fixed_source_waypoint)
1098 fixed_source_waypoint.wpconsidered =
true;
1099 fixed_source_waypoint.wpnearestpoint = fixed_source_waypoint.origin + 0.5 * (fixed_source_waypoint.mins + fixed_source_waypoint.maxs);
1100 fixed_source_waypoint.wpcost = fixed_source_waypoint.dmg;
1101 fixed_source_waypoint.wpfire = 1;
1102 fixed_source_waypoint.enemy =
NULL;
1108 float increment, maxdistance;
1112 maxdistance = 50000;
1123 bool searching =
true;
1132 p = it.wpnearestpoint;
1134 wp = it.wp00;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp00mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1135 wp = it.wp01;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp01mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1136 wp = it.wp02;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp02mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1137 wp = it.wp03;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp03mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1138 wp = it.wp04;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp04mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1139 wp = it.wp05;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp05mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1140 wp = it.wp06;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp06mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1141 wp = it.wp07;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp07mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1142 wp = it.wp08;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp08mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1143 wp = it.wp09;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp09mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1144 wp = it.wp10;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp10mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1145 wp = it.wp11;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp11mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1146 wp = it.wp12;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp12mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1147 wp = it.wp13;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp13mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1148 wp = it.wp14;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp14mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1149 wp = it.wp15;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp15mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1150 wp = it.wp16;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp16mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1151 wp = it.wp17;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp17mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1152 wp = it.wp18;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp18mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1153 wp = it.wp19;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp19mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1154 wp = it.wp20;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp20mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1155 wp = it.wp21;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp21mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1156 wp = it.wp22;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp22mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1157 wp = it.wp23;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp23mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1158 wp = it.wp24;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp24mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1159 wp = it.wp25;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp25mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1160 wp = it.wp26;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp26mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1161 wp = it.wp27;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp27mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1162 wp = it.wp28;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp28mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1163 wp = it.wp29;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp29mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1164 wp = it.wp30;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp30mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1165 wp = it.wp31;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp31mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1166 }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
1178 it.wpconsidered =
false;
1179 it.wpnearestpoint =
'0 0 0';
1180 it.wpcost = 10000000;
1185 if(fixed_source_waypoint)
1187 fixed_source_waypoint.wpconsidered =
true;
1188 fixed_source_waypoint.wpnearestpoint = fixed_source_waypoint.origin + 0.5 * (fixed_source_waypoint.mins + fixed_source_waypoint.maxs);
1189 fixed_source_waypoint.wpcost = fixed_source_waypoint.dmg;
1190 fixed_source_waypoint.wpfire = 1;
1191 fixed_source_waypoint.enemy =
NULL;
1195 error(
"need to start with a waypoint\n");
1198 bool searching =
true;
1207 p = it.wpnearestpoint;
1209 IL_EACH(g_waypoints, it != wp,
1211 if(!waypoint_islinked(it, wp))
1213 cost2 = cost + it.dmg;
1214 navigation_markroutes_checkwaypoint(wp, it, cost2, p);
1223 if (!e || e.blacklisted) {
return; }
1230 bool rate_wps =
false;
1239 traceline(e.origin, e.origin +
'0 0 -1500',
true,
NULL);
1256 &&
vdist(it.origin - theEnemy.origin, <, 500)
1257 &&
vdist(it.origin -
this.origin, >, 100)
1258 &&
vdist(it.origin -
this.origin, <, 10000),
1260 float dist = vlen2(it.origin - theEnemy.origin);
1261 if (dist < best_dist)
1273 vector goal_org = (e.absmin + e.absmax) * 0.5;
1284 LOG_DEBUG(
"jetpack ai: evaluating path for ", e.classname);
1291 traceline(goal_org, goal_org +
'0 0 65535',
MOVE_NORMAL, e);
1299 LOG_DEBUG(
"jetpack ai: can bridge these two points");
1302 float zdistance, xydistance, cost, t, fuel;
1305 down =
'0 0 -1' * (
STAT(PL_MAX,
this).z -
STAT(PL_MIN,
this).z) * 10;
1308 npa = pointa + down;
1309 npb = pointb + down;
1311 if(npa.z<=
this.absmax.z)
1314 if(npb.z<=e.absmax.z)
1329 xydistance =
vlen(pointa - pointb);
1330 zdistance =
fabs(pointa.z -
this.origin.z);
1350 f = f * rangebias / (rangebias + cost);
1354 LOG_DEBUG(
"jetpack path: added goal ", e.classname,
" (with rating ",
ftos(f),
")");
1377 e.nearestwaypoint =
NULL;
1379 if ((!e.nearestwaypoint || e.navigation_dynamicgoal)
1380 && e.nearestwaypointtimeout >= 0 &&
time > e.nearestwaypointtimeout)
1382 if(
IS_BOT_CLIENT(e) && e.goalcurrent && e.goalcurrent.classname ==
"waypoint")
1383 e.nearestwaypoint = nwp = e.goalcurrent;
1388 LOG_DEBUG(
"FAILED to find a nearest waypoint to '", e.classname,
"' #",
etos(e));
1390 if(!e.navigation_dynamicgoal)
1391 e.blacklisted =
true;
1395 LOG_DEBUG(
"The entity '", e.classname,
"' is going to be excluded from path finding during this match");
1400 if(e.navigation_dynamicgoal)
1401 e.nearestwaypointtimeout =
time + 2;
1403 e.nearestwaypointtimeout =
time + 3 +
random() * 2;
1405 nwp = e.nearestwaypoint;
1408 if (nwp && nwp.wpcost < 10000000)
1411 float nwptoitem_cost = 0;
1413 nwptoitem_cost = nwp.wp00mincost;
1416 float cost = nwp.wpcost + nwptoitem_cost;
1417 LOG_DEBUG(
"checking ^5", e.classname,
"^7 with base rating ^xf04",
ftos(f),
"^7 and rangebias ^xf40",
ftos(rangebias));
1418 f = f * rangebias / (rangebias + cost);
1419 LOG_DEBUG(
" ^5", e.classname,
"^7 with cost ^6",
ftos(cost),
"^7 and final rating ^2",
ftos(f));
1422 LOG_DEBUG(
" ground path: ^3added goal ^5", e.classname);
1477 e = e.nearestwaypoint;
1480 else if(teleport_goal)
1496 e = nearest_wp.enemy;
1502 &&
tracewalk(
this, nearest_wp.enemy.origin,
STAT(PL_MIN,
this),
STAT(PL_MAX,
this),
1505 e = nearest_wp.enemy;
1518 e = nearest_wp.enemy;
1522 entity wp = nearest_wp.enemy;
1524 bool walkable =
false;
1533 e = nearest_wp.enemy;
1563 bool cut_allowed =
false;
1582 while (deviation.y < -180) deviation.y += 360;
1583 while (deviation.y > 180) deviation.y -= 360;
1584 if (
fabs(deviation.y) > 25)
1620 LOG_DEBUG(
"path optimized for ", this.
netname,
", removed a goal from the queue");
1632 int removed_goals = 0;
1635 return removed_goals;
1664 float max_delay = 0.1;
1668 return removed_goals;
1680 return removed_goals;
1710 return removed_goals;
1743 return removed_goals;
1752 if(this.
goalcurrent.classname ==
"waypoint" && !
this.goalcurrent.wpisbox)
1779 return removed_goals;
1781 return removed_goals;
1798 if(wp.classname !=
"waypoint")
1800 wp = wp.nearestwaypoint;
1804 if(
vdist(wp.origin -
this.origin, >, min_dist))
1809 if(vdist(it.origin - this.origin, <, min_dist))
1889 v.x = bound(m1_x, v.x, m2_x);
1890 v.y = bound(m1_y, v.y, m2_y);
1891 v.z = bound(m1_z, v.z, m2_z);
1892 o = (it.absmin + it.absmax) * 0.5;
1893 d = waypoint_getlinearcost(it.bot_dodgerating) - waypoint_gettravelcost(o, v, it, wp_cur);
1896 traceline(o, v, true, NULL);
1897 if (trace_fraction == 1)
1898 danger = danger + d;
1913 bool has_user_waypoints =
false;
1916 has_user_waypoints = true;
1919 if (!has_user_waypoints)
1922 float search_radius = 1000;
1967 LOG_DEBUG(this.
netname,
" stuck, reachable waypoint found, heading to it");
1987 LOG_DEBUG(this.
netname,
" stuck, scanning reachable waypoints within ",
ftos(search_radius),
" qu");
1993 if(bot_waypoint_queue_goal)
1994 bot_waypoint_queue_goal.bot_waypoint_queue_nextgoal = it;
1998 bot_waypoint_queue_goal = it;
1999 bot_waypoint_queue_goal.bot_waypoint_queue_nextgoal = NULL;
2053 te_customflash(position, 40, 2, c);
2114 go = ( goal.absmin + goal.absmax ) * 0.5;
bool havocbot_goalrating_item_pickable_check_players(entity this, vector org, entity item, vector item_org)
const int WAYPOINTFLAG_PERSONAL
const int WAYPOINTFLAG_TELEPORT
const int WAYPOINTFLAG_PROTECTED
float nearestwaypointtimeout
bool navigation_dynamicgoal
bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float end_height, float movemode)
float goalentity_lock_timeout
const int WAYPOINTFLAG_GENERATED
const int WPFLAGMASK_NORELINK
IntrusiveList g_bot_dodge
const int WAYPOINTFLAG_JUMP
IntrusiveList g_waypoints
const int AI_STATUS_RUNNING
const int AI_STATUS_WAYPOINT_PERSONAL_REACHED
const int AI_STATUS_WAYPOINT_PERSONAL_GOING
const int AI_STATUS_STUCK
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.
const int IT_UNLIMITED_AMMO
float autocvar_sv_maxspeed
int autocvar_g_jetpack_fuel
float autocvar_g_jetpack_maxspeed_up
float autocvar_g_jetpack_maxspeed_side
const vector PL_MIN_CONST
const int FL_PARTIALGROUND
const vector PL_MAX_CONST
const float MOVE_NOMONSTERS
const float CONTENT_SOLID
const float CONTENT_WATER
float checkpvs(vector viewpos, entity viewee)
const float CONTENT_SLIME
float autocvar_bot_ai_ignoregoal_timeout
bool autocvar_bot_debug_tracewalk
bool autocvar_bot_wander_enable
float autocvar_bot_ai_navigation_jetpack_mindistance
float autocvar_bot_ai_strategyinterval_movingtarget
float autocvar_bot_ai_strategyinterval
int autocvar_g_waypointeditor_auto
float autocvar_bot_ai_navigation_jetpack
bool tracebox_hits_trigger_hurt(vector start, vector e_min, vector e_max, vector end)
#define IL_EACH(this, cond, body)
#define FOREACH_ENTITY_RADIUS(org, dist, cond, body)
bool trigger_push_test(entity this, entity item)
const int WATERLEVEL_WETFEET
const int WATERLEVEL_SUBMERGED
void debugnodestatus(vector position, float status)
float navigation_waypoint_will_link(vector v, vector org, entity ent, vector v2, float v2_height, vector o2, float o2_height, float walkfromwp, float bestdist)
bool navigation_checkladders(entity e, vector org, vector m1, vector m2, vector end, vector end2, int movemode)
vector resurface_limited(vector org, float lim, vector m1)
entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
void navigation_goalrating_start(entity this)
void navigation_goalrating_timeout_force(entity this)
void navigation_markroutes_inverted(entity fixed_source_waypoint)
void navigation_goalrating_timeout_set(entity this)
bool navigation_goalrating_timeout_can_be_anticipated(entity this)
void navigation_markroutes_checkwaypoint(entity w, entity wp, float cost, vector p)
void debugnode(entity this, vector node)
void navigation_unstuck(entity this)
bool navigation_routetogoal(entity this, entity e, vector startposition)
entity navigation_get_really_close_waypoint(entity this)
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 navigation_markroutes_nearestwaypoints(entity this, float maxdist)
bool navigation_goalrating_timeout(entity this)
entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfromwp, float bestdist, entity except)
ERASEABLE void navigation_goalrating_timeout_extend_if_needed(entity this, float seconds)
void navigation_dynamicgoal_init(entity this, bool initially_static)
void navigation_markroutes(entity this, entity fixed_source_waypoint)
vector get_closer_dest(entity ent, vector org)
#define NAV_SWIM_UNDERWATER
void navigation_poproute(entity this)
void navigation_routerating(entity this, entity e, float f, float rangebias)
void navigation_dynamicgoal_set(entity this, entity dropper)
bool navigation_check_submerged_state(entity ent, vector pos)
void navigation_clearroute(entity this)
void debuggoalstack(entity this)
void navigation_goalrating_timeout_expire(entity this, float seconds)
void navigation_goalrating_end(entity this)
#define MAX_CHASE_DISTANCE
void navigation_pushroute(entity this, entity e)
vector set_tracewalk_dest_2(entity ent, vector org)
bool navigation_shortenpath(entity this)
void botframe_updatedangerousobjects(float maxupdate)
int navigation_poptouchedgoals(entity this)
#define RESURFACE_LIMITED(org, lim)
void navigation_dynamicgoal_unset(entity this)
bool goalentity_shouldbefrozen
entity bot_waypoint_queue_bestgoal
float bot_navigation_movemode
float goalcurrent_distance_2d
const float DEBUG_NODE_SUCCESS
float bot_waypoint_queue_bestgoalrating
float goalcurrent_distance_time
#define SUBMERGED_UNDEFINED
#define navigation_item_getlinknum(to_item, from_wp)
vector navigation_jetpack_point
const float DEBUG_NODE_WARNING
entity bot_waypoint_queue_owner
#define navigation_item_iswalkablelink(to_item, from_wp)
const float BOT_BUNNYHOP_WP_DETECTION_RANGE
entity navigation_bestgoal
entity navigation_jetpack_goal
float goalcurrent_distance_z
#define navigation_item_initlinks_ifneeded(e)
entity bot_waypoint_queue_goal
float tracewalk_dest_height
#define TELEPORT_USED(pl, tele_wp)
float navigation_bestrating
float navigation_testtracewalk
const float DEBUG_NODE_FAIL
#define navigation_item_add_link(from_wp, to_item, walkable)
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
ERASEABLE float boxesoverlap(vector m1, vector m2, vector m3, vector m4)
requires that m2>m1 in all coordinates, and that m4>m3
float waypoint_gettravelcost(vector from, vector to, entity from_ent, entity to_ent)
float waypoint_getlinearcost(float dist)
bool waypointeditor_enabled