Merge master
authormand1nga <mand1nga@xonotic.org>
Sun, 4 Dec 2011 16:12:31 +0000 (13:12 -0300)
committermand1nga <mand1nga@xonotic.org>
Sun, 4 Dec 2011 16:12:31 +0000 (13:12 -0300)
1  2 
defaultXonotic.cfg
qcsrc/server/autocvars.qh
qcsrc/server/bot/bot.qc
qcsrc/server/bot/navigation.qc
qcsrc/server/bot/waypoints.qc

Simple merge
@@@ -1017,11 -1029,7 +1029,8 @@@ float autocvar_g_turrets_unit_walker_tu
  float autocvar_g_turrets_unit_walker_turn_swim;
  float autocvar_g_use_ammunition;
  float autocvar_g_waypointeditor;
 +float autocvar_g_waypointeditor_auto;
  float autocvar_g_waypoints_for_items;
- float autocvar_g_waypointsprite_deadlifetime;
- float autocvar_g_waypointsprite_deployed_lifetime;
- float autocvar_g_waypointsprite_limitedrange;
  float autocvar_g_weapon_charge_colormod_blue_full;
  float autocvar_g_weapon_charge_colormod_blue_half;
  float autocvar_g_weapon_charge_colormod_green_full;
Simple merge
@@@ -330,37 -330,14 +330,39 @@@ void navigation_poproute(
        self.goalstack29 = self.goalstack30;
        self.goalstack30 = self.goalstack31;
        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 vector v, org, pm1, pm2;
+       entity waylist, w, best;
 -      float dist, bestdist;
++      float dist;
+       vector v, org, pm1, pm2;
++
        pm1 = ent.origin + ent.mins;
        pm2 = ent.origin + ent.maxs;
        waylist = findchain(classname, "waypoint");
@@@ -876,204 -876,4 +876,206 @@@ 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;
 +      entity wp0, wp1;
 +      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);
 +      }
 +}
++