]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/waypoints.qc
Fix HMG
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / waypoints.qc
index 4db72e407da5676ad73a15eab5a3c170a1aafd67..da0b3508941ecaec1fdf0205e0b464be0c971978 100644 (file)
@@ -6,7 +6,7 @@ entity waypoint_spawn(vector m1, vector m2, float f)
        entity w;
        w = find(world, classname, "waypoint");
 
-       if not(f & WAYPOINTFLAG_PERSONAL)
+       if (!(f & WAYPOINTFLAG_PERSONAL))
        while (w)
        {
                // if a matching spawnfunc_waypoint already exists, don't add a duplicate
@@ -360,8 +360,8 @@ void waypoint_schedulerelinkall()
 float waypoint_load_links()
 {
        string filename, s;
-       float file, tokens, c, found;
-       entity wp_from, wp_to;
+       float file, tokens, c = 0, found;
+       entity wp_from = world, wp_to;
        vector wp_to_pos, wp_from_pos;
        filename = strcat("maps/", mapname);
        filename = strcat(filename, ".waypoints.cache");
@@ -375,12 +375,8 @@ float waypoint_load_links()
                return FALSE;
        }
 
-       while (1)
+       while ((s = fgets(file)))
        {
-               s = fgets(file);
-               if (!s)
-                       break;
-
                tokens = tokenizebyseparator(s, "*");
 
                if (tokens!=2)
@@ -394,7 +390,7 @@ float waypoint_load_links()
                wp_to_pos       = stov(argv(1));
 
                // Search "from" waypoint
-               if(wp_from.origin!=wp_from_pos)
+               if(!wp_from || wp_from.origin!=wp_from_pos)
                {
                        wp_from = findradius(wp_from_pos, 1);
                        found = FALSE;
@@ -456,8 +452,8 @@ float waypoint_load_links()
 void waypoint_load_links_hardwired()
 {
        string filename, s;
-       float file, tokens, c, found;
-       entity wp_from, wp_to;
+       float file, tokens, c = 0, found;
+       entity wp_from = world, wp_to;
        vector wp_to_pos, wp_from_pos;
        filename = strcat("maps/", mapname);
        filename = strcat(filename, ".waypoints.hardwired");
@@ -473,12 +469,8 @@ void waypoint_load_links_hardwired()
                return;
        }
 
-       for (;;)
+       while ((s = fgets(file)))
        {
-               s = fgets(file);
-               if (!s)
-                       break;
-
                if(substring(s, 0, 2)=="//")
                        continue;
 
@@ -494,7 +486,7 @@ void waypoint_load_links_hardwired()
                wp_to_pos       = stov(argv(1));
 
                // Search "from" waypoint
-               if(wp_from.origin!=wp_from_pos)
+               if(!wp_from || wp_from.origin!=wp_from_pos)
                {
                        wp_from = findradius(wp_from_pos, 5);
                        found = FALSE;
@@ -551,6 +543,46 @@ void waypoint_load_links_hardwired()
        dprint(".waypoints.hardwired\n");
 }
 
+entity waypoint_get_link(entity w, float i)
+{
+       switch(i)
+       {
+               case  0:return w.wp00;
+               case  1:return w.wp01;
+               case  2:return w.wp02;
+               case  3:return w.wp03;
+               case  4:return w.wp04;
+               case  5:return w.wp05;
+               case  6:return w.wp06;
+               case  7:return w.wp07;
+               case  8:return w.wp08;
+               case  9:return w.wp09;
+               case 10:return w.wp10;
+               case 11:return w.wp11;
+               case 12:return w.wp12;
+               case 13:return w.wp13;
+               case 14:return w.wp14;
+               case 15:return w.wp15;
+               case 16:return w.wp16;
+               case 17:return w.wp17;
+               case 18:return w.wp18;
+               case 19:return w.wp19;
+               case 20:return w.wp20;
+               case 21:return w.wp21;
+               case 22:return w.wp22;
+               case 23:return w.wp23;
+               case 24:return w.wp24;
+               case 25:return w.wp25;
+               case 26:return w.wp26;
+               case 27:return w.wp27;
+               case 28:return w.wp28;
+               case 29:return w.wp29;
+               case 30:return w.wp30;
+               case 31:return w.wp31;
+               default:return world;
+       }
+}
+
 // Save all waypoint links to a file
 void waypoint_save_links()
 {
@@ -573,43 +605,7 @@ void waypoint_save_links()
                for(i=0;i<32;++i)
                {
                        // :S
-                       switch(i)
-                       {
-                               //      for i in $(seq -w 0 31); do echo "case $i:link = w.wp$i; break;"; done;
-                               case 00:link = w.wp00; break;
-                               case 01:link = w.wp01; break;
-                               case 02:link = w.wp02; break;
-                               case 03:link = w.wp03; break;
-                               case 04:link = w.wp04; break;
-                               case 05:link = w.wp05; break;
-                               case 06:link = w.wp06; break;
-                               case 07:link = w.wp07; break;
-                               case 08:link = w.wp08; break;
-                               case 09:link = w.wp09; break;
-                               case 10:link = w.wp10; break;
-                               case 11:link = w.wp11; break;
-                               case 12:link = w.wp12; break;
-                               case 13:link = w.wp13; break;
-                               case 14:link = w.wp14; break;
-                               case 15:link = w.wp15; break;
-                               case 16:link = w.wp16; break;
-                               case 17:link = w.wp17; break;
-                               case 18:link = w.wp18; break;
-                               case 19:link = w.wp19; break;
-                               case 20:link = w.wp20; break;
-                               case 21:link = w.wp21; break;
-                               case 22:link = w.wp22; break;
-                               case 23:link = w.wp23; break;
-                               case 24:link = w.wp24; break;
-                               case 25:link = w.wp25; break;
-                               case 26:link = w.wp26; break;
-                               case 27:link = w.wp27; break;
-                               case 28:link = w.wp28; break;
-                               case 29:link = w.wp29; break;
-                               case 30:link = w.wp30; break;
-                               case 31:link = w.wp31; break;
-                       }
-
+                       link = waypoint_get_link(w, i);
                        if(link==world)
                                continue;
 
@@ -686,11 +682,8 @@ float waypoint_loadall()
        file = fopen(filename, FILE_READ);
        if (file >= 0)
        {
-               while (1)
+               while ((s = fgets(file)))
                {
-                       s = fgets(file);
-                       if (!s)
-                               break;
                        m1 = stov(s);
                        s = fgets(file);
                        if (!s)
@@ -886,7 +879,7 @@ float botframe_autowaypoints_fixdown(vector v)
        return 1;
 }
 
-float botframe_autowaypoints_createwp(vector v, entity p, .entity fld)
+float botframe_autowaypoints_createwp(vector v, entity p, .entity fld, float f)
 {
        entity w;
 
@@ -900,7 +893,7 @@ float botframe_autowaypoints_createwp(vector v, entity p, .entity fld)
                w = find(w, classname, "waypoint");
        }
 
-       waypoint_schedulerelink(p.fld = waypoint_spawn(v, v, 0));
+       waypoint_schedulerelink(p.fld = waypoint_spawn(v, v, f));
        return 1;
 }
 
@@ -926,7 +919,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
 
        if(wp)
        {
-               // if any WP w fulfills wp -> w -> porg, then switch from wp to w
+               // if any WP w fulfills wp -> w -> porg and w is closer than wp, then switch from wp to w
 
                // if wp -> porg, then OK
                float maxdist;
@@ -1003,7 +996,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
                t = (tmin + tmax) * 0.5;
                o = antilag_takebackorigin(p, time - t);
                if(!botframe_autowaypoints_fixdown(o))
-                       return -1;
+                       return -2;
                o = trace_endpos;
 
                if(wp)
@@ -1042,7 +1035,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
        }
 
        print("spawning a waypoint for connecting to ", etos(wp), "\n");
-       botframe_autowaypoints_createwp(o, p, fld);
+       botframe_autowaypoints_createwp(o, p, fld, 0);
        return 1;
 }
 
@@ -1061,13 +1054,83 @@ void botframe_autowaypoints_fix(entity p, float walkfromwp, .entity fld)
        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);
+       botframe_autowaypoints_createwp(trace_endpos, p, fld, WAYPOINTFLAG_PROTECTED);
+}
+
+void botframe_deleteuselesswaypoints()
+{
+       entity w, w1, w2;
+       float i, j, k;
+       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.
+       }
+       for (w = world; (w = find(w, classname, "waypoint")); )
+       {
+               w.wpflags &= ~WAYPOINTFLAG_USEFUL;
+               // WP is useful if:
+               if (w.wpflags & WAYPOINTFLAG_ITEM)
+                       w.wpflags |= WAYPOINTFLAG_USEFUL;
+               if (w.wpflags & WAYPOINTFLAG_TELEPORT)
+                       w.wpflags |= WAYPOINTFLAG_USEFUL;
+               if (w.wpflags & WAYPOINTFLAG_PROTECTED)
+                       w.wpflags |= WAYPOINTFLAG_USEFUL;
+               // b) WP is closest WP for an item/spawnpoint/other entity
+               //    This has been done above by protecting these WPs.
+       }
+       // c) There are w1, w, w2 so that w1 -> w, w -> w2 and not w1 -> w2.
+       for (w1 = world; (w1 = find(w1, classname, "waypoint")); )
+       {
+               if (w1.wpflags & WAYPOINTFLAG_PERSONAL)
+                       continue;
+               for (i = 0; i < 32; ++i)
+               {
+                       w = waypoint_get_link(w1, i);
+                       if (!w)
+                               break;
+                       if (w.wpflags & WAYPOINTFLAG_PERSONAL)
+                               continue;
+                       if (w.wpflags & WAYPOINTFLAG_USEFUL)
+                               continue;
+                       for (j = 0; j < 32; ++j)
+                       {
+                               w2 = waypoint_get_link(w1, i);
+                               if (!w2)
+                                       break;
+                               if (w2.wpflags & WAYPOINTFLAG_PERSONAL)
+                                       continue;
+                               for (k = 0; k < 32; ++k)
+                               {
+                                       if (waypoint_get_link(w1, k) == w2)
+                                               continue;
+                                       // IF WE GET HERE, w is proven useful
+                                       // to get from w1 to w2!
+                                       w.wpflags |= WAYPOINTFLAG_USEFUL;
+                                       continue;
+                               }
+                       }
+               }
+       }
+       for (w = world; (w = find(w, classname, "waypoint")); )
+       {
+               if (!(w.wpflags & WAYPOINTFLAG_USEFUL))
+               {
+                       printf("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
 }
 
 void botframe_autowaypoints()
 {
        entity p;
-       entity wp0, wp1;
        FOR_EACH_REALPLAYER(p)
        {
                if(p.deadflag)
@@ -1077,5 +1140,7 @@ void botframe_autowaypoints()
                botframe_autowaypoints_fix(p, TRUE, botframe_autowaypoints_lastwp1);
                //te_explosion(p.botframe_autowaypoints_lastwp0.origin);
        }
+
+       botframe_deleteuselesswaypoints();
 }