this.nearestwaypointtimeout = -1;
}
+bool navigation_check_submerged_state(entity ent, vector pos)
+{
+ bool submerged;
+ if(IS_PLAYER(ent))
+ submerged = (ent.waterlevel == WATERLEVEL_SUBMERGED);
+ else if(ent.nav_submerged_state != SUBMERGED_UNDEFINED)
+ submerged = (ent.nav_submerged_state == SUBMERGED_YES);
+ else
+ {
+ submerged = SUBMERGED(pos);
+ // NOTE: SUBMERGED check of box waypoint origin may fail even if origin
+ // is actually submerged because often they are inside some solid.
+ // That's why submerged state is saved now that we know current pos is
+ // not stuck in solid (previous tracewalk call to this pos was successfully)
+ if(!ent.navigation_dynamicgoal)
+ ent.nav_submerged_state = (submerged) ? SUBMERGED_YES : SUBMERGED_NO;
+ }
+ return submerged;
+}
+
bool navigation_checkladders(entity e, vector org, vector m1, vector m2, vector end, vector end2, int movemode)
{
IL_EACH(g_ladders, it.classname == "func_ladder",
{
if(it.bot_pickup)
if(boxesoverlap(org + m1 + '-1 -1 -1', org + m2 + '1 1 1', it.absmin, it.absmax))
- if(boxesoverlap(end, end2, it.absmin + (m1 - eZ * m1.z - '1 1 0'), it.absmax + (m2 - eZ * m2.z + '1 1 0')))
+ if(boxesoverlap(end, end2, it.absmin + vec2(m1) + '-1 -1 0', it.absmax + vec2(m2) + '1 1 0'))
{
vector top = org;
top.z = it.absmax.z + (PL_MAX_CONST.z - PL_MIN_CONST.z);
if (flatdist <= 0)
break;
+ if (stepdist > flatdist)
+ stepdist = flatdist;
if(nav_action == NAV_SWIM_UNDERWATER || (nav_action == NAV_SWIM_ONWATER && org.z > end2.z))
{
// can't use movement direction here to calculate move because of
//water_dir = normalize(water_end - org);
//move = org + water_dir * stepdist;
fixed_end.z = bound(end.z, org.z, end2.z);
- if (stepdist > flatdist)
- stepdist = flatdist;
if (stepdist == flatdist) {
move = fixed_end;
flatdist = 0;
}
else // horiz. direction
{
- if (stepdist > flatdist)
- stepdist = flatdist;
flatdist -= stepdist;
move = org + flatdir * stepdist;
}
if (trace_fraction < 1 || trace_startsolid) // can't jump obstacle out of water
{
- if(navigation_checkladders(e, trace_endpos, m1, m2, end, end2, movemode))
+ org = trace_endpos;
+ if(navigation_checkladders(e, org, m1, m2, end, end2, movemode))
{
if(autocvar_bot_debug_tracewalk)
{
- debugnode(e, trace_endpos);
- debugnodestatus(trace_endpos, DEBUG_NODE_SUCCESS);
+ debugnode(e, org);
+ debugnodestatus(org, DEBUG_NODE_SUCCESS);
}
//print("tracewalk: ", vtos(start), " can reach ", vtos(end), "\n");
}
if(autocvar_bot_debug_tracewalk)
- debugnodestatus(trace_endpos, DEBUG_NODE_FAIL);
+ debugnodestatus(org, DEBUG_NODE_FAIL);
return false;
//print("tracewalk: ", vtos(start), " hit something when trying to reach ", vtos(end), "\n");
nav_action = NAV_SWIM_ONWATER;
// we didn't advance horiz. in this step, flatdist decrease should be reverted
- // but we can do it properly right now... apply this workaround instead
+ // but we can't do it properly right now... apply this workaround instead
if (flatdist <= 0)
flatdist = 1;
tracebox(org + stepheightvec, m1, m2, move + stepheightvec, movemode, e);
if (trace_fraction < 1 || trace_startsolid)
{
- tracebox(org + jumpstepheightvec, m1, m2, move + jumpstepheightvec, movemode, e);
- if (trace_fraction < 1 || trace_startsolid)
+ if (trace_startsolid) // hit ceiling above org
+ {
+ // reduce stepwalk height
+ tracebox(org, m1, m2, org + stepheightvec, movemode, e);
+ tracebox(trace_endpos, m1, m2, move + eZ * (trace_endpos.z - move.z), movemode, e);
+ }
+ else //if (trace_fraction < 1)
+ {
+ tracebox(org + jumpstepheightvec, m1, m2, move + jumpstepheightvec, movemode, e);
+ if (trace_startsolid) // hit ceiling above org
+ {
+ // reduce jumpstepwalk height
+ tracebox(org, m1, m2, org + jumpstepheightvec, movemode, e);
+ tracebox(trace_endpos, m1, m2, move + eZ * (trace_endpos.z - move.z), movemode, e);
+ }
+ }
+
+ if (trace_fraction < 1)
{
- vector v = trace_endpos - jumpstepheightvec + jumpheight_vec;
+ vector v = trace_endpos;
+ v.z = org.z + jumpheight_vec.z;
if(navigation_checkladders(e, v, m1, m2, end, end2, movemode))
{
if(autocvar_bot_debug_tracewalk)
else
move = trace_endpos;
- if (flatdist <= 0)
- {
- org = move;
- continue;
- }
-
// trace down from stepheight as far as possible and move there,
// if this starts in solid we try again without the stepup, and
// if that also fails we assume it is a wall
}
}
+ if (flatdist <= 0)
+ {
+ if(move.z >= end2.z && org.z < end2.z)
+ org.z = end2.z;
+ continue;
+ }
+
if(org.z > move.z - 1 || !SUBMERGED(org))
{
nav_action = NAV_WALK;
if (tracewalk(this, this.origin, this.mins, this.maxs, v, v_height, bot_navigation_movemode))
{
it.wpnearestpoint = v;
- it.wpcost = waypoint_gettravelcost(this.origin, v, SUBMERGED(this.origin), SUBMERGED(v)) + it.dmg;
+ it.wpcost = waypoint_gettravelcost(this.origin, v, this, it) + it.dmg;
it.wpfire = 1;
it.enemy = NULL;
c = c + 1;
if (w.wpflags & WAYPOINTFLAG_TELEPORT)
cost += w.wp00mincost; // assuming teleport has exactly one destination
else
- cost += waypoint_gettravelcost(p, v, SUBMERGED(p), SUBMERGED(v));
+ cost += waypoint_gettravelcost(p, v, w, wp);
if (wp.wpcost > cost)
{
wp.wpcost = cost;
if (nwp.wpcost < 10000000)
{
//te_wizspike(nwp.wpnearestpoint);
- float cost = nwp.wpcost + waypoint_gettravelcost(nwp.wpnearestpoint, goal_org, SUBMERGED(nwp.wpnearestpoint), SUBMERGED(goal_org));
+ float cost = nwp.wpcost + waypoint_gettravelcost(nwp.wpnearestpoint, goal_org, nwp, e);
LOG_DEBUG(e.classname, " ", ftos(f), "/(1+", ftos(cost), "/", ftos(rangebias), ") = ");
f = f * rangebias / (rangebias + cost);
LOG_DEBUG("considering ", e.classname, " (with rating ", ftos(f), ")");
vector m1, m2, v, o;
float c, d, danger;
c = 0;
+ entity wp_cur;
IL_EACH(g_waypoints, true,
{
danger = 0;
m1 = it.absmin;
m2 = it.absmax;
+ wp_cur = it;
IL_EACH(g_bot_dodge, it.bot_dodge,
{
v = it.origin;
v.y = bound(m1_y, v.y, m2_y);
v.z = bound(m1_z, v.z, m2_z);
o = (it.absmin + it.absmax) * 0.5;
- d = waypoint_getlinearcost(it.bot_dodgerating) - waypoint_gettravelcost(o, v, SUBMERGED(o), SUBMERGED(v));
+ d = waypoint_getlinearcost(it.bot_dodgerating) - waypoint_gettravelcost(o, v, it, wp_cur);
if (d > 0)
{
traceline(o, v, true, NULL);