]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/waypoints.qc
Fix compilation with gmqcc.
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / waypoints.qc
index e2bcc5bd628e341000f7273cd9d7dee80da44167..8e9ae6b911e745cfb58bf6acb7132792f3d898eb 100644 (file)
@@ -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;
@@ -573,19 +565,20 @@ 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 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  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;
@@ -686,18 +679,15 @@ 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)
+                       if not(s)
                                break;
                        m2 = stov(s);
                        s = fgets(file);
-                       if (!s)
+                       if not(s)
                                break;
                        fl = stof(s);
                        waypoint_spawn(m1, m2, fl);
@@ -877,3 +867,204 @@ void botframe_showwaypointlinks()
                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;
+       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);
+       }
+}
+