return false;
}
-#define IN_LAVA(pos) (cont = pointcontents(pos), (cont == CONTENT_LAVA || cont == CONTENT_SLIME))
-#define IN_LIQUID(pos) (cont = pointcontents(pos), (cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME))
-#define SUBMERGED(pos) IN_LIQUID(pos + autocvar_sv_player_viewoffset)
-#define WETFEET(pos) IN_LIQUID(pos + eZ * (m1.z + 1))
-
vector resurface_limited(vector org, float lim, vector m1)
{
- int cont;
if (WETFEET(org + eZ * (lim - org.z)))
org.z = lim;
else
flatdir = normalize(flatdir);
float stepdist = 32;
bool ignorehazards = false;
- int cont;
int nav_action;
// Analyze starting point
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) + it.dmg;
+ it.wpcost = waypoint_gettravelcost(this.origin, v, SUBMERGED(this.origin), SUBMERGED(v)) + 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);
+ cost += waypoint_gettravelcost(p, v, SUBMERGED(p), SUBMERGED(v));
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);
+ float cost = nwp.wpcost + waypoint_gettravelcost(nwp.wpnearestpoint, goal_org, SUBMERGED(nwp.wpnearestpoint), SUBMERGED(goal_org));
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), ")");
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);
+ d = waypoint_getlinearcost(it.bot_dodgerating) - waypoint_gettravelcost(o, v, SUBMERGED(o), SUBMERGED(v));
if (d > 0)
{
traceline(o, v, true, NULL);
return dist / (autocvar_sv_maxspeed * 1.25);
return dist / autocvar_sv_maxspeed;
}
+float waypoint_getlinearcost_underwater(float dist)
+{
+ // NOTE: this value is hardcoded on the engine too, see SV_WaterMove
+ return dist / (autocvar_sv_maxspeed * 0.7);
+}
-float waypoint_gettravelcost(vector from, vector to)
+float waypoint_gettravelcost(vector from, vector to, bool submerged_from, bool submerged_to)
{
+ if (submerged_from && submerged_to)
+ return waypoint_getlinearcost_underwater(vlen(to - from));
+
float c = waypoint_getlinearcost(vlen(to - from));
float height = from.z - to.z;
if(height_cost > c)
c = height_cost;
}
+
+ if (submerged_from || submerged_to)
+ return (c + waypoint_getlinearcost_underwater(vlen(to - from))) / 2;
return c;
}
v2_y = bound(m1_y, v2_y, m2_y);
v2_z = bound(m1_z, v2_z, m2_z);
}
- return waypoint_gettravelcost(v1, v2);
+ return waypoint_gettravelcost(v1, v2, SUBMERGED(v1), SUBMERGED(v2));
}
// add a new link to the spawnfunc_waypoint, replacing the furthest link it already has