#include "navigation.qh"
+#include <server/defs.qh>
+#include <server/miscfunctions.qh>
#include "cvars.qh"
#include "bot.qh"
{
tracebox(org, m1, m2, org - jumpheight_vec, movemode, e);
if (SUBMERGED(trace_endpos))
- RESURFACE_LIMITED(trace_endpos, end.z);
+ {
+ vector v = trace_endpos;
+ tracebox(v, m1, m2, end, movemode, e);
+ if(trace_endpos.z >= end.z - 1)
+ {
+ RESURFACE_LIMITED(v, trace_endpos.z);
+ trace_endpos = v;
+ }
+ }
else if (trace_endpos.z > org.z - jumpheight_vec.z)
tracebox(trace_endpos, m1, m2, trace_endpos + jumpheight_vec, movemode, e);
org = trace_endpos;
{
tracebox(org, m1, m2, move, movemode, e); // swim
- bool stepswimmed = false;
+ bool stepswum = false;
// hit something
if (trace_fraction < 1)
continue;
}
- stepswimmed = true;
+ stepswum = true;
}
if (!WETFEET(trace_endpos))
{
tracebox(trace_endpos, m1, m2, trace_endpos - eZ * (stepdist + (m2.z - m1.z)), movemode, e);
- // if stepswimmed we'll land on the obstacle, avoid the SUBMERGED check
- if (!stepswimmed && SUBMERGED(trace_endpos))
+ // if stepswum we'll land on the obstacle, avoid the SUBMERGED check
+ if (!stepswum && SUBMERGED(trace_endpos))
{
RESURFACE_LIMITED(trace_endpos, end2.z);
org = trace_endpos;
// walking to wp (walkfromwp == false) v2 and v2_height will be used as
// waypoint destination coordinates instead of v (only useful for box waypoints)
// for normal waypoints v2 == v and v2_height == 0
-float navigation_waypoint_will_link(vector v, vector org, entity ent, vector v2, float v2_height, float walkfromwp, float bestdist)
+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)
{
if (vdist(v - org, <, bestdist))
{
{
if (walkfromwp)
{
- if (tracewalk(ent, v, PL_MIN_CONST, PL_MAX_CONST, org, 0, bot_navigation_movemode))
+ if (tracewalk(ent, v, PL_MIN_CONST, PL_MAX_CONST, v2, v2_height, bot_navigation_movemode))
return true;
}
else
{
- if (tracewalk(ent, org, PL_MIN_CONST, PL_MAX_CONST, v2, v2_height, bot_navigation_movemode))
+ if (tracewalk(ent, org, PL_MIN_CONST, PL_MAX_CONST, o2, o2_height, bot_navigation_movemode))
return true;
}
}
// find the spawnfunc_waypoint near a dynamic goal such as a dropped weapon
entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfromwp, float bestdist, entity except)
{
+ if(ent.tag_entity)
+ ent = ent.tag_entity;
+
vector pm1 = ent.origin + ent.mins;
vector pm2 = ent.origin + ent.maxs;
return it;
});
- vector org = ent.origin + 0.5 * (ent.mins + ent.maxs);
- org.z = ent.origin.z + ent.mins.z - PL_MIN_CONST.z; // player height
- // TODO possibly make other code have the same support for bboxes
- if(ent.tag_entity)
- org = org + ent.tag_entity.origin;
+ vector org = ent.origin;
if (navigation_testtracewalk)
te_plasmaburn(org);
entity best = NULL;
- vector v, v2;
- float v2_height;
+ vector v = '0 0 0', v2 = '0 0 0';
+ float v2_height = 0;
- if(!autocvar_g_waypointeditor && !ent.navigation_dynamicgoal)
+ if(ent.size && !IS_PLAYER(ent))
+ {
+ org += 0.5 * (ent.mins + ent.maxs);
+ org.z = ent.origin.z + ent.mins.z - PL_MIN_CONST.z; // player height
+ }
+
+ if(!autocvar_g_waypointeditor && walkfromwp && !ent.navigation_dynamicgoal)
{
waypoint_clearlinks(ent); // initialize wpXXmincost fields
IL_EACH(g_waypoints, it != ent,
if(walkfromwp && (it.wpflags & WAYPOINTFLAG_NORELINK))
continue;
- SET_TRACEWALK_DESTCOORDS_2(it, org, v, v2, v2_height);
- if(navigation_waypoint_will_link(v, org, ent, v2, v2_height, walkfromwp, 1050))
+ SET_TRACEWALK_DESTCOORDS(it, org, v2, v2_height);
+ if(vdist(v2 - org, <, 1050))
+ if(tracewalk(ent, org, PL_MIN_CONST, PL_MAX_CONST, v2, v2_height, bot_navigation_movemode))
navigation_item_addlink(it, ent);
});
}
{
if(walkfromwp && (it.wpflags & WAYPOINTFLAG_NORELINK))
continue;
- SET_TRACEWALK_DESTCOORDS_2(it, org, v, v2, v2_height);
- if(navigation_waypoint_will_link(v, org, ent, v2, v2_height, walkfromwp, bestdist))
+ v = it.origin;
+ if(walkfromwp)
+ SET_TRACEWALK_DESTCOORDS(ent, v, v2, v2_height);
+ 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))
{
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;
+ vector v = '0 0 0';
//navigation_testtracewalk = true;
int c = 0;
- float v_height;
+ float v_height = 0;
IL_EACH(g_waypoints, !it.wpconsidered,
{
SET_TRACEWALK_DESTCOORDS(it, this.origin, v, v_height);
if (!e)
return false;
+ entity teleport_goal = NULL;
+
+ this.goalentity = e;
+
if(e.wpflags & WAYPOINTFLAG_TELEPORT)
{
// force teleport destination as route destination
- e.wp00.enemy = e;
- e = e.wp00;
+ teleport_goal = e;
+ navigation_pushroute(this, e.wp00);
+ this.goalentity = e.wp00;
}
- this.goalentity = e;
-
// put the entity on the goal stack
//print("routetogoal ", etos(e), "\n");
navigation_pushroute(this, e);
+ if(teleport_goal)
+ e = this.goalentity;
+
if(e.classname == "waypoint" && !(e.wpflags & WAYPOINTFLAG_PERSONAL))
{
this.wp_goal_prev1 = this.wp_goal_prev0;
return true;
// if it can reach the goal there is nothing more to do
- vector dest = (e.absmin + e.absmax) * 0.5;
- dest.z = e.absmin.z;
- float dest_height = e.absmax.z - e.absmin.z;
+ 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))
return true;
e = e.nearestwaypoint;
nearest_wp = e;
}
+ else if(teleport_goal)
+ e = teleport_goal;
else
e = e.enemy; // we already have added it, so...
e = nearest_wp.enemy;
else
{
- if (this.goalentity.navigation_dynamicgoal)
+ if (this.goalentity.navigation_dynamicgoal || autocvar_g_waypointeditor)
{
- vector dest = (this.goalentity.absmin + this.goalentity.absmax) * 0.5;
- dest.z = this.goalentity.absmin.z;
- float dest_height = this.goalentity.absmax.z - this.goalentity.absmin.z;
+ 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))
e = nearest_wp.enemy;
}
{
LOG_DEBUG("path optimized for ", this.netname, ", removed a goal from the queue");
navigation_poproute(this);
+ if(this.goalcurrent && this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)
+ return;
// TODO this may also be a nice idea to do "early" (e.g. by
// manipulating the vlen() comparisons) to shorten paths in
// general - this would make bots walk more "on rails" than
}
navigation_poproute(this);
+ if(this.goalcurrent && this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)
+ return;
}
}
}
}
navigation_poproute(this);
+ if(this.goalcurrent && this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)
+ return;
}
}