Merge branch 'master' into terencehill/bot_waypoints
authorterencehill <piuntn@gmail.com>
Wed, 6 Sep 2017 16:36:50 +0000 (18:36 +0200)
committerterencehill <piuntn@gmail.com>
Wed, 6 Sep 2017 16:36:50 +0000 (18:36 +0200)
1  2 
qcsrc/server/command/sv_cmd.qc
qcsrc/server/sv_main.qc

@@@ -1095,9 -1095,15 +1095,15 @@@ void GameCommand_moveplayer(float reque
  
                                                                // If so, lets continue and finally move the player
                                                                client.team_forced = 0;
-                                                               MoveToTeam(client, team_id, 6);
-                                                               successful = strcat(successful, (successful ? ", " : ""), playername(client, false));
-                                                               LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ") has been moved to the ", Team_ColoredFullName(team_id), "^7.");
+                                                               if (MoveToTeam(client, team_id, 6))
+                                                               {
+                                                                       successful = strcat(successful, (successful ? ", " : ""), playername(client, false));
+                                                                       LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ") has been moved to the ", Team_ColoredFullName(team_id), "^7.");
+                                                               }
+                                                               else
+                                                               {
+                                                                       LOG_INFO("Unable to move player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ")");
+                                                               }
                                                                continue;
                                                        }
                                                        else
@@@ -1568,13 -1574,11 +1574,13 @@@ void GameCommand_trace(float request, f
  
                                case "walk":
                                {
 -                                      if (argc == 4)
 +                                      if (argc == 4 || argc == 5)
                                        {
                                                e = nextent(NULL);
 -                                              if (tracewalk(e, stov(argv(2)), e.mins, e.maxs, stov(argv(3)), MOVE_NORMAL)) LOG_INFO("can walk");
 -                                              else LOG_INFO("cannot walk");
 +                                              if (tracewalk(e, stov(argv(2)), e.mins, e.maxs, stov(argv(3)), stof(argv(4)), MOVE_NORMAL))
 +                                                      LOG_INFO("can walk");
 +                                              else
 +                                                      LOG_INFO("cannot walk");
                                                return;
                                        }
                                }
                        LOG_INFO("Incorrect parameters for ^2trace^7");
                case CMD_REQUEST_USAGE:
                {
 -                      LOG_INFO("Usage:^3 sv_cmd trace command (startpos endpos)");
 +                      LOG_INFO("Usage:^3 sv_cmd trace command [startpos endpos] [endpos_height]");
 +                      LOG_INFO("  Where startpos and endpos are parameters for 'walk' and 'showline' commands,");
 +                      LOG_INFO("  'endpos_height' is an optional parameter for 'walk' command,");
                        LOG_INFO("  Full list of commands here: \"debug, debug2, walk, showline.\"");
                        LOG_INFO("See also: ^2bbox, gettaginfo^7");
                        return;
diff --combined qcsrc/server/sv_main.qc
@@@ -217,6 -217,8 +217,6 @@@ void StartFrame(
        if (timeout_status == TIMEOUT_LEADTIME) // just before the timeout (when timeout_status will be TIMEOUT_ACTIVE)
                orig_slowmo = autocvar_slowmo; // slowmo will be restored after the timeout
  
 -      skill = autocvar_skill;
 -
        // detect when the pre-game countdown (if any) has ended and the game has started
        bool game_delay = (time < game_starttime);
        if (autocvar_sv_eventlog && game_delay_last && !game_delay)
  .string gametypefilter;
  .string cvarfilter;
  bool DoesQ3ARemoveThisEntity(entity this);
+ /**
+  * Evaluate an expression of the form: [+ | -]? [var[op]val | [op]var | val | var] ...
+  * +: all must match. this is the default
+  * -: one must NOT match
+  *
+  * var>x
+  * var<x
+  * var>=x
+  * var<=x
+  * var==x
+  * var!=x
+  * var===x
+  * var!==x
+  */
+ bool expr_evaluate(string s)
+ {
+     bool ret = false;
+     if (str2chr(s, 0) == '+') {
+         s = substring(s, 1, -1);
+     } else if (str2chr(s, 0) == '-') {
+         ret = true;
+         s = substring(s, 1, -1);
+     }
+     bool expr_fail = false;
+     for (int i = 0, n = tokenize_console(s); i < n; ++i) {
+         int o;
+         string k, v;
+         s = argv(i);
+         #define X(expr) \
+             if (expr) { \
+                 continue; \
+             } else { \
+                 expr_fail = true; \
+                 break; \
+             }
+         #define BINOP(op, len, expr) \
+             if ((o = strstrofs(s, op, 0)) >= 0) { \
+                 k = substring(s, 0, o); \
+                 v = substring(s, o + len, -1); \
+                 X(expr); \
+             }
+         BINOP(">=", 2, cvar(k) >= stof(v));
+         BINOP("<=", 2, cvar(k) <= stof(v));
+         BINOP(">",  1, cvar(k) >  stof(v));
+         BINOP("<",  1, cvar(k) <  stof(v));
+         BINOP("==", 2, cvar(k) == stof(v));
+         BINOP("!=", 2, cvar(k) != stof(v));
+         BINOP("===", 3, cvar_string(k) == v);
+         BINOP("!==", 3, cvar_string(k) != v);
+         {
+             k = s;
+             bool b = true;
+             if (str2chr(k, 0) == '!') {
+                 k = substring(s, 1, -1);
+                 b = false;
+             }
+             float f = stof(k);
+             bool isnum = ftos(f) == k;
+             X(boolean(isnum ? f : cvar(k)) == b);
+         }
+         #undef BINOP
+         #undef X
+     }
+     if (!expr_fail) {
+         ret = !ret;
+     }
+     // now ret is true if we want to keep the item, and false if we want to get rid of it
+     return ret;
+ }
  void SV_OnEntityPreSpawnFunction(entity this)
  {
        __spawnfunc_expecting = true;
        if (this.gametypefilter != "")
        if (!isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, this.gametypefilter))
        {
-               delete(this);
-               __spawnfunc_expecting = false;
-               return;
+               goto cleanup;
        }
-       if(this.cvarfilter != "")
-       {
-               float n, i, o, inv;
-               string s, k, v;
-               inv = 0;
-               s = this.cvarfilter;
-               if(substring(s, 0, 1) == "+")
-               {
-                       s = substring(s, 1, -1);
-               }
-               else if(substring(s, 0, 1) == "-")
-               {
-                       inv = 1;
-                       s = substring(s, 1, -1);
-               }
-               n = tokenize_console(s);
-               for(i = 0; i < n; ++i)
-               {
-                       s = argv(i);
-                       // syntax:
-                       // var>x
-                       // var<x
-                       // var>=x
-                       // var<=x
-                       // var==x
-                       // var!=x
-                       // var===x
-                       // var!==x
-                       if((o = strstrofs(s, ">=", 0)) >= 0)
-                       {
-                               k = substring(s, 0, o);
-                               v = substring(s, o+2, -1);
-                               if(cvar(k) < stof(v))
-                                       goto cvar_fail;
-                       }
-                       else if((o = strstrofs(s, "<=", 0)) >= 0)
-                       {
-                               k = substring(s, 0, o);
-                               v = substring(s, o+2, -1);
-                               if(cvar(k) > stof(v))
-                                       goto cvar_fail;
-                       }
-                       else if((o = strstrofs(s, ">", 0)) >= 0)
-                       {
-                               k = substring(s, 0, o);
-                               v = substring(s, o+1, -1);
-                               if(cvar(k) <= stof(v))
-                                       goto cvar_fail;
-                       }
-                       else if((o = strstrofs(s, "<", 0)) >= 0)
-                       {
-                               k = substring(s, 0, o);
-                               v = substring(s, o+1, -1);
-                               if(cvar(k) >= stof(v))
-                                       goto cvar_fail;
-                       }
-                       else if((o = strstrofs(s, "==", 0)) >= 0)
-                       {
-                               k = substring(s, 0, o);
-                               v = substring(s, o+2, -1);
-                               if(cvar(k) != stof(v))
-                                       goto cvar_fail;
-                       }
-                       else if((o = strstrofs(s, "!=", 0)) >= 0)
-                       {
-                               k = substring(s, 0, o);
-                               v = substring(s, o+2, -1);
-                               if(cvar(k) == stof(v))
-                                       goto cvar_fail;
-                       }
-                       else if((o = strstrofs(s, "===", 0)) >= 0)
-                       {
-                               k = substring(s, 0, o);
-                               v = substring(s, o+2, -1);
-                               if(cvar_string(k) != v)
-                                       goto cvar_fail;
-                       }
-                       else if((o = strstrofs(s, "!==", 0)) >= 0)
-                       {
-                               k = substring(s, 0, o);
-                               v = substring(s, o+2, -1);
-                               if(cvar_string(k) == v)
-                                       goto cvar_fail;
-                       }
-                       else if(substring(s, 0, 1) == "!")
-                       {
-                               k = substring(s, 1, -1);
-                               if(cvar(k))
-                                       goto cvar_fail;
-                       }
-                       else
-                       {
-                               k = s;
-                               if (!cvar(k))
-                                       goto cvar_fail;
-                       }
-               }
-               inv = !inv;
- LABEL(cvar_fail)
-               // now inv is 1 if we want to keep the item, and 0 if we want to get rid of it
-               if (!inv)
-               {
-                       //print("cvarfilter fail\n");
-                       delete(this);
-                       __spawnfunc_expecting = false;
-                       return;
-               }
+       if (this.cvarfilter != "" && !expr_evaluate(this.cvarfilter)) {
+         goto cleanup;
        }
  
-       if(DoesQ3ARemoveThisEntity(this))
-       {
-               delete(this);
-               __spawnfunc_expecting = false;
-               return;
+       if (DoesQ3ARemoveThisEntity(this)) {
+               goto cleanup;
        }
  
        set_movetype(this, this.movetype);
  
-       if(this.monster_attack)
+       if (this.monster_attack) {
                IL_PUSH(g_monster_targets, this);
+     }
  
        // support special -1 and -2 angle from radiant
-       if (this.angles == '0 -1 0')
+       if (this.angles == '0 -1 0') {
                this.angles = '-90 0 0';
-       else if (this.angles == '0 -2 0')
+       } else if (this.angles == '0 -2 0') {
                this.angles = '+90 0 0';
-       if(this.originjitter.x != 0)
-               this.origin_x = this.origin.x + (random() * 2 - 1) * this.originjitter.x;
-       if(this.originjitter.y != 0)
-               this.origin_y = this.origin.y + (random() * 2 - 1) * this.originjitter.y;
-       if(this.originjitter.z != 0)
-               this.origin_z = this.origin.z + (random() * 2 - 1) * this.originjitter.z;
-       if(this.anglesjitter.x != 0)
-               this.angles_x = this.angles.x + (random() * 2 - 1) * this.anglesjitter.x;
-       if(this.anglesjitter.y != 0)
-               this.angles_y = this.angles.y + (random() * 2 - 1) * this.anglesjitter.y;
-       if(this.anglesjitter.z != 0)
-               this.angles_z = this.angles.z + (random() * 2 - 1) * this.anglesjitter.z;
-       if(this.anglejitter != 0)
-               this.angles_y = this.angles.y + (random() * 2 - 1) * this.anglejitter;
-       if(MUTATOR_CALLHOOK(OnEntityPreSpawn, this))
-       {
-               delete(this);
-               __spawnfunc_expecting = false;
-               return;
+     }
+     #define X(out, in) MACRO_BEGIN \
+         if (in != 0) { out = out + (random() * 2 - 1) * in; } \
+     MACRO_END
+     X(this.origin.x, this.originjitter.x); X(this.origin.y, this.originjitter.y); X(this.origin.z, this.originjitter.z);
+     X(this.angles.x, this.anglesjitter.x); X(this.angles.y, this.anglesjitter.y); X(this.angles.z, this.anglesjitter.z);
+     X(this.angles.y, this.anglejitter);
+     #undef X
+       if (MUTATOR_CALLHOOK(OnEntityPreSpawn, this)) {
+               goto cleanup;
        }
+       return;
+ LABEL(cleanup)
+     builtin_remove(this);
+     __spawnfunc_expecting = false;
  }
  
  void WarpZone_PostInitialize_Callback()
  {
        // create waypoint links for warpzones
 +      entity tracetest_ent = spawn();
 +      setsize(tracetest_ent, PL_MIN_CONST, PL_MAX_CONST);
 +      tracetest_ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
        //for(entity e = warpzone_first; e; e = e.warpzone_next)
        for(entity e = NULL; (e = find(e, classname, "trigger_warpzone")); )
        {
                dst = (e.enemy.absmin + e.enemy.absmax) * 0.5;
                makevectors(e.enemy.warpzone_angles);
                dst = dst + ((e.enemy.warpzone_origin - dst) * v_forward) * v_forward - 16 * v_right;
 -              waypoint_spawnforteleporter_v(e, src, dst, 0);
 +              waypoint_spawnforteleporter_wz(e, src, dst, 0, -v_up, tracetest_ent);
        }
 +      delete(tracetest_ent);
  }