this.aistatus |= AI_STATUS_ROAMING;
this.aistatus &= ~AI_STATUS_ATTACKING;
- vector v = '0 0 0', now, next;
+ vector now, next;
float aimdistance,skillblend,distanceblend,blend;
- SET_DESTCOORDS(this.goalcurrent, this.origin, v);
+ vector v = get_closer_dest(this.goalcurrent, this.origin);
if(this.goalcurrent.wpisbox)
{
// avoid a glitch when bot is teleported but teleport waypoint isn't removed yet
float bunnyhopdistance;
vector deviation;
float maxspeed;
- vector gco = '0 0 0', gno;
// Don't jump when attacking
if(this.aistatus & AI_STATUS_ATTACKING)
this.bot_timelastseengoal = 0;
}
- SET_DESTCOORDS(this.goalcurrent, this.origin, gco);
+ vector gco = get_closer_dest(this.goalcurrent, this.origin);
bunnyhopdistance = vlen(this.origin - gco);
// Run only to visible goals
if(fabs(gco.z - this.origin.z) < this.maxs.z - this.mins.z)
if(this.goalstack01 && !wasfreed(this.goalstack01))
{
- gno = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
+ vector gno = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
deviation = vectoangles(gno - this.origin) - vectoangles(gco - this.origin);
while (deviation.y < -180) deviation.y = deviation.y + 360;
while (deviation.y > 180) deviation.y = deviation.y - 360;
void havocbot_movetogoal(entity this)
{
- vector destorg = '0 0 0';
vector diff;
vector dir;
vector flatdir;
debuggoalstack(this);
bool bunnyhop_forbidden = false;
- SET_DESTCOORDS(this.goalcurrent, this.origin, destorg);
+ vector destorg = get_closer_dest(this.goalcurrent, this.origin);
// in case bot ends up inside the teleport waypoint without touching
// the teleport itself, head to the teleport origin
return;
}
- vector dest = '0 0 0';
- float dest_height = 0;
- SET_TRACEWALK_DESTCOORDS(this.goalcurrent, this.origin, dest, dest_height);
- if (!tracewalk(this, this.origin, this.mins, this.maxs, dest, dest_height, bot_navigation_movemode))
+ set_tracewalk_dest(this.goalcurrent, this.origin, false);
+ if (!tracewalk(this, this.origin, this.mins, this.maxs,
+ tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
{
navigation_clearroute(this);
navigation_goalrating_timeout_force(this);
debuggoalstack(this);
// Heading
- vector dir = '0 0 0';
- SET_DESTCOORDS(this.goalcurrent, this.origin, dir);
+ vector dir = get_closer_dest(this.goalcurrent, this.origin);
dir = dir - (this.origin + this.view_ofs);
dir.z = 0;
bot_aimdir(this, dir, -1);
this.nearestwaypointtimeout = -1;
}
+// returns point of ent closer to org
+vector get_closer_dest(entity ent, vector org)
+{
+ vector dest = '0 0 0';
+ if ((ent.classname != "waypoint") || ent.wpisbox)
+ {
+ vector wm1 = ent.origin + ent.mins - eZ * (PL_MAX_CONST.z - 1);
+ vector wm2 = ent.origin + ent.maxs - eZ * (PL_MIN_CONST.z + 1);
+ dest.x = bound(wm1.x, org.x, wm2.x);
+ dest.y = bound(wm1.y, org.y, wm2.y);
+ dest.z = bound(wm1.z, org.z, wm2.z);
+ }
+ else
+ dest = ent.origin;
+ return dest;
+}
+
+void set_tracewalk_dest(entity ent, vector org, bool fix_player_dest)
+{
+ if ((ent.classname != "waypoint") || ent.wpisbox)
+ {
+ vector wm1 = ent.origin + ent.mins - eZ * (PL_MAX_CONST.z - 1);
+ vector wm2 = ent.origin + ent.maxs - eZ * (PL_MIN_CONST.z + 1);
+ if (IS_PLAYER(ent) || IS_MONSTER(ent))
+ {
+ // move destination point out of player bbox otherwise tracebox always fails
+ // (if bot_navigation_ignoreplayers is false)
+ wm1 += vec2(PL_MIN_CONST) + '-1 -1 0';
+ wm2 += vec2(PL_MAX_CONST) + '1 1 0';
+ }
+ // set destination point to x and y coords of ent that are closer to org
+ // z coord is set to ent's min height
+ tracewalk_dest.x = bound(wm1.x, org.x, wm2.x);
+ tracewalk_dest.y = bound(wm1.y, org.y, wm2.y);
+ tracewalk_dest.z = wm1.z;
+ tracewalk_dest_height = wm2.z - wm1.z; // destination height
+ }
+ else
+ {
+ tracewalk_dest = ent.origin;
+ tracewalk_dest_height = 0;
+ }
+ if (fix_player_dest && IS_PLAYER(ent) && !IS_ONGROUND(ent))
+ {
+ // snap player to the ground
+ tracebox(tracewalk_dest, ent.mins, ent.maxs, tracewalk_dest - '0 0 700', MOVE_NORMAL, ent);
+ if (!trace_startsolid && tracewalk_dest.z - trace_endpos.z > 0)
+ {
+ tracewalk_dest_height = tracewalk_dest.z - trace_endpos.z;
+ tracewalk_dest.z = trace_endpos.z;
+ }
+ }
+}
+
+// returns point of ent closer to org
+vector set_tracewalk_dest_2(entity ent, vector org)
+{
+ vector closer_dest = '0 0 0';
+ if ((ent.classname != "waypoint") || ent.wpisbox)
+ {
+ vector wm1 = ent.origin + ent.mins - eZ * (PL_MAX_CONST.z - 1);
+ vector wm2 = ent.origin + ent.maxs - eZ * (PL_MIN_CONST.z + 1);
+ closer_dest.x = bound(wm1.x, org.x, wm2.x);
+ closer_dest.y = bound(wm1.y, org.y, wm2.y);
+ closer_dest.z = bound(wm1.z, org.z, wm2.z);
+ // set destination point to x and y coords of ent that are closer to org
+ // z coord is set to ent's min height
+ tracewalk_dest.x = closer_dest.x;
+ tracewalk_dest.y = closer_dest.y;
+ tracewalk_dest.z = wm1.z;
+ tracewalk_dest_height = wm2.z - wm1.z; // destination height
+ }
+ else
+ {
+ closer_dest = ent.origin;
+ tracewalk_dest = closer_dest;
+ tracewalk_dest_height = 0;
+ }
+ return closer_dest;
+}
+
bool navigation_check_submerged_state(entity ent, vector pos)
{
bool submerged;
te_plasmaburn(org);
entity best = NULL;
- vector v = '0 0 0', v2 = '0 0 0';
- float v2_height = 0;
+ vector v = '0 0 0';
if(ent.size && !IS_PLAYER(ent))
{
if(walkfromwp && (it.wpflags & WAYPOINTFLAG_NORELINK))
continue;
- SET_TRACEWALK_DESTCOORDS(ent, it.origin, v2, v2_height);
- if(vdist(v2 - it.origin, <, 1050))
- if(tracewalk(ent, it.origin, PL_MIN_CONST, PL_MAX_CONST, v2, v2_height, bot_navigation_movemode))
+ set_tracewalk_dest(ent, it.origin, false);
+ if (vdist(tracewalk_dest - it.origin, <, 1050)
+ && tracewalk(ent, it.origin, PL_MIN_CONST, PL_MAX_CONST,
+ tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
+ {
navigation_item_addlink(it, ent);
+ }
});
}
continue;
v = it.origin;
if(walkfromwp)
- SET_TRACEWALK_DESTCOORDS(ent, v, v2, v2_height);
+ set_tracewalk_dest(ent, v, false);
else
- SET_TRACEWALK_DESTCOORDS(it, org, v2, v2_height);
- if(navigation_waypoint_will_link(v, org, ent, v2, v2_height, v2, v2_height, walkfromwp, bestdist))
+ set_tracewalk_dest(it, org, false);
+ if (navigation_waypoint_will_link(v, org, ent,
+ tracewalk_dest, tracewalk_dest_height,
+ tracewalk_dest, tracewalk_dest_height, walkfromwp, bestdist))
{
bestdist = vlen(v - org);
best = it;
// finds the waypoints near the bot initiating a navigation query
float navigation_markroutes_nearestwaypoints(entity this, float maxdist)
{
- vector v = '0 0 0';
//navigation_testtracewalk = true;
int c = 0;
- float v_height = 0;
IL_EACH(g_waypoints, !it.wpconsidered,
{
- SET_TRACEWALK_DESTCOORDS(it, this.origin, v, v_height);
+ set_tracewalk_dest(it, this.origin, false);
- vector diff = v - this.origin;
+ vector diff = tracewalk_dest - this.origin;
diff.z = max(0, diff.z);
if(vdist(diff, <, maxdist))
{
it.wpconsidered = true;
- if (tracewalk(this, this.origin, this.mins, this.maxs, v, v_height, bot_navigation_movemode))
+ if (tracewalk(this, this.origin, this.mins, this.maxs,
+ tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
{
- it.wpnearestpoint = v;
- it.wpcost = waypoint_gettravelcost(this.origin, v, this, it) + it.dmg;
+ it.wpnearestpoint = tracewalk_dest;
+ it.wpcost = waypoint_gettravelcost(this.origin, tracewalk_dest, this, it) + it.dmg;
it.wpfire = 1;
it.enemy = NULL;
c = c + 1;
return true;
// if it can reach the goal there is nothing more to do
- vector dest = '0 0 0';
- float dest_height = 0;
- SET_TRACEWALK_DESTCOORDS(e, startposition, dest, dest_height);
- if (tracewalk(this, startposition, STAT(PL_MIN, this), STAT(PL_MAX, this), dest, dest_height, bot_navigation_movemode))
+ set_tracewalk_dest(e, startposition, true);
+ if (tracewalk(this, startposition, STAT(PL_MIN, this), STAT(PL_MAX, this),
+ tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
+ {
return true;
+ }
entity nearest_wp = NULL;
// see if there are waypoints describing a path to the item
// often path can be optimized by not adding the nearest waypoint
if (this.goalentity.navigation_dynamicgoal || autocvar_g_waypointeditor)
{
- SET_TRACEWALK_DESTCOORDS(this.goalentity, nearest_wp.enemy.origin, dest, dest_height);
- if(vdist(dest - nearest_wp.enemy.origin, <, 1050))
- if(tracewalk(this, nearest_wp.enemy.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), dest, dest_height, bot_navigation_movemode))
+ set_tracewalk_dest(this.goalentity, nearest_wp.enemy.origin, true);
+ if (vdist(tracewalk_dest - nearest_wp.enemy.origin, <, 1050)
+ && tracewalk(this, nearest_wp.enemy.origin, STAT(PL_MIN, this), STAT(PL_MAX, this),
+ tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
+ {
e = nearest_wp.enemy;
+ }
}
else if(navigation_item_islinked(nearest_wp.enemy, this.goalentity))
e = nearest_wp.enemy;
if(vlen2(this.goalcurrent.origin - this.goalstack01.origin) > vlen2(this.goalstack01.origin - this.origin))
if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
{
- vector dest = '0 0 0';
- float dest_height = 0;
- SET_TRACEWALK_DESTCOORDS(this.goalstack01, this.origin, dest, dest_height);
- if(tracewalk(this, this.origin, this.mins, this.maxs, dest, dest_height, bot_navigation_movemode))
+ set_tracewalk_dest(this.goalstack01, this.origin, false);
+ if(tracewalk(this, this.origin, this.mins, this.maxs,
+ tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
{
LOG_DEBUG("path optimized for ", this.netname, ", removed a goal from the queue");
navigation_poproute(this);
if(wp.wpflags & WAYPOINTFLAG_TELEPORT)
return NULL;
- vector dest = '0 0 0';
- float dest_height = 0;
- SET_TRACEWALK_DESTCOORDS(wp, this.origin, dest, dest_height);
- if (!tracewalk(this, this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), dest, dest_height, bot_navigation_movemode))
+ set_tracewalk_dest(wp, this.origin, false);
+ if (!tracewalk(this, this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this),
+ tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
+ {
return NULL;
+ }
return wp;
}
// evaluate the next goal on the queue
float d = vlen2(this.origin - bot_waypoint_queue_goal.origin);
LOG_DEBUG(this.netname, " evaluating ", bot_waypoint_queue_goal.classname, " with distance ", ftos(d));
- vector dest = '0 0 0';
- float dest_height = 0;
- SET_TRACEWALK_DESTCOORDS(bot_waypoint_queue_goal, this.origin, dest, dest_height);
- if(tracewalk(bot_waypoint_queue_goal, this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), dest, dest_height, bot_navigation_movemode))
+ set_tracewalk_dest(bot_waypoint_queue_goal, this.origin, false);
+ if (tracewalk(bot_waypoint_queue_goal, this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this),
+ tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
{
if( d > bot_waypoint_queue_bestgoalrating)
{
#define navigation_item_addlink(from_wp, to_item) \
waypoint_addlink_customcost(to_item, from_wp, waypoint_getlinkcost(from_wp, to_item))
-// if ent is a box waypoint or an item v is set to coords of ent that are closer to org
-#define SET_DESTCOORDS(ent, org, v) MACRO_BEGIN { \
- if ((ent.classname != "waypoint") || ent.wpisbox) { \
- vector wm1 = ent.origin + ent.mins - eZ * (PL_MAX_CONST.z - 1); \
- vector wm2 = ent.origin + ent.maxs - eZ * (PL_MIN_CONST.z + 1); \
- v.x = bound(wm1.x, org.x, wm2.x); \
- v.y = bound(wm1.y, org.y, wm2.y); \
- v.z = bound(wm1.z, org.z, wm2.z); \
- } else { \
- v = ent.origin; \
- } \
-} MACRO_END
-
-// if ent is a box waypoint or an item v is set to coords of ent that are closer to org
-// (but v.z is set to the lowest coord of ent), v_height is set to ent's height
-// if destination ent is a player make so that destination point doesn't overlap with
-// player bbox, otherwise tracebox always fails (if bot_navigation_ignoreplayers is false)
-#define SET_TRACEWALK_DESTCOORDS(ent, org, v, v_height) MACRO_BEGIN { \
- if ((ent.classname != "waypoint") || ent.wpisbox) { \
- vector wm1 = ent.origin + ent.mins - eZ * (PL_MAX_CONST.z - 1); \
- vector wm2 = ent.origin + ent.maxs - eZ * (PL_MIN_CONST.z + 1); \
- if (IS_PLAYER(ent) || IS_MONSTER(ent)) \
- { \
- wm1 += vec2(PL_MIN_CONST) + '-1 -1 0'; \
- wm2 += vec2(PL_MAX_CONST) + '1 1 0'; \
- } \
- v.x = bound(wm1.x, org.x, wm2.x); \
- v.y = bound(wm1.y, org.y, wm2.y); \
- v.z = wm1.z; \
- v_height = wm2.z - wm1.z; \
- } else { \
- v = ent.origin; \
- v_height = 0; \
- } \
-} MACRO_END
-
-// if ent is a box waypoint or an item v and v2 are set to coords of ent that are closer to org
-// (but v2.z is set to the lowest coord of ent), v2_height is set to ent's height
-#define SET_TRACEWALK_DESTCOORDS_2(ent, org, v, v2, v2_height) MACRO_BEGIN { \
- if ((ent.classname != "waypoint") || ent.wpisbox) { \
- vector wm1 = ent.origin + ent.mins - eZ * (PL_MAX_CONST.z - 1); \
- vector wm2 = ent.origin + ent.maxs - eZ * (PL_MIN_CONST.z + 1); \
- v.x = bound(wm1.x, org.x, wm2.x); \
- v.y = bound(wm1.y, org.y, wm2.y); \
- v.z = bound(wm1.z, org.z, wm2.z); \
- v2.x = v.x; \
- v2.y = v.y; \
- v2.z = wm1.z; \
- v2_height = wm2.z - wm1.z; \
- } else { \
- v = ent.origin; \
- v2 = v; \
- v2_height = 0; \
- } \
-} MACRO_END
+vector tracewalk_dest;
+float tracewalk_dest_height;
.entity wp_goal_prev0;
.entity wp_goal_prev1;