Merge remote-tracking branch 'origin/master' into samual/combined_updates
authorSamual Lenks <samual@xonotic.org>
Sun, 9 Mar 2014 01:12:14 +0000 (20:12 -0500)
committerSamual Lenks <samual@xonotic.org>
Sun, 9 Mar 2014 01:12:14 +0000 (20:12 -0500)
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/server/bot/navigation.qc
qcsrc/server/bot/waypoints.qc
qcsrc/server/bot/waypoints.qh

index d668a38..ae903d5 100644 (file)
@@ -2803,3 +2803,18 @@ float Mod_Q1BSP_NativeContentsFromSuperContents(float supercontents)
        return CONTENT_EMPTY;
 }
 #endif
+
+vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
+{
+       return
+               (c - 2 * b + a) * (t * t) +
+               (b - a) * (2 * t) +
+               a;
+}
+
+vector bezier_quadratic_getderivative(vector a, vector b, vector c, float t)
+{
+       return
+               (c - 2 * b + a) * (2 * t) +
+               (b - a) * 2;
+}
index bb65e31..b65f87b 100644 (file)
@@ -442,3 +442,7 @@ float Announcer_PickNumber(float type, float num);
 float Mod_Q1BSP_SuperContentsFromNativeContents(float nativecontents);
 float Mod_Q1BSP_NativeContentsFromSuperContents(float supercontents);
 #endif
+
+// Quadratic splines (bezier)
+vector bezier_quadratic_getpoint(vector a, vector p, vector b, float t);
+vector bezier_quadratic_getderivative(vector a, vector p, vector b, float t);
index 691ce3e..0facbf0 100644 (file)
@@ -366,7 +366,7 @@ float navigation_waypoint_will_link(vector v, vector org, entity ent, float walk
 }
 
 // find the spawnfunc_waypoint near a dynamic goal such as a dropped weapon
-entity navigation_findnearestwaypoint_withdist(entity ent, float walkfromwp, float bestdist)
+entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfromwp, float bestdist, entity except)
 {
        entity waylist, w, best;
        vector v, org, pm1, pm2;
@@ -380,7 +380,7 @@ entity navigation_findnearestwaypoint_withdist(entity ent, float walkfromwp, flo
        while (w)
        {
                // if object is touching spawnfunc_waypoint
-               if(w != ent)
+               if(w != ent && w != except)
                        if (boxesoverlap(pm1, pm2, w.absmin, w.absmax))
                                return w;
                w = w.chain;
@@ -426,7 +426,14 @@ entity navigation_findnearestwaypoint_withdist(entity ent, float walkfromwp, flo
 }
 entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
 {
-       return navigation_findnearestwaypoint_withdist(ent, walkfromwp, 1050);
+       entity wp = navigation_findnearestwaypoint_withdist_except(ent, walkfromwp, 1050, world);
+       if (autocvar_g_waypointeditor_auto)
+       {
+               entity wp2 = navigation_findnearestwaypoint_withdist_except(ent, walkfromwp, 1050, wp);
+               if (!wp2)
+                       wp.wpflags |= WAYPOINTFLAG_PROTECTED;
+       }
+       return wp;
 }
 
 // finds the waypoints near the bot initiating a navigation query
index 78bf0f2..da0b350 100644 (file)
@@ -543,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()
 {
@@ -565,44 +605,7 @@ void waypoint_save_links()
                for(i=0;i<32;++i)
                {
                        // :S
-                       link = world;
-                       switch(i)
-                       {
-                               //      for i in $(seq -w 0 31); do echo "case $i:link = w.wp$i; break;"; done;
-                               case  0:link = w.wp00; break;
-                               case  1:link = w.wp01; break;
-                               case  2:link = w.wp02; break;
-                               case  3:link = w.wp03; break;
-                               case  4:link = w.wp04; break;
-                               case  5:link = w.wp05; break;
-                               case  6:link = w.wp06; break;
-                               case  7:link = w.wp07; break;
-                               case  8:link = w.wp08; break;
-                               case  9: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;
 
@@ -876,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;
 
@@ -890,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;
 }
 
@@ -916,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;
@@ -993,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)
@@ -1032,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;
 }
 
@@ -1051,7 +1054,78 @@ 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()
@@ -1066,5 +1140,7 @@ void botframe_autowaypoints()
                botframe_autowaypoints_fix(p, TRUE, botframe_autowaypoints_lastwp1);
                //te_explosion(p.botframe_autowaypoints_lastwp0.origin);
        }
+
+       botframe_deleteuselesswaypoints();
 }
 
index 5a75551..9ac9240 100644 (file)
@@ -7,6 +7,8 @@ const float WAYPOINTFLAG_ITEM = 4194304;
 const float WAYPOINTFLAG_TELEPORT = 2097152;
 const float WAYPOINTFLAG_NORELINK = 1048576;
 const float WAYPOINTFLAG_PERSONAL = 524288;
+const float WAYPOINTFLAG_PROTECTED = 262144;  // Useless WP detection never kills these.
+const float WAYPOINTFLAG_USEFUL = 131072;  // Useless WP detection temporary flag.
 
 // fields you can query using prvm_global server to get some statistics about waypoint linking culling
 float relink_total, relink_walkculled, relink_pvsculled, relink_lengthculled;