setsize(w, m1 - w.origin, m2 - w.origin);
if (vlen(w.size) > 0)
w.wpisbox = TRUE;
-
+
if(!w.wpisbox)
{
setsize(w, PL_MIN - '1 1 0', PL_MAX + '1 1 0');
}
else
{
- if(cvar("developer"))
+ if(autocvar_developer)
{
print("A generated waypoint is stuck in solid at ", vtos(w.origin), "\n");
backtrace("Waypoint stuck");
waypoint_clearlinks(w);
//waypoint_schedulerelink(w);
- if (cvar("g_waypointeditor"))
+ if (autocvar_g_waypointeditor)
{
m1 = w.mins;
m2 = w.maxs;
local entity e;
local vector sv, sm1, sm2, ev, em1, em2, dv;
- stepheightvec = cvar("sv_stepheight") * '0 0 1';
- bot_navigation_movemode = ((cvar("bot_navigation_ignoreplayers")) ? MOVE_NOMONSTERS : MOVE_NORMAL);
+ bot_calculate_stepheightvec();
+
+ bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL);
//dprint("waypoint_think wpisbox = ", ftos(self.wpisbox), "\n");
sm1 = self.origin + self.mins;
if (wp == world)
return;
// TODO: add some sort of visible box in edit mode for box waypoints
- if (cvar("g_waypointeditor"))
+ if (autocvar_g_waypointeditor)
{
local vector m1, m2;
m1 = wp.mins;
if(!found)
{
- // can't find that waypoint
- fclose(file);
- return FALSE;
+ dprint("waypoint_load_links: couldn't find 'from' waypoint at ", vtos(wp_from.origin),"\n");
+ continue;
}
+
}
// Search "to" waypoint
if(!found)
{
- // can't find that waypoint
- fclose(file);
- return FALSE;
+ dprint("waypoint_load_links: couldn't find 'to' waypoint at ", vtos(wp_to.origin),"\n");
+ continue;
}
++c;
// Search "from" waypoint
if(wp_from.origin!=wp_from_pos)
{
- wp_from = findradius(wp_from_pos, 1);
+ wp_from = findradius(wp_from_pos, 5);
found = FALSE;
while(wp_from)
{
- if(vlen(wp_from.origin-wp_from_pos)<1)
+ if(vlen(wp_from.origin-wp_from_pos)<5)
if(wp_from.classname == "waypoint")
{
found = TRUE;
}
// Search "to" waypoint
- wp_to = findradius(wp_to_pos, 1);
+ wp_to = findradius(wp_to_pos, 5);
found = FALSE;
while(wp_to)
{
- if(vlen(wp_to.origin-wp_to_pos)<1)
+ if(vlen(wp_to.origin-wp_to_pos)<5)
if(wp_to.classname == "waypoint")
{
found = TRUE;
++c;
waypoint_addlink(wp_from, wp_to);
+ wp_from.wphardwired = TRUE;
+ wp_to.wphardwired = TRUE;
}
fclose(file);
waypoint_spawnforitem_force(e, e.origin);
};
-void waypoint_spawnforteleporter(entity e, vector destination, float timetaken)
+void waypoint_spawnforteleporter_boxes(entity e, vector org1, vector org2, vector destination1, vector destination2, float timetaken)
{
local entity w;
local entity dw;
- w = waypoint_spawn(e.absmin, e.absmax, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_NORELINK);
- dw = waypoint_spawn(destination, destination, WAYPOINTFLAG_GENERATED);
+ w = waypoint_spawn(org1, org2, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_NORELINK);
+ dw = waypoint_spawn(destination1, destination2, WAYPOINTFLAG_GENERATED);
// one way link to the destination
w.wp00 = dw;
w.wp00mincost = timetaken; // this is just for jump pads
e.nearestwaypointtimeout = time + 1000000000;
};
+void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, float timetaken)
+{
+ org = waypoint_fixorigin(org);
+ destination = waypoint_fixorigin(destination);
+ waypoint_spawnforteleporter_boxes(e, org, org, destination, destination, timetaken);
+};
+
+void waypoint_spawnforteleporter(entity e, vector destination, float timetaken)
+{
+ destination = waypoint_fixorigin(destination);
+ waypoint_spawnforteleporter_boxes(e, e.absmin, e.absmax, destination, destination, timetaken);
+};
+
entity waypoint_spawnpersonal(vector position)
{
entity w;
player = find(player, classname, "player");
}
};
+
+float botframe_autowaypoints_fixdown(vector v)
+{
+ tracebox(v, PL_MIN, PL_MAX, v + '0 0 -64', MOVE_NOMONSTERS, world);
+ if(trace_fraction >= 1)
+ return 0;
+ return 1;
+}
+
+float botframe_autowaypoints_createwp(vector v, entity p, .entity fld)
+{
+ entity w;
+
+ w = find(world, classname, "waypoint");
+ while (w)
+ {
+ // if a matching spawnfunc_waypoint already exists, don't add a duplicate
+ if (boxesoverlap(v - '32 32 32', v + '32 32 32', w.absmin, w.absmax))
+ //if (boxesoverlap(v - '4 4 4', v + '4 4 4', w.absmin, w.absmax))
+ return 0;
+ w = find(w, classname, "waypoint");
+ }
+
+ waypoint_schedulerelink(p.fld = waypoint_spawn(v, v, 0));
+ return 1;
+}
+
+// return value:
+// 1 = WP created
+// 0 = no action needed
+// -1 = temp fail, try from world too
+// -2 = permanent fail, do not retry
+float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .entity fld)
+{
+ // make it possible to go from p to wp, if we can
+ // if wp is world, nearest is chosen
+
+ entity w;
+ vector porg;
+ float t, tmin, tmax;
+ vector o;
+ vector save;
+
+ if(!botframe_autowaypoints_fixdown(p.origin))
+ return -2;
+ porg = trace_endpos;
+
+ if(wp)
+ {
+ // if any WP w fulfills wp -> w -> porg, then switch from wp to w
+
+ // if wp -> porg, then OK
+ float maxdist;
+ if(navigation_waypoint_will_link(wp.origin, porg, p, walkfromwp, 1050))
+ {
+ // we may find a better one
+ maxdist = vlen(wp.origin - porg);
+ }
+ else
+ {
+ // accept any "good"
+ maxdist = 2100;
+ }
+
+ float bestdist;
+ bestdist = maxdist;
+ w = find(world, classname, "waypoint");
+ while (w)
+ {
+ if(w != wp && !(w.wpflags & WAYPOINTFLAG_NORELINK))
+ {
+ float d;
+ d = vlen(wp.origin - w.origin) + vlen(w.origin - porg);
+ if(d < bestdist)
+ if(navigation_waypoint_will_link(wp.origin, w.origin, p, walkfromwp, 1050))
+ if(navigation_waypoint_will_link(w.origin, porg, p, walkfromwp, 1050))
+ {
+ bestdist = d;
+ p.fld = w;
+ }
+ }
+ w = find(w, classname, "waypoint");
+ }
+ if(bestdist < maxdist)
+ {
+ print("update chain to new nearest WP ", etos(p.fld), "\n");
+ return 0;
+ }
+
+ if(bestdist < 2100)
+ {
+ // we know maxdist < 2100
+ // so wp -> porg is still valid
+ // all is good
+ p.fld = wp;
+ return 0;
+ }
+
+ // otherwise, no existing WP can fix our issues
+ }
+ else
+ {
+ save = p.origin;
+ setorigin(p, porg);
+ w = navigation_findnearestwaypoint(p, walkfromwp);
+ setorigin(p, save);
+ if(w)
+ {
+ p.fld = w;
+ return 0;
+ }
+ }
+
+ tmin = 0;
+ tmax = 1;
+ for(;;)
+ {
+ if(tmax - tmin < 0.001)
+ {
+ // did not get a good candidate
+ return -1;
+ }
+
+ t = (tmin + tmax) * 0.5;
+ o = antilag_takebackorigin(p, time - t);
+ if(!botframe_autowaypoints_fixdown(o))
+ return -1;
+ o = trace_endpos;
+
+ if(wp)
+ {
+ if(!navigation_waypoint_will_link(wp.origin, o, p, walkfromwp, 1050))
+ {
+ // we cannot walk from wp.origin to o
+ // get closer to tmax
+ tmin = t;
+ continue;
+ }
+ }
+ else
+ {
+ save = p.origin;
+ setorigin(p, o);
+ w = navigation_findnearestwaypoint(p, walkfromwp);
+ setorigin(p, save);
+ if(!w)
+ {
+ // we cannot walk from any WP to o
+ // get closer to tmax
+ tmin = t;
+ continue;
+ }
+ }
+
+ // if we get here, o is valid regarding waypoints
+ // check if o is connected right to the player
+ // we break if it succeeds, as that means o is a good waypoint location
+ if(navigation_waypoint_will_link(o, porg, p, walkfromwp, 1050))
+ break;
+
+ // o is no good, we need to get closer to the player
+ tmax = t;
+ }
+
+ print("spawning a waypoint for connecting to ", etos(wp), "\n");
+ botframe_autowaypoints_createwp(o, p, fld);
+ return 1;
+}
+
+// automatically create missing waypoints
+.entity botframe_autowaypoints_lastwp0, botframe_autowaypoints_lastwp1;
+void botframe_autowaypoints_fix(entity p, float walkfromwp, .entity fld)
+{
+ float r;
+ r = botframe_autowaypoints_fix_from(p, walkfromwp, p.fld, fld);
+ if(r != -1)
+ return;
+ r = botframe_autowaypoints_fix_from(p, walkfromwp, world, fld);
+ if(r != -1)
+ return;
+
+ print("emergency: got no good nearby WP to build a link from, starting a new chain\n");
+ if(!botframe_autowaypoints_fixdown(p.origin))
+ return; // shouldn't happen, caught above
+ botframe_autowaypoints_createwp(trace_endpos, p, fld);
+}
+void botframe_autowaypoints()
+{
+ entity p;
+ entity wp0, wp1;
+ FOR_EACH_REALPLAYER(p)
+ {
+ if(p.deadflag)
+ continue;
+ // going back is broken, so only fix waypoints to walk TO the player
+ //botframe_autowaypoints_fix(p, FALSE, botframe_autowaypoints_lastwp0);
+ botframe_autowaypoints_fix(p, TRUE, botframe_autowaypoints_lastwp1);
+ //te_explosion(p.botframe_autowaypoints_lastwp0.origin);
+ }
+}