]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
more autowaypoint stuff
authorRudolf Polzer <divverent@xonotic.org>
Sun, 28 Aug 2011 17:31:58 +0000 (19:31 +0200)
committerRudolf Polzer <divverent@xonotic.org>
Sun, 28 Aug 2011 17:31:58 +0000 (19:31 +0200)
qcsrc/server/bot/navigation.qc
qcsrc/server/bot/waypoints.qc

index 968e760b8b721caff6b71cd452af93dd183fe726..71016d5032514af649d8c637244803c928c383a9 100644 (file)
@@ -326,11 +326,35 @@ void navigation_poproute()
        self.goalstack31 = world;
 };
 
+float navigation_waypoint_will_link(vector v, vector org, entity ent, float walkfromwp, float bestdist)
+{
+       float dist;
+       dist = vlen(v - org);
+       if (bestdist > dist)
+       {
+               traceline(v, org, TRUE, ent);
+               if (trace_fraction == 1)
+               {
+                       if (walkfromwp)
+                       {
+                               if (tracewalk(ent, v, PL_MIN, PL_MAX, org, bot_navigation_movemode))
+                                       return TRUE;
+                       }
+                       else
+                       {
+                               if (tracewalk(ent, org, PL_MIN, PL_MAX, v, bot_navigation_movemode))
+                                       return TRUE;
+                       }
+               }
+       }
+       return FALSE;
+}
+
 // find the spawnfunc_waypoint near a dynamic goal such as a dropped weapon
-entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
+entity navigation_findnearestwaypoint_withdist(entity ent, float walkfromwp, float bestdist)
 {
        local entity waylist, w, best;
-       local float dist, bestdist;
+       local float dist;
        local vector v, org, pm1, pm2;
        pm1 = ent.origin + ent.mins;
        pm2 = ent.origin + ent.maxs;
@@ -356,7 +380,6 @@ entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
                te_plasmaburn(org);
 
        best = world;
-       bestdist = 1050;
 
        // box check failed, try walk
        w = waylist;
@@ -376,36 +399,20 @@ entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
                        }
                        else
                                v = w.origin;
-                       dist = vlen(v - org);
-                       if (bestdist > dist)
+                       if(navigation_waypoint_will_link(v, org, ent, walkfromwp, bestdist))
                        {
-                               traceline(v, org, TRUE, ent);
-                               if (trace_fraction == 1)
-                               {
-                                       if (walkfromwp)
-                                       {
-                                               //print("^1can I reach ", vtos(org), " from ", vtos(v), "?\n");
-                                               if (tracewalk(ent, v, PL_MIN, PL_MAX, org, bot_navigation_movemode))
-                                               {
-                                                       bestdist = dist;
-                                                       best = w;
-                                               }
-                                       }
-                                       else
-                                       {
-                                               if (tracewalk(ent, org, PL_MIN, PL_MAX, v, bot_navigation_movemode))
-                                               {
-                                                       bestdist = dist;
-                                                       best = w;
-                                               }
-                                       }
-                               }
+                               bestdist = dist;
+                               best = w;
                        }
                }
                w = w.chain;
        }
        return best;
 }
+entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
+{
+       return navigation_findnearestwaypoint_withdist(ent, walkfromwp, 1050);
+}
 
 // finds the waypoints near the bot initiating a navigation query
 float navigation_markroutes_nearestwaypoints(entity waylist, float maxdist)
index eb08b38c5d68db83ff35bb2bed7a0492161b61ac..5a0bb1e7c428ec69f236145e997ddbe618737f8d 100644 (file)
@@ -877,62 +877,136 @@ void botframe_showwaypointlinks()
        }
 };
 
-// automatically create missing waypoints
-.float lastwaypointtime0;
-.float lastwaypointtime1;
-void botframe_autowaypoints_fix(entity p, float walkfromwp, .float last)
+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;
+}
+
+// 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)
 {
-       float t;
-       entity wp;
+       // 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;
-       float tmin, tmax;
        vector save;
-       
-       wp = navigation_findnearestwaypoint(p, walkfromwp);
+
+       if(!botframe_autowaypoints_fixdown(p.origin))
+               return -2;
+       porg = trace_endpos;
+
        if(wp)
-               return;
+       {
+               // if nearest WP from here is linked to wp, everything is fine
+               w = navigation_findnearestwaypoint(p, walkfromwp);
+               if(w != wp)
+               {
+                       if(navigation_waypoint_will_link(w.origin, wp.origin, p, walkfromwp, 1050))
+                       {
+                               print("update chain from ", etos(p.fld), " to new nearest WP ", etos(w), "\n");
+                               p.fld = w;
+                               return 0;
+                       }
+               }
+               if(navigation_waypoint_will_link(p.origin, wp.origin, p, walkfromwp, 1050))
+               {
+                       p.fld = wp;
+                       return 0;
+               }
+       }
+       else
+       {
+               w = navigation_findnearestwaypoint(p, walkfromwp);
+               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);
-               save = p.origin;
-               setorigin(p, o);
-               wp = navigation_findnearestwaypoint(p, walkfromwp);
-               setorigin(p, save);
+               if(!botframe_autowaypoints_fixdown(o))
+                       return -1;
+               o = trace_endpos;
+
                if(wp)
                {
-                       if(walkfromwp)
-                       {
-                               if(tracewalk(p, o, PL_MIN, PL_MAX, p.origin, bot_navigation_movemode))
-                                       break;
-                       }
-                       else
+                       if(!navigation_waypoint_will_link(wp.origin, o, p, walkfromwp, 1050))
                        {
-                               if(tracewalk(p, p.origin, PL_MIN, PL_MAX, o, bot_navigation_movemode))
-                                       break;
+                               // we cannot walk from wp.origin to o
+                               // get closer to tmax
+                               tmin = t;
+                               continue;
                        }
-                       // if we get here: o has a nearest waypoint, but can't reach us
-                       // i.e. move towards current location
-                       tmax = t;
                }
                else
                {
-                       // if we get here: o has no nearest waypoint
-                       // i.e. move closer to to the past
-                       tmin = t;
-               }
-               if(tmax - tmin < 0.01)
-               {
-                       print("Cannot link waypoints - didn't find a good new WP position\n");
-                       return;
+                       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;
        }
 
-       waypoint_schedulerelink(waypoint_spawn(o, o, 0));
-       p.last = max(1, time - t);
+       print("spawning a waypoint for connecting to ", etos(wp), "\n");
+       waypoint_schedulerelink(p.fld = waypoint_spawn(o, o, 0));
+       print("new waypoint is ", etos(p.fld), "\n");
+       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
+       waypoint_schedulerelink(p.fld = waypoint_spawn(trace_endpos, trace_endpos, 0));
 }
 void botframe_autowaypoints()
 {
@@ -940,7 +1014,11 @@ void botframe_autowaypoints()
        entity wp0, wp1;
        FOR_EACH_REALPLAYER(p)
        {
-               botframe_autowaypoints_fix(p, FALSE, lastwaypointtime0);
-               botframe_autowaypoints_fix(p, TRUE, lastwaypointtime1);
+               if(p.deadflag)
+                       continue;
+               if(!(p.flags & FL_ONGROUND))
+                       continue;
+               botframe_autowaypoints_fix(p, FALSE, botframe_autowaypoints_lastwp0);
+               botframe_autowaypoints_fix(p, TRUE, botframe_autowaypoints_lastwp1);
        }
 }