]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/waypoints.qc
Merge branch 'master' into TimePath/global_self
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / waypoints.qc
index da0b3508941ecaec1fdf0205e0b464be0c971978..957f2478d2e44a6f20ac2f0badf84d2460b69884 100644 (file)
@@ -1,3 +1,15 @@
+#include "waypoints.qh"
+#include "../_all.qh"
+
+#include "bot.qh"
+#include "navigation.qh"
+
+#include "../antilag.qh"
+
+#include "../../common/constants.qh"
+
+#include "../../warpzonelib/util_server.qh"
+
 // create a new spawnfunc_waypoint and automatically link it to other waypoints, and link
 // them back to it as well
 // (suitable for spawnfunc_waypoint editor)
@@ -22,7 +34,7 @@ entity waypoint_spawn(vector m1, vector m2, float f)
        setorigin(w, (m1 + m2) * 0.5);
        setsize(w, m1 - w.origin, m2 - w.origin);
        if (vlen(w.size) > 0)
-               w.wpisbox = TRUE;
+               w.wpisbox = true;
 
        if(!w.wpisbox)
        {
@@ -31,7 +43,7 @@ entity waypoint_spawn(vector m1, vector m2, float f)
                {
                        if(!(f & WAYPOINTFLAG_GENERATED))
                        {
-                               dprint("Killed a waypoint that was stuck in solid at ", vtos(w.origin), "\n");
+                               LOG_TRACE("Killed a waypoint that was stuck in solid at ", vtos(w.origin), "\n");
                                remove(w);
                                return world;
                        }
@@ -39,7 +51,7 @@ entity waypoint_spawn(vector m1, vector m2, float f)
                        {
                                if(autocvar_developer)
                                {
-                                       print("A generated waypoint is stuck in solid at ", vtos(w.origin), "\n");
+                                       LOG_INFO("A generated waypoint is stuck in solid at ", vtos(w.origin), "\n");
                                        backtrace("Waypoint stuck");
                                }
                        }
@@ -150,7 +162,7 @@ void waypoint_addlink(entity from, entity to)
 // (precompile a list of all reachable waypoints from this spawnfunc_waypoint)
 // (SLOW!)
 void waypoint_think()
-{
+{SELFPARAM();
        entity e;
        vector sv, sm1, sm2, ev, em1, em2, dv;
 
@@ -177,17 +189,17 @@ void waypoint_think()
                                continue;
                        }
                        sv = e.origin;
-                       sv_x = bound(sm1_x, sv_x, sm2_x);
-                       sv_y = bound(sm1_y, sv_y, sm2_y);
-                       sv_z = bound(sm1_z, sv_z, sm2_z);
+                       sv.x = bound(sm1_x, sv.x, sm2_x);
+                       sv.y = bound(sm1_y, sv.y, sm2_y);
+                       sv.z = bound(sm1_z, sv.z, sm2_z);
                        ev = self.origin;
                        em1 = e.origin + e.mins;
                        em2 = e.origin + e.maxs;
-                       ev_x = bound(em1_x, ev_x, em2_x);
-                       ev_y = bound(em1_y, ev_y, em2_y);
-                       ev_z = bound(em1_z, ev_z, em2_z);
+                       ev.x = bound(em1_x, ev.x, em2_x);
+                       ev.y = bound(em1_y, ev.y, em2_y);
+                       ev.z = bound(em1_z, ev.z, em2_z);
                        dv = ev - sv;
-                       dv_z = 0;
+                       dv.z = 0;
                        if (vlen(dv) >= 1050) // max search distance in XY
                        {
                                ++relink_lengthculled;
@@ -196,7 +208,7 @@ void waypoint_think()
                        navigation_testtracewalk = 0;
                        if (!self.wpisbox)
                        {
-                               tracebox(sv - PL_MIN_z * '0 0 1', PL_MIN, PL_MAX, sv, FALSE, self);
+                               tracebox(sv - PL_MIN.z * '0 0 1', PL_MIN, PL_MAX, sv, false, self);
                                if (!trace_startsolid)
                                {
                                        //dprint("sv deviation", vtos(trace_endpos - sv), "\n");
@@ -205,14 +217,14 @@ void waypoint_think()
                        }
                        if (!e.wpisbox)
                        {
-                               tracebox(ev - PL_MIN_z * '0 0 1', PL_MIN, PL_MAX, ev, FALSE, e);
+                               tracebox(ev - PL_MIN.z * '0 0 1', PL_MIN, PL_MAX, ev, false, e);
                                if (!trace_startsolid)
                                {
                                        //dprint("ev deviation", vtos(trace_endpos - ev), "\n");
                                        ev = trace_endpos + '0 0 1';
                                }
                        }
-                       //traceline(self.origin, e.origin, FALSE, world);
+                       //traceline(self.origin, e.origin, false, world);
                        //if (trace_fraction == 1)
                        if (!self.wpisbox && tracewalk(self, sv, PL_MIN, PL_MAX, ev, MOVE_NOMONSTERS))
                                waypoint_addlink(self, e);
@@ -225,7 +237,7 @@ void waypoint_think()
                }
        }
        navigation_testtracewalk = 0;
-       self.wplinked = TRUE;
+       self.wplinked = true;
 }
 
 void waypoint_clearlinks(entity wp)
@@ -243,7 +255,7 @@ void waypoint_clearlinks(entity wp)
        wp.wp16mincost = wp.wp17mincost = wp.wp18mincost = wp.wp19mincost = wp.wp20mincost = wp.wp21mincost = wp.wp22mincost = wp.wp23mincost = f;
        wp.wp24mincost = wp.wp25mincost = wp.wp26mincost = wp.wp27mincost = wp.wp28mincost = wp.wp29mincost = wp.wp30mincost = wp.wp31mincost = f;
 
-       wp.wplinked = FALSE;
+       wp.wplinked = false;
 }
 
 // tell a spawnfunc_waypoint to relink
@@ -282,7 +294,7 @@ void waypoint_schedulerelink(entity wp)
 
 // spawnfunc_waypoint map entity
 void spawnfunc_waypoint()
-{
+{SELFPARAM();
        setorigin(self, self.origin);
        // schedule a relink after other waypoints have had a chance to spawn
        waypoint_clearlinks(self);
@@ -369,10 +381,10 @@ float waypoint_load_links()
 
        if (file < 0)
        {
-               dprint("waypoint links load from ");
-               dprint(filename);
-               dprint(" failed\n");
-               return FALSE;
+               LOG_TRACE("waypoint links load from ");
+               LOG_TRACE(filename);
+               LOG_TRACE(" failed\n");
+               return false;
        }
 
        while ((s = fgets(file)))
@@ -383,7 +395,7 @@ float waypoint_load_links()
                {
                        // bad file format
                        fclose(file);
-                       return FALSE;
+                       return false;
                }
 
                wp_from_pos     = stov(argv(0));
@@ -393,13 +405,13 @@ float waypoint_load_links()
                if(!wp_from || wp_from.origin!=wp_from_pos)
                {
                        wp_from = findradius(wp_from_pos, 1);
-                       found = FALSE;
+                       found = false;
                        while(wp_from)
                        {
                                if(vlen(wp_from.origin-wp_from_pos)<1)
                                if(wp_from.classname == "waypoint")
                                {
-                                       found = TRUE;
+                                       found = true;
                                        break;
                                }
                                wp_from = wp_from.chain;
@@ -407,7 +419,7 @@ float waypoint_load_links()
 
                        if(!found)
                        {
-                               dprint("waypoint_load_links: couldn't find 'from' waypoint at ", vtos(wp_from.origin),"\n");
+                               LOG_TRACE("waypoint_load_links: couldn't find 'from' waypoint at ", vtos(wp_from.origin),"\n");
                                continue;
                        }
 
@@ -415,13 +427,13 @@ float waypoint_load_links()
 
                // Search "to" waypoint
                wp_to = findradius(wp_to_pos, 1);
-               found = FALSE;
+               found = false;
                while(wp_to)
                {
                        if(vlen(wp_to.origin-wp_to_pos)<1)
                        if(wp_to.classname == "waypoint")
                        {
-                               found = TRUE;
+                               found = true;
                                break;
                        }
                        wp_to = wp_to.chain;
@@ -429,7 +441,7 @@ float waypoint_load_links()
 
                if(!found)
                {
-                       dprint("waypoint_load_links: couldn't find 'to' waypoint at ", vtos(wp_to.origin),"\n");
+                       LOG_TRACE("waypoint_load_links: couldn't find 'to' waypoint at ", vtos(wp_to.origin),"\n");
                        continue;
                }
 
@@ -439,14 +451,14 @@ float waypoint_load_links()
 
        fclose(file);
 
-       dprint("loaded ");
-       dprint(ftos(c));
-       dprint(" waypoint links from maps/");
-       dprint(mapname);
-       dprint(".waypoints.cache\n");
+       LOG_TRACE("loaded ");
+       LOG_TRACE(ftos(c));
+       LOG_TRACE(" waypoint links from maps/");
+       LOG_TRACE(mapname);
+       LOG_TRACE(".waypoints.cache\n");
 
-       botframe_cachedwaypointlinks = TRUE;
-       return TRUE;
+       botframe_cachedwaypointlinks = true;
+       return true;
 }
 
 void waypoint_load_links_hardwired()
@@ -459,13 +471,13 @@ void waypoint_load_links_hardwired()
        filename = strcat(filename, ".waypoints.hardwired");
        file = fopen(filename, FILE_READ);
 
-       botframe_loadedforcedlinks = TRUE;
+       botframe_loadedforcedlinks = true;
 
        if (file < 0)
        {
-               dprint("waypoint links load from ");
-               dprint(filename);
-               dprint(" failed\n");
+               LOG_TRACE("waypoint links load from ");
+               LOG_TRACE(filename);
+               LOG_TRACE(" failed\n");
                return;
        }
 
@@ -489,13 +501,13 @@ void waypoint_load_links_hardwired()
                if(!wp_from || wp_from.origin!=wp_from_pos)
                {
                        wp_from = findradius(wp_from_pos, 5);
-                       found = FALSE;
+                       found = false;
                        while(wp_from)
                        {
                                if(vlen(wp_from.origin-wp_from_pos)<5)
                                if(wp_from.classname == "waypoint")
                                {
-                                       found = TRUE;
+                                       found = true;
                                        break;
                                }
                                wp_from = wp_from.chain;
@@ -503,20 +515,20 @@ void waypoint_load_links_hardwired()
 
                        if(!found)
                        {
-                               print(strcat("NOTICE: Can not find waypoint at ", vtos(wp_from_pos), ". Path skipped\n"));
+                               LOG_INFO(strcat("NOTICE: Can not find waypoint at ", vtos(wp_from_pos), ". Path skipped\n"));
                                continue;
                        }
                }
 
                // Search "to" waypoint
                wp_to = findradius(wp_to_pos, 5);
-               found = FALSE;
+               found = false;
                while(wp_to)
                {
                        if(vlen(wp_to.origin-wp_to_pos)<5)
                        if(wp_to.classname == "waypoint")
                        {
-                               found = TRUE;
+                               found = true;
                                break;
                        }
                        wp_to = wp_to.chain;
@@ -524,23 +536,23 @@ void waypoint_load_links_hardwired()
 
                if(!found)
                {
-                       print(strcat("NOTICE: Can not find waypoint at ", vtos(wp_to_pos), ". Path skipped\n"));
+                       LOG_INFO(strcat("NOTICE: Can not find waypoint at ", vtos(wp_to_pos), ". Path skipped\n"));
                        continue;
                }
 
                ++c;
                waypoint_addlink(wp_from, wp_to);
-               wp_from.wphardwired = TRUE;
-               wp_to.wphardwired = TRUE;
+               wp_from.wphardwired = true;
+               wp_to.wphardwired = true;
        }
 
        fclose(file);
 
-       dprint("loaded ");
-       dprint(ftos(c));
-       dprint(" waypoint links from maps/");
-       dprint(mapname);
-       dprint(".waypoints.hardwired\n");
+       LOG_TRACE("loaded ");
+       LOG_TRACE(ftos(c));
+       LOG_TRACE(" waypoint links from maps/");
+       LOG_TRACE(mapname);
+       LOG_TRACE(".waypoints.hardwired\n");
 }
 
 entity waypoint_get_link(entity w, float i)
@@ -594,9 +606,9 @@ void waypoint_save_links()
        file = fopen(filename, FILE_WRITE);
        if (file < 0)
        {
-               print("waypoint links save to ");
-               print(filename);
-               print(" failed\n");
+               LOG_INFO("waypoint links save to ");
+               LOG_INFO(filename);
+               LOG_INFO(" failed\n");
        }
        c = 0;
        w = findchain(classname, "waypoint");
@@ -616,13 +628,13 @@ void waypoint_save_links()
                w = w.chain;
        }
        fclose(file);
-       botframe_cachedwaypointlinks = TRUE;
+       botframe_cachedwaypointlinks = true;
 
-       print("saved ");
-       print(ftos(c));
-       print(" waypoints links to maps/");
-       print(mapname);
-       print(".waypoints.cache\n");
+       LOG_INFO("saved ");
+       LOG_INFO(ftos(c));
+       LOG_INFO(" waypoints links to maps/");
+       LOG_INFO(mapname);
+       LOG_INFO(".waypoints.cache\n");
 }
 
 // save waypoints to gamedir/data/maps/mapname.waypoints
@@ -666,7 +678,7 @@ void waypoint_saveall()
                bprint(" failed\n");
        }
        waypoint_save_links();
-       botframe_loadedforcedlinks = FALSE;
+       botframe_loadedforcedlinks = false;
 }
 
 // load waypoints from file
@@ -700,26 +712,26 @@ float waypoint_loadall()
                                cwb = cwb + 1;
                }
                fclose(file);
-               dprint("loaded ");
-               dprint(ftos(cwp));
-               dprint(" waypoints and ");
-               dprint(ftos(cwb));
-               dprint(" wayboxes from maps/");
-               dprint(mapname);
-               dprint(".waypoints\n");
+               LOG_TRACE("loaded ");
+               LOG_TRACE(ftos(cwp));
+               LOG_TRACE(" waypoints and ");
+               LOG_TRACE(ftos(cwb));
+               LOG_TRACE(" wayboxes from maps/");
+               LOG_TRACE(mapname);
+               LOG_TRACE(".waypoints\n");
        }
        else
        {
-               dprint("waypoint load from ");
-               dprint(filename);
-               dprint(" failed\n");
+               LOG_TRACE("waypoint load from ");
+               LOG_TRACE(filename);
+               LOG_TRACE(" failed\n");
        }
        return cwp + cwb;
 }
 
 vector waypoint_fixorigin(vector position)
 {
-       tracebox(position + '0 0 1' * (1 - PL_MIN_z), PL_MIN, PL_MAX, position + '0 0 -512', MOVE_NOMONSTERS, world);
+       tracebox(position + '0 0 1' * (1 - PL_MIN.z), PL_MIN, PL_MAX, position + '0 0 -512', MOVE_NOMONSTERS, world);
        if(trace_fraction < 1)
                position = trace_endpos;
        //traceline(position, position + '0 0 -512', MOVE_NOMONSTERS, world);
@@ -796,7 +808,7 @@ void waypoint_spawnforteleporter(entity e, vector destination, float timetaken)
 }
 
 entity waypoint_spawnpersonal(vector position)
-{
+{SELFPARAM();
        entity w;
 
        // drop the waypoint to a proper location:
@@ -826,10 +838,10 @@ void botframe_showwaypointlinks()
                if (!player.isbot)
                if (player.flags & FL_ONGROUND || player.waterlevel > WATERLEVEL_NONE)
                {
-                       //navigation_testtracewalk = TRUE;
-                       head = navigation_findnearestwaypoint(player, FALSE);
+                       //navigation_testtracewalk = true;
+                       head = navigation_findnearestwaypoint(player, false);
                //      print("currently selected WP is ", etos(head), "\n");
-                       //navigation_testtracewalk = FALSE;
+                       //navigation_testtracewalk = false;
                        if (head)
                        {
                                w = head     ;if (w) te_lightning2(world, w.origin, player.origin);
@@ -893,7 +905,7 @@ float botframe_autowaypoints_createwp(vector v, entity p, .entity fld, float f)
                w = find(w, classname, "waypoint");
        }
 
-       waypoint_schedulerelink(p.fld = waypoint_spawn(v, v, f));
+       waypoint_schedulerelink(p.(fld) = waypoint_spawn(v, v, f));
        return 1;
 }
 
@@ -948,14 +960,14 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
                                                if(navigation_waypoint_will_link(w.origin, porg, p, walkfromwp, 1050))
                                                {
                                                        bestdist = d;
-                                                       p.fld = w;
+                                                       p.(fld) = w;
                                                }
                        }
                        w = find(w, classname, "waypoint");
                }
                if(bestdist < maxdist)
                {
-                       print("update chain to new nearest WP ", etos(p.fld), "\n");
+                       LOG_INFO("update chain to new nearest WP ", etos(p.(fld)), "\n");
                        return 0;
                }
 
@@ -964,7 +976,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
                        // we know maxdist < 2100
                        // so wp -> porg is still valid
                        // all is good
-                       p.fld = wp;
+                       p.(fld) = wp;
                        return 0;
                }
 
@@ -978,14 +990,14 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
                setorigin(p, save);
                if(w)
                {
-                       p.fld = w;
+                       p.(fld) = w;
                        return 0;
                }
        }
 
        tmin = 0;
        tmax = 1;
-       for(;;)
+       for (;;)
        {
                if(tmax - tmin < 0.001)
                {
@@ -1034,7 +1046,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
                tmax = t;
        }
 
-       print("spawning a waypoint for connecting to ", etos(wp), "\n");
+       LOG_INFO("spawning a waypoint for connecting to ", etos(wp), "\n");
        botframe_autowaypoints_createwp(o, p, fld, 0);
        return 1;
 }
@@ -1043,15 +1055,14 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
 .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);
+       float 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");
+       LOG_INFO("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, WAYPOINTFLAG_PROTECTED);
@@ -1061,15 +1072,16 @@ void botframe_deleteuselesswaypoints()
 {
        entity w, w1, w2;
        float i, j, k;
-       for (w = world; (w = findfloat(w, bot_pickup, TRUE)); )
+       for (w = world; (w = findfloat(w, bot_pickup, true)); )
        {
                // NOTE: this protects waypoints if they're the ONLY nearest
                // waypoint. That's the intention.
-               navigation_findnearestwaypoint(w, FALSE);  // Walk TO item.
-               navigation_findnearestwaypoint(w, TRUE);  // Walk FROM item.
+               navigation_findnearestwaypoint(w, false);  // Walk TO item.
+               navigation_findnearestwaypoint(w, true);  // Walk FROM item.
        }
        for (w = world; (w = find(w, classname, "waypoint")); )
        {
+               w.wpflags |= WAYPOINTFLAG_DEAD_END;
                w.wpflags &= ~WAYPOINTFLAG_USEFUL;
                // WP is useful if:
                if (w.wpflags & WAYPOINTFLAG_ITEM)
@@ -1097,11 +1109,17 @@ void botframe_deleteuselesswaypoints()
                                continue;
                        for (j = 0; j < 32; ++j)
                        {
-                               w2 = waypoint_get_link(w1, i);
+                               w2 = waypoint_get_link(w, j);
                                if (!w2)
                                        break;
+                               if (w1 == w2)
+                                       continue;
                                if (w2.wpflags & WAYPOINTFLAG_PERSONAL)
                                        continue;
+                               // If we got here, w1 != w2 exist with w1 -> w
+                               // and w -> w2. That means the waypoint is not
+                               // a dead end.
+                               w.wpflags &= ~WAYPOINTFLAG_DEAD_END;
                                for (k = 0; k < 32; ++k)
                                {
                                        if (waypoint_get_link(w1, k) == w2)
@@ -1109,23 +1127,27 @@ void botframe_deleteuselesswaypoints()
                                        // IF WE GET HERE, w is proven useful
                                        // to get from w1 to w2!
                                        w.wpflags |= WAYPOINTFLAG_USEFUL;
-                                       continue;
+                                       goto next;
                                }
                        }
+:next
                }
        }
+       // d) The waypoint is a dead end. Dead end waypoints must be kept as
+       //     they are needed to complete routes while autowaypointing.
+
        for (w = world; (w = find(w, classname, "waypoint")); )
        {
-               if (!(w.wpflags & WAYPOINTFLAG_USEFUL))
+               if (!(w.wpflags & (WAYPOINTFLAG_USEFUL | WAYPOINTFLAG_DEAD_END)))
                {
-                       printf("Removed a waypoint at %v. Try again for more!\n", w.origin);
+                       LOG_INFOF("Removed a waypoint at %v. Try again for more!\n", w.origin);
                        te_explosion(w.origin);
                        waypoint_remove(w);
                        break;
                }
        }
        for (w = world; (w = find(w, classname, "waypoint")); )
-               w.wpflags &= ~WAYPOINTFLAG_USEFUL; // temp flag
+               w.wpflags &= ~(WAYPOINTFLAG_USEFUL | WAYPOINTFLAG_DEAD_END); // temp flag
 }
 
 void botframe_autowaypoints()
@@ -1136,11 +1158,13 @@ void botframe_autowaypoints()
                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);
+               //botframe_autowaypoints_fix(p, false, botframe_autowaypoints_lastwp0);
+               botframe_autowaypoints_fix(p, true, botframe_autowaypoints_lastwp1);
                //te_explosion(p.botframe_autowaypoints_lastwp0.origin);
        }
 
-       botframe_deleteuselesswaypoints();
+       if (autocvar_g_waypointeditor_auto >= 2) {
+               botframe_deleteuselesswaypoints();
+       }
 }