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 (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;
}
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;
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);