]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into TimePath/csqc_viewmodels
authorTimePath <andrew.hardaker1995@gmail.com>
Sun, 29 Nov 2015 22:59:11 +0000 (09:59 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Sun, 29 Nov 2015 23:32:37 +0000 (10:32 +1100)
# Conflicts:
# qcsrc/client/weapons/projectile.qc
# qcsrc/common/stats.qh
# qcsrc/common/weapons/all.qc
# qcsrc/common/weapons/weapon.qh
# qcsrc/server/defs.qh
# qcsrc/server/g_subs.qh
# qcsrc/server/g_world.qc

17 files changed:
1  2 
qcsrc/client/progs.inc
qcsrc/client/view.qc
qcsrc/client/weapons/projectile.qc
qcsrc/common/stats.qh
qcsrc/common/triggers/subs.qh
qcsrc/common/weapons/all.qc
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/weapon.qh
qcsrc/common/weapons/weapon/arc.qc
qcsrc/lib/_all.inc
qcsrc/lib/vector.qh
qcsrc/server/cl_client.qc
qcsrc/server/cl_player.qc
qcsrc/server/defs.qh
qcsrc/server/g_subs.qh
qcsrc/server/g_world.qc
qcsrc/server/progs.inc

diff --combined qcsrc/client/progs.inc
index 12d43b5c4c44eca85fd368f046f6119bed35063c,4a6b587882c744ae15e9c16036025acbbca336d6..8c443568ea206ed16e5fcc6b9919feff6cb083a0
  
  #include "weapons/projectile.qc" // TODO
  
 +#include "../common/anim.qc"
  #include "../common/animdecide.qc"
  #include "../common/effects/effectinfo.qc"
+ #include "../common/ent_cs.qc"
  #include "../common/mapinfo.qc"
  #include "../common/movetypes/include.qc"
  #include "../common/net_notice.qc"
  #include "../common/minigames/minigames.qc"
  #include "../common/minigames/cl_minigames.qc"
  
- #include "../common/buffs/all.qc"
  #include "../common/deathtypes/all.qc"
  #include "../common/effects/all.qc"
  #include "../common/gamemodes/all.qc"
  #include "../common/items/all.qc"
  #include "../common/monsters/all.qc"
  #include "../common/mutators/all.qc"
- #include "../common/nades/all.qc"
  #include "../common/turrets/all.qc"
  #include "../common/vehicles/all.qc"
  #include "../common/weapons/all.qc"
diff --combined qcsrc/client/view.qc
index 45629f206af44a9dbf4ee3491dfbe55a6068dd08,c98400df56760fb56814319b836458b39a0ecb44..a6d05d9a62cd24ca8a9ea2f15f75b353b79feb55
@@@ -9,12 -9,11 +9,12 @@@
  
  #include "mutators/events.qh"
  
 +#include "../common/anim.qh"
  #include "../common/constants.qh"
  #include "../common/debug.qh"
  #include "../common/mapinfo.qh"
  #include "../common/gamemodes/all.qh"
- #include "../common/nades/all.qh"
+ #include "../common/physics.qh"
  #include "../common/stats.qh"
  #include "../common/triggers/target/music.qh"
  #include "../common/teams.qh"
  #include "../lib/warpzone/client.qh"
  #include "../lib/warpzone/common.qh"
  
-       float frametime = (time - prevtime) * getstatf(STAT_MOVEVARS_TIMESCALE);
 +#define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOSHADOW | EF_SELECTABLE | EF_TELEPORT_BIT)
 +
 +float autocvar_cl_viewmodel_scale;
 +
 +bool autocvar_cl_bobmodel;
 +float autocvar_cl_bobmodel_speed;
 +float autocvar_cl_bobmodel_side;
 +float autocvar_cl_bobmodel_up;
 +
 +float autocvar_cl_followmodel;
 +float autocvar_cl_followmodel_side_speed;
 +float autocvar_cl_followmodel_side_highpass;
 +float autocvar_cl_followmodel_side_highpass1;
 +float autocvar_cl_followmodel_side_limit;
 +float autocvar_cl_followmodel_side_lowpass;
 +float autocvar_cl_followmodel_up_speed;
 +float autocvar_cl_followmodel_up_highpass;
 +float autocvar_cl_followmodel_up_highpass1;
 +float autocvar_cl_followmodel_up_limit;
 +float autocvar_cl_followmodel_up_lowpass;
 +
 +float autocvar_cl_leanmodel;
 +float autocvar_cl_leanmodel_side_speed;
 +float autocvar_cl_leanmodel_side_highpass;
 +float autocvar_cl_leanmodel_side_highpass1;
 +float autocvar_cl_leanmodel_side_lowpass;
 +float autocvar_cl_leanmodel_side_limit;
 +float autocvar_cl_leanmodel_up_speed;
 +float autocvar_cl_leanmodel_up_highpass;
 +float autocvar_cl_leanmodel_up_highpass1;
 +float autocvar_cl_leanmodel_up_lowpass;
 +float autocvar_cl_leanmodel_up_limit;
 +
 +#define lowpass(value, frac, ref_store, ret) do \
 +{ \
 +      float __frac = bound(0, frac, 1); \
 +      ret = ref_store = ref_store * (1 - __frac) + (value) * __frac; \
 +} while (0)
 +
 +#define lowpass_limited(value, frac, limit, ref_store, ret) do \
 +{ \
 +      float __ignore; lowpass(value, frac, ref_store, __ignore); \
 +      ret = ref_store = bound((value) - (limit), ref_store, (value) + (limit)); \
 +} while (0)
 +
 +#define highpass(value, frac, ref_store, ret) do \
 +{ \
 +      float __f; lowpass(value, frac, ref_store, __f); \
 +      ret = (value) - __f; \
 +} while (0)
 +
 +#define highpass_limited(value, frac, limit, ref_store, ret) do \
 +{ \
 +      float __f; lowpass_limited(value, frac, limit, ref_store, __f); \
 +      ret = (value) - __f; \
 +} while (0)
 +
 +#define lowpass3(value, fracx, fracy, fracz, ref_store, ref_out) do \
 +{ \
 +      lowpass(value.x, fracx, ref_store.x, ref_out.x); \
 +      lowpass(value.y, fracy, ref_store.y, ref_out.y); \
 +      lowpass(value.z, fracz, ref_store.z, ref_out.z); \
 +} while (0)
 +
 +#define highpass3(value, fracx, fracy, fracz, ref_store, ref_out) do \
 +{ \
 +      highpass(value.x, fracx, ref_store.x, ref_out.x); \
 +      highpass(value.y, fracy, ref_store.y, ref_out.y); \
 +      highpass(value.z, fracz, ref_store.z, ref_out.z); \
 +} while (0)
 +
 +#define highpass3_limited(value, fracx, limitx, fracy, limity, fracz, limitz, ref_store, ref_out) do \
 +{ \
 +      highpass_limited(value.x, fracx, limitx, ref_store.x, ref_out.x); \
 +      highpass_limited(value.y, fracy, limity, ref_store.y, ref_out.y); \
 +      highpass_limited(value.z, fracz, limitz, ref_store.z, ref_out.z); \
 +} while (0)
 +
 +void viewmodel_animate(entity this)
 +{
 +      static float prevtime;
-       entity view = CSQCModel_server2csqc(player_localentnum);
++      float frametime = (time - prevtime) * STAT(MOVEVARS_TIMESCALE);
 +      prevtime = time;
 +
 +      if (autocvar_chase_active) return;
 +      if (getstati(STAT_HEALTH) <= 0) return;
 +
-       entity me = CSQCModel_server2csqc(player_localentnum);
++      entity view = CSQCModel_server2csqc(player_localentnum - 1);
 +
 +      bool clonground = !(view.anim_implicit_state & ANIMIMPLICITSTATE_INAIR);
 +      static bool oldonground;
 +      static float hitgroundtime;
 +      static float lastongroundtime;
 +      if (clonground)
 +      {
 +              float f = time; // cl.movecmd[0].time
 +              if (!oldonground)
 +                      hitgroundtime = f;
 +              lastongroundtime = f;
 +      }
 +      oldonground = clonground;
 +
 +      vector gunorg = '0 0 0', gunangles = '0 0 0';
 +      static vector gunorg_prev = '0 0 0', gunangles_prev = '0 0 0';
 +
 +      bool teleported = view.csqcmodel_teleported;
 +
 +      // 1. if we teleported, clear the frametime... the lowpass will recover the previous value then
 +      if (teleported)
 +      {
 +              // try to fix the first highpass; result is NOT
 +              // perfect! TODO find a better fix
 +              gunangles_prev = view_angles;
 +              gunorg_prev = view_origin;
 +      }
 +
 +      static vector gunorg_highpass = '0 0 0';
 +
 +      // 2. for the gun origin, only keep the high frequency (non-DC) parts, which is "somewhat like velocity"
 +      gunorg_highpass += gunorg_prev;
 +      highpass3_limited(view_origin,
 +              frametime * autocvar_cl_followmodel_side_highpass1, autocvar_cl_followmodel_side_limit,
 +              frametime * autocvar_cl_followmodel_side_highpass1, autocvar_cl_followmodel_side_limit,
 +              frametime * autocvar_cl_followmodel_up_highpass1, autocvar_cl_followmodel_up_limit,
 +              gunorg_highpass, gunorg);
 +      gunorg_prev = view_origin;
 +      gunorg_highpass -= gunorg_prev;
 +
 +      static vector gunangles_highpass = '0 0 0';
 +
 +      // in the highpass, we _store_ the DIFFERENCE to the actual view angles...
 +      gunangles_highpass += gunangles_prev;
 +      PITCH(gunangles_highpass) += 360 * floor((PITCH(view_angles) - PITCH(gunangles_highpass)) / 360 + 0.5);
 +      YAW(gunangles_highpass) += 360 * floor((YAW(view_angles) - YAW(gunangles_highpass)) / 360 + 0.5);
 +      ROLL(gunangles_highpass) += 360 * floor((ROLL(view_angles) - ROLL(gunangles_highpass)) / 360 + 0.5);
 +      highpass3_limited(view_angles,
 +              frametime * autocvar_cl_leanmodel_up_highpass1, autocvar_cl_leanmodel_up_limit,
 +              frametime * autocvar_cl_leanmodel_side_highpass1, autocvar_cl_leanmodel_side_limit,
 +              0, 0,
 +              gunangles_highpass, gunangles);
 +      gunangles_prev = view_angles;
 +      gunangles_highpass -= gunangles_prev;
 +
 +      // 3. calculate the RAW adjustment vectors
 +      gunorg.x *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_side_speed : 0);
 +      gunorg.y *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_side_speed : 0);
 +      gunorg.z *= (autocvar_cl_followmodel ? -autocvar_cl_followmodel_up_speed : 0);
 +
 +      PITCH(gunangles) *= (autocvar_cl_leanmodel ? -autocvar_cl_leanmodel_up_speed : 0);
 +      YAW(gunangles) *= (autocvar_cl_leanmodel ? -autocvar_cl_leanmodel_side_speed : 0);
 +      ROLL(gunangles) = 0;
 +
 +      static vector gunorg_adjustment_highpass;
 +      static vector gunorg_adjustment_lowpass;
 +      static vector gunangles_adjustment_highpass;
 +      static vector gunangles_adjustment_lowpass;
 +
 +      // 4. perform highpass/lowpass on the adjustment vectors (turning velocity into acceleration!)
 +      //    trick: we must do the lowpass LAST, so the lowpass vector IS the final vector!
 +      highpass3(gunorg,
 +              frametime * autocvar_cl_followmodel_side_highpass,
 +              frametime * autocvar_cl_followmodel_side_highpass,
 +              frametime * autocvar_cl_followmodel_up_highpass,
 +              gunorg_adjustment_highpass, gunorg);
 +      lowpass3(gunorg,
 +              frametime * autocvar_cl_followmodel_side_lowpass,
 +              frametime * autocvar_cl_followmodel_side_lowpass,
 +              frametime * autocvar_cl_followmodel_up_lowpass,
 +              gunorg_adjustment_lowpass, gunorg);
 +      // we assume here: PITCH = 0, YAW = 1, ROLL = 2
 +      highpass3(gunangles,
 +              frametime * autocvar_cl_leanmodel_up_highpass,
 +              frametime * autocvar_cl_leanmodel_side_highpass,
 +              0,
 +              gunangles_adjustment_highpass, gunangles);
 +      lowpass3(gunangles,
 +              frametime * autocvar_cl_leanmodel_up_lowpass,
 +              frametime * autocvar_cl_leanmodel_side_lowpass,
 +              0,
 +              gunangles_adjustment_lowpass, gunangles);
 +      float xyspeed = bound(0, vlen(vec2(view.velocity)), 400);
 +
 +      // vertical view bobbing code
 +      // TODO: cl_bob
 +
 +      // horizontal view bobbing code
 +      // TODO: cl_bob2
 +
 +      // fall bobbing code
 +      // causes the view to swing down and back up when touching the ground
 +      // TODO: cl_bobfall
 +
 +      // gun model bobbing code
 +      if (autocvar_cl_bobmodel)
 +      {
 +              // calculate for swinging gun model
 +              // the gun bobs when running on the ground, but doesn't bob when you're in the air.
 +              // Sajt: I tried to smooth out the transitions between bob and no bob, which works
 +              // for the most part, but for some reason when you go through a message trigger or
 +              // pick up an item or anything like that it will momentarily jolt the gun.
 +              vector forward, right, up;
 +              float bspeed;
 +              float t = 1;
 +              float s = time * autocvar_cl_bobmodel_speed;
 +              if (clonground)
 +              {
 +                      if (time - hitgroundtime < 0.2)
 +                      {
 +                              // just hit the ground, speed the bob back up over the next 0.2 seconds
 +                              t = time - hitgroundtime;
 +                              t = bound(0, t, 0.2);
 +                              t *= 5;
 +                      }
 +              }
 +              else
 +              {
 +                      // recently left the ground, slow the bob down over the next 0.2 seconds
 +                      t = time - lastongroundtime;
 +                      t = 0.2 - bound(0, t, 0.2);
 +                      t *= 5;
 +              }
 +              bspeed = xyspeed * 0.01;
 +              MAKEVECTORS(makevectors, gunangles, forward, right, up);
 +              float bobr = bspeed * autocvar_cl_bobmodel_side * autocvar_cl_viewmodel_scale * sin(s) * t;
 +              gunorg += bobr * right;
 +              float bobu = bspeed * autocvar_cl_bobmodel_up * autocvar_cl_viewmodel_scale * cos(s * 2) * t;
 +              gunorg += bobu * up;
 +      }
 +      this.origin += view_forward * gunorg.x + view_right * gunorg.y + view_up * gunorg.z;
 +      gunangles.x = -gunangles.x; // pitch was inverted, now that actually matters
 +      this.angles += gunangles;
 +}
 +
 +.vector viewmodel_origin, viewmodel_angles;
 +
 +void viewmodel_draw(entity this)
 +{
 +      int mask = (intermission || (getstati(STAT_HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
 +      float a = this.alpha;
 +      int c = stof(getplayerkeyvalue(current_player, "colors"));
 +      vector g = this.glowmod; // TODO: completely clientside: colormapPaletteColor(c & 0x0F, true) * 2;
-       float eta = (getstatf(STAT_WEAPON_NEXTTHINK) - time); // TODO: / W_WeaponRateFactor();
++      entity me = CSQCModel_server2csqc(player_localentnum - 1);
 +      int fx = ((me.csqcmodel_effects & EFMASK_CHEAP)
 +              | EF_NODEPTHTEST)
 +              &~ (EF_FULLBRIGHT); // can mask team color, so get rid of it
 +      for (entity e = this; e; e = e.weaponchild)
 +      {
 +              e.drawmask = mask;
 +              e.alpha = a;
 +              e.colormap = c;
 +              e.glowmod = g;
 +              e.csqcmodel_effects = fx;
 +              WITH(entity, self, e, CSQCModel_Effects_Apply());
 +      }
 +      {
 +              static string name_last;
 +              string name = Weapons_from(activeweapon).mdl;
 +              if (name != name_last)
 +              {
 +                      name_last = name;
 +                      CL_WeaponEntity_SetModel(this, name);
 +                      this.viewmodel_origin = this.origin;
 +                      this.viewmodel_angles = this.angles;
 +              }
 +              anim_update(this);
 +              if (!this.animstate_override)
 +                      anim_set(this, this.anim_idle, true, false, false);
 +      }
++      float eta = (STAT(WEAPON_NEXTTHINK) - time); // TODO: / W_WeaponRateFactor();
 +      float f = 0; // 0..1; 0: fully active
 +      switch (this.state)
 +      {
 +              case WS_RAISE:
 +              {
 +                      // entity newwep = Weapons_from(activeweapon);
 +                      float delay = 0.2; // TODO: newwep.switchdelay_raise;
 +                      f = eta / max(eta, delay);
 +                      break;
 +              }
 +              case WS_DROP:
 +              {
 +                      // entity oldwep = Weapons_from(activeweapon);
 +                      float delay = 0.2; // TODO: newwep.switchdelay_drop;
 +                      f = 1 - eta / max(eta, delay);
 +                      break;
 +              }
 +              case WS_CLEAR:
 +              {
 +                      f = 1;
 +                      break;
 +              }
 +      }
 +      this.origin = this.viewmodel_origin;
 +      this.angles = this.viewmodel_angles;
 +      this.angles_x = (-90 * f * f);
 +      viewmodel_animate(this);
 +      setorigin(this, this.origin);
 +}
 +
 +entity viewmodel;
 +STATIC_INIT(viewmodel) {
 +    viewmodel = new(viewmodel);
 +      viewmodel.draw = viewmodel_draw;
 +}
 +
  entity porto;
  vector polyline[16];
  void Porto_Draw(entity this)
@@@ -666,9 -360,9 +666,9 @@@ float TrueAimCheck(
                        break;
        }
  
-       vector traceorigin = getplayerorigin(player_localentnum-1) + (eZ * getstati(STAT_VIEWHEIGHT));
+       vector traceorigin = entcs_receiver(player_localentnum - 1).origin + (eZ * getstati(STAT_VIEWHEIGHT));
  
-       vecs = decompressShotOrigin(getstati(STAT_SHOTORG));
+       vecs = decompressShotOrigin(STAT(SHOTORG));
  
        traceline(traceorigin, traceorigin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
        trueaimpoint = trace_endpos;
@@@ -749,7 -443,7 +749,7 @@@ bool WantEventchase(
                        return true;
                if(MUTATOR_CALLHOOK(WantEventchase, self))
                        return true;
-               if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WepSet_FromWeapon(WEP_NEXBALL.m_id)))
+               if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WEPSET(NEXBALL)))
                        return true;
                if(autocvar_cl_eventchase_death && (getstati(STAT_HEALTH) <= 0))
                {
@@@ -781,12 -475,12 +781,12 @@@ void UpdateDamage(
  {
        // accumulate damage with each stat update
        static float damage_total_prev = 0;
-       float damage_total = getstati(STAT_DAMAGE_DEALT_TOTAL);
+       float damage_total = STAT(DAMAGE_DEALT_TOTAL);
        float unaccounted_damage_new = COMPARE_INCREASING(damage_total, damage_total_prev);
        damage_total_prev = damage_total;
  
        static float damage_dealt_time_prev = 0;
-       float damage_dealt_time = getstatf(STAT_HIT_TIME);
+       float damage_dealt_time = STAT(HIT_TIME);
        if (damage_dealt_time != damage_dealt_time_prev)
        {
                unaccounted_damage += unaccounted_damage_new;
@@@ -842,7 -536,7 +842,7 @@@ void HitSound(
        }
  
        static float typehit_time_prev = 0;
-       float typehit_time = getstatf(STAT_TYPEHIT_TIME);
+       float typehit_time = STAT(TYPEHIT_TIME);
        if (COMPARE_INCREASING(typehit_time, typehit_time_prev) > autocvar_cl_hitsound_antispam_time)
        {
                sound(world, CH_INFO, SND_TYPEHIT, VOL_BASE, ATTN_NONE);
@@@ -1018,7 -712,7 +1018,7 @@@ void HUD_Crosshair(
  
                if(autocvar_crosshair_pickup)
                {
-                       float stat_pickup_time = getstatf(STAT_LAST_PICKUP);
+                       float stat_pickup_time = STAT(LAST_PICKUP);
  
                        if(pickup_crosshair_time < stat_pickup_time)
                        {
                                ring_scale = autocvar_crosshair_ring_size;
  
                                float weapon_clipload, weapon_clipsize;
-                               weapon_clipload = getstati(STAT_WEAPON_CLIPLOAD);
-                               weapon_clipsize = getstati(STAT_WEAPON_CLIPSIZE);
+                               weapon_clipload = STAT(WEAPON_CLIPLOAD);
+                               weapon_clipsize = STAT(WEAPON_CLIPSIZE);
  
                                float ok_ammo_charge, ok_ammo_chargepool;
-                               ok_ammo_charge = getstatf(STAT_OK_AMMO_CHARGE);
-                               ok_ammo_chargepool = getstatf(STAT_OK_AMMO_CHARGEPOOL);
+                               ok_ammo_charge = STAT(OK_AMMO_CHARGE);
+                               ok_ammo_chargepool = STAT(OK_AMMO_CHARGEPOOL);
  
                                float vortex_charge, vortex_chargepool;
-                               vortex_charge = getstatf(STAT_VORTEX_CHARGE);
-                               vortex_chargepool = getstatf(STAT_VORTEX_CHARGEPOOL);
+                               vortex_charge = STAT(VORTEX_CHARGE);
+                               vortex_chargepool = STAT(VORTEX_CHARGEPOOL);
  
-                               float arc_heat = getstatf(STAT_ARC_HEAT);
+                               float arc_heat = STAT(ARC_HEAT);
  
                                if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
                                        vortex_charge_movingavg = vortex_charge;
                                }
                                else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER.m_id && minelayer_maxmines && autocvar_crosshair_ring_minelayer)
                                {
-                                       ring_value = bound(0, getstati(STAT_LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
+                                       ring_value = bound(0, STAT(LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
                                        ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring.tga";
                                }
-                               else if (activeweapon == WEP_HAGAR.m_id && getstati(STAT_HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
+                               else if (activeweapon == WEP_HAGAR.m_id && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
                                {
-                                       ring_value = bound(0, getstati(STAT_HAGAR_LOAD) / hagar_maxrockets, 1);
+                                       ring_value = bound(0, STAT(HAGAR_LOAD) / hagar_maxrockets, 1);
                                        ring_alpha = autocvar_crosshair_ring_hagar_alpha;
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring.tga";
                                        wcross_color = stov(autocvar_crosshair_dot_color);
  
                                CROSSHAIR_DRAW(wcross_resolution * autocvar_crosshair_dot_size, "gfx/crosshairdot.tga", f * autocvar_crosshair_dot_alpha);
-                               // FIXME why don't we use wcross_alpha here?cl_notice_run();
+                               // FIXME why don't we use wcross_alpha here?
                                wcross_color = wcross_color_old;
                        }
                }
  
  void HUD_Draw()
  {
-       if(getstati(STAT_FROZEN))
-               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, ((getstatf(STAT_REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * getstatf(STAT_REVIVE_PROGRESS)) + ('0 1 1' * getstatf(STAT_REVIVE_PROGRESS) * -1)) : '0.25 0.90 1'), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
-       else if (getstatf(STAT_HEALING_ORB)>time)
-               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, NADE_TYPE_HEAL.m_color, autocvar_hud_colorflash_alpha*getstatf(STAT_HEALING_ORB_ALPHA), DRAWFLAG_ADDITIVE);
+       vector rgb = '0 0 0';
+       float a = 1;
+       if (MUTATOR_CALLHOOK(HUD_Draw_overlay))
+       {
+               rgb = MUTATOR_ARGV(0, vector);
+               a = MUTATOR_ARGV(0, float);
+       }
+       else if(STAT(FROZEN))
+       {
+               rgb = ((STAT(REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * STAT(REVIVE_PROGRESS)) + ('0 1 1' * STAT(REVIVE_PROGRESS) * -1)) : '0.25 0.90 1');
+       }
+       drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, rgb, autocvar_hud_colorflash_alpha * a, DRAWFLAG_ADDITIVE);
        if(!intermission)
-       if(getstatf(STAT_NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
+       if(STAT(NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
        {
-               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * getstatf(STAT_NADE_TIMER)) - ('0 1 1' * getstatf(STAT_NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * STAT(NADE_TIMER)) - ('0 1 1' * STAT(NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
                drawstring_aspect(eY * 0.64 * vid_conheight, ((autocvar_cl_nade_timer == 2) ? _("Nade timer") : ""), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
        }
-       else if(getstatf(STAT_REVIVE_PROGRESS))
+       else if(STAT(REVIVE_PROGRESS))
        {
-               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
                drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
        }
  
@@@ -1351,9 -1053,7 +1359,7 @@@ float oldr_novis
  float oldr_useportalculling;
  float oldr_useinfinitefarclip;
  
- const int BUTTON_3 = 4;
- const int BUTTON_4 = 8;
- float cl_notice_run();
+ void cl_notice_run();
  float prev_myteam;
  int lasthud;
  float vh_notice_time;
@@@ -1370,7 -1070,8 +1376,8 @@@ void CSQC_UpdateView(float w, float h
  
        ++framecount;
  
-       hud = getstati(STAT_HUD);
+       stats_get();
+       hud = STAT(HUD);
  
        if(hud != HUD_NORMAL && lasthud == HUD_NORMAL)
                vh_notice_time = time + autocvar_cl_vehicles_notify_time;
        else
                view_quality = 1;
  
-       button_attack2 = (input_buttons & BUTTON_3);
-       button_zoom = (input_buttons & BUTTON_4);
+       button_attack2 = PHYS_INPUT_BUTTON_ATCK2(self);
+       button_zoom = PHYS_INPUT_BUTTON_ZOOM(self);
  
        vf_size = getpropertyvec(VF_SIZE);
        vf_min = getpropertyvec(VF_MIN);
                prev_myteam = myteam;
        }
  
-       ticrate = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
+       ticrate = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
  
        float is_dead = (getstati(STAT_HEALTH) <= 0);
  
        if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
        {
                float vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
-               float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && getstati(STAT_ROUNDLOST));
+               float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && STAT(ROUNDLOST));
                entity gen = world;
  
                if(ons_roundlost)
  
        ColorTranslateMode = autocvar_cl_stripcolorcodes;
  
-       // next WANTED weapon (for HUD)
-       switchweapon = getstati(STAT_SWITCHWEAPON);
        // currently switching-to weapon (for crosshair)
-       switchingweapon = getstati(STAT_SWITCHINGWEAPON);
+       switchingweapon = STAT(SWITCHINGWEAPON);
  
        // actually active weapon (for zoom)
        activeweapon = getstati(STAT_ACTIVEWEAPON);
           mousepos = mousepos*0.5 + getmousepos();
         */
  
-       for(entity e = NULL; (e = nextent(e)); ) if (e.draw) {
-               WITH(entity, self, e, e.draw(e));
-       }
+       FOREACH_ENTITY(it.draw, LAMBDA(WITH(entity, self, it, it.draw(it))));
  
        addentities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS);
        renderscene();
                }
        }
  
-       if(autocvar_hud_damage && !getstati(STAT_FROZEN))
+       if(autocvar_hud_damage && !STAT(FROZEN))
        {
                splash_size.x = max(vid_conwidth, vid_conheight);
                splash_size.y = max(vid_conwidth, vid_conheight);
                }
  
                // edge detection postprocess handling done second (used by hud_powerup)
-               float sharpen_intensity = 0, strength_finished = getstatf(STAT_STRENGTH_FINISHED), invincible_finished = getstatf(STAT_INVINCIBLE_FINISHED);
+               float sharpen_intensity = 0, strength_finished = STAT(STRENGTH_FINISHED), invincible_finished = STAT(INVINCIBLE_FINISHED);
                if (strength_finished - time > 0) { sharpen_intensity += (strength_finished - time); }
                if (invincible_finished - time > 0) { sharpen_intensity += (invincible_finished - time); }
  
          } else */
  
        // draw 2D entities
-       for (entity e = NULL; (e = nextent(e)); ) if (e.draw2d) {
-               WITH(entity, self, e, e.draw2d(e));
-       }
+       FOREACH_ENTITY(it.draw2d, LAMBDA(WITH(entity, self, it, it.draw2d(it))));
        Draw_ShowNames_All();
        Debug_Draw();
  
index c423032fe963870fe39e3a90290e563e2d1c4408,1591bad96b5ccba33b54f72a29acbb93cf1bad3f..2100c3f5fd41d4680937b0adfc63ff7c10cf642e
@@@ -7,7 -7,6 +7,6 @@@
  
  #include "../../common/constants.qh"
  #include "../../common/movetypes/movetypes.qh"
- #include "../../common/nades/all.qh"
  
  #include "../../lib/csqcmodel/interpolate.qh"
  
@@@ -49,6 -48,8 +48,8 @@@ void Projectile_DrawTrail(entity this, 
        }
  }
  
+ bool Projectile_isnade(int proj); // TODO: remove
  void Projectile_Draw(entity this)
  {
        vector rot;
        {
                // self.move_flags &= ~FL_ONGROUND;
                if (self.move_movetype == MOVETYPE_NONE || self.move_movetype == MOVETYPE_FLY)
-                       Movetype_Physics_NoMatchServer();
+                       Movetype_Physics_NoMatchServer(self);
                // the trivial movetypes do not have to match the
                // server's ticrate as they are ticrate independent
                // NOTE: this assumption is only true if MOVETYPE_FLY
                // projectiles detonate on impact. If they continue
                // moving, we might still be ticrate dependent.
                else
-                       Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+                       Movetype_Physics_MatchServer(self, autocvar_cl_projectiles_sloppy);
                if (!(self.move_flags & FL_ONGROUND))
                        if (self.velocity != '0 0 0')
                                self.move_angles = self.angles = vectoangles(self.velocity);
        }
        else
        {
-               InterpolateOrigin_Do();
+               InterpolateOrigin_Do(self);
        }
  
        if (self.count & 0x80)
                                break;
                }
  
-               if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
+               if (Projectile_isnade(self.cnt))
                        rot = self.avelocity;
  
                self.angles = AnglesTransform_ToAngles(AnglesTransform_Multiply(AnglesTransform_FromAngles(self.angles), rot * (t - self.spawntime)));
                        break;
        }
  
-       if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
+       if (Projectile_isnade(self.cnt))
                trailorigin += v_up * 4;
  
        if (drawn)
@@@ -226,7 -227,7 +227,7 @@@ NET_HANDLE(ENT_CLIENT_PROJECTILE, bool 
        }
  
        if (!(self.count & 0x80))
-               InterpolateOrigin_Undo();
+               InterpolateOrigin_Undo(self);
  
        if (f & 1)
        {
                self.traileffect = 0;
                switch (self.cnt)
                {
 -                      #define CASE(id) case PROJECTILE_##id: setmodel(self, MDL_PROJECTILE_##id);
 -                      CASE(ELECTRO)            self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
 -                      CASE(ROCKET)             self.traileffect = EFFECT_TR_ROCKET.m_id; self.scale = 2; break;
 -                      CASE(CRYLINK)            self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
 -                      CASE(CRYLINK_BOUNCING)   self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
 -                      CASE(ELECTRO_BEAM)       self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
 -                      CASE(GRENADE)            self.traileffect = EFFECT_TR_GRENADE.m_id; break;
 -                      CASE(GRENADE_BOUNCING)   self.traileffect = EFFECT_TR_GRENADE.m_id; break;
 -                      CASE(MINE)               self.traileffect = EFFECT_TR_GRENADE.m_id; break;
 -                      CASE(BLASTER)            self.traileffect = EFFECT_Null.m_id; break;
 -                      CASE(HLAC)               self.traileffect = EFFECT_Null.m_id; break;
 -                      CASE(PORTO_RED)          self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
 -                      CASE(PORTO_BLUE)         self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
 -                      CASE(HOOKBOMB)           self.traileffect = EFFECT_TR_KNIGHTSPIKE.m_id; break;
 -                      CASE(HAGAR)              self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
 -                      CASE(HAGAR_BOUNCING)     self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
 -                      CASE(FIREBALL)           self.modelindex = 0; self.traileffect = EFFECT_FIREBALL.m_id; break; // particle effect is good enough
 -                      CASE(FIREMINE)           self.modelindex = 0; self.traileffect = EFFECT_FIREMINE.m_id; break; // particle effect is good enough
 -                      CASE(TAG)                self.traileffect = EFFECT_TR_ROCKET.m_id; break;
 -                      CASE(FLAC)               self.scale = 0.4; self.traileffect = EFFECT_FLAC_TRAIL.m_id; break;
 -                      CASE(SEEKER)             self.traileffect = EFFECT_SEEKER_TRAIL.m_id; break;
 -
 -                      CASE(MAGE_SPIKE)         self.traileffect = EFFECT_TR_VORESPIKE.m_id; break;
 -                      CASE(SHAMBLER_LIGHTNING) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
 -
 -                      CASE(RAPTORBOMB)         self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
 -                      CASE(RAPTORBOMBLET)      self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
 -                      CASE(RAPTORCANNON)       self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
 -
 -                      CASE(SPIDERROCKET)       self.traileffect = EFFECT_SPIDERBOT_ROCKET_TRAIL.m_id; break;
 -                      CASE(WAKIROCKET)         self.traileffect = EFFECT_RACER_ROCKET_TRAIL.m_id; break;
 -                      CASE(WAKICANNON)         self.traileffect = EFFECT_Null.m_id; break;
 -
 -                      CASE(BUMBLE_GUN)         self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
 -                      CASE(BUMBLE_BEAM)        self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
 -
 -                      CASE(RPC)                self.traileffect = EFFECT_TR_ROCKET.m_id; break;
 -
 -                      CASE(ROCKETMINSTA_LASER) self.traileffect = EFFECT_ROCKETMINSTA_LASER(self.team).m_id; break;
 -#undef CASE
 +                      #define HANDLE(id) case PROJECTILE_##id: setmodel(self, MDL_PROJECTILE_##id);
 +                      HANDLE(ELECTRO)            self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
 +                      HANDLE(ROCKET)             self.traileffect = EFFECT_TR_ROCKET.m_id; self.scale = 2; break;
 +                      HANDLE(CRYLINK)            self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
 +                      HANDLE(CRYLINK_BOUNCING)   self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
 +                      HANDLE(ELECTRO_BEAM)       self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
 +                      HANDLE(GRENADE)            self.traileffect = EFFECT_TR_GRENADE.m_id; break;
 +                      HANDLE(GRENADE_BOUNCING)   self.traileffect = EFFECT_TR_GRENADE.m_id; break;
 +                      HANDLE(MINE)               self.traileffect = EFFECT_TR_GRENADE.m_id; break;
 +                      HANDLE(BLASTER)            self.traileffect = EFFECT_Null.m_id; break;
 +                      HANDLE(HLAC)               self.traileffect = EFFECT_Null.m_id; break;
 +                      HANDLE(PORTO_RED)          self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
 +                      HANDLE(PORTO_BLUE)         self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
 +                      HANDLE(HOOKBOMB)           self.traileffect = EFFECT_TR_KNIGHTSPIKE.m_id; break;
 +                      HANDLE(HAGAR)              self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
 +                      HANDLE(HAGAR_BOUNCING)     self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
-                       HANDLE(NAPALM_FOUNTAIN)                                                                         // fallthrough // sself.modelindex = 0; self.traileffect = _particleeffectnum("torch_small"); break;
 +                      HANDLE(FIREBALL)           self.modelindex = 0; self.traileffect = EFFECT_FIREBALL.m_id; break; // particle effect is good enough
 +                      HANDLE(FIREMINE)           self.modelindex = 0; self.traileffect = EFFECT_FIREMINE.m_id; break; // particle effect is good enough
 +                      HANDLE(TAG)                self.traileffect = EFFECT_TR_ROCKET.m_id; break;
 +                      HANDLE(FLAC)               self.scale = 0.4; self.traileffect = EFFECT_FLAC_TRAIL.m_id; break;
 +                      HANDLE(SEEKER)             self.traileffect = EFFECT_SEEKER_TRAIL.m_id; break;
 +
 +                      HANDLE(MAGE_SPIKE)         self.traileffect = EFFECT_TR_VORESPIKE.m_id; break;
 +                      HANDLE(SHAMBLER_LIGHTNING) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
 +
 +                      HANDLE(RAPTORBOMB)         self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
 +                      HANDLE(RAPTORBOMBLET)      self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
 +                      HANDLE(RAPTORCANNON)       self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
 +
 +                      HANDLE(SPIDERROCKET)       self.traileffect = EFFECT_SPIDERBOT_ROCKET_TRAIL.m_id; break;
 +                      HANDLE(WAKIROCKET)         self.traileffect = EFFECT_RACER_ROCKET_TRAIL.m_id; break;
 +                      HANDLE(WAKICANNON)         self.traileffect = EFFECT_Null.m_id; break;
 +
 +                      HANDLE(BUMBLE_GUN)         self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
 +                      HANDLE(BUMBLE_BEAM)        self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
 +
 +                      HANDLE(RPC)                self.traileffect = EFFECT_TR_ROCKET.m_id; break;
 +
 +                      HANDLE(ROCKETMINSTA_LASER) self.traileffect = EFFECT_ROCKETMINSTA_LASER(self.team).m_id; break;
 +#undef HANDLE
                        default:
                                if (MUTATOR_CALLHOOK(Ent_Projectile, self))
                                        break;
  
-                               if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
-                               {
-                                       setmodel(self, MDL_PROJECTILE_NADE);
-                                       entity trail = Nade_TrailEffect(self.cnt, self.team);
-                                       if (trail.eent_eff_name) self.traileffect = trail.m_id;
-                                       break;
-                               }
                                error("Received invalid CSQC projectile, can't work with this!");
                                break;
                }
                                self.move_movetype = MOVETYPE_BOUNCE;
                                self.move_touch = func_null;
                                break;
-                       case PROJECTILE_NAPALM_FOUNTAIN:
                        case PROJECTILE_FIREBALL:
                                loopsound(self, CH_SHOTS_SINGLE, SND(FIREBALL_FLY2), VOL_BASE, ATTEN_NORM);
                                self.mins = '-16 -16 -16';
                                break;
                }
  
-               if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
-               {
-                       entity nade_type = Nade_FromProjectile(self.cnt);
-                       self.mins = '-16 -16 -16';
-                       self.maxs = '16 16 16';
-                       self.colormod = nade_type.m_color;
-                       self.move_movetype = MOVETYPE_BOUNCE;
-                       self.move_touch = func_null;
-                       self.scale = 1.5;
-                       self.avelocity = randomvec() * 720;
-                       if (nade_type == NADE_TYPE_TRANSLOCATE || nade_type == NADE_TYPE_SPAWN)
-                               self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
-                       else
-                               self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY;
-               }
                MUTATOR_CALLHOOK(EditProjectile, self);
  
                setsize(self, self.mins, self.maxs);
        }
  
        if (!(self.count & 0x80))
-               InterpolateOrigin_Note();
+               InterpolateOrigin_Note(this);
  
        self.classname = "csqcprojectile";
        self.draw = Projectile_Draw;
diff --combined qcsrc/common/stats.qh
index 68bfbe8332ee4b5b881b79a7f04da839fe8f6093,6825ff76b6a89548570ff92e3d0df7287d83d40e..be3e10f5ef1bd1e06fdac0591ce4393d8fe41e67
  // Full list of all stat constants, included in a single location for easy reference
  // 255 is the current limit (MAX_CL_STATS - 1), engine will need to be modified if you wish to add more stats
  
- const int MAX_CL_STATS                = 256;
- // -Wdouble-declaration
- // const int STAT_HEALTH                 = 0;
- // 1 empty?
- const int STAT_WEAPON                 = 2;
- // -Wdouble-declaration
- // const int STAT_AMMO                   = 3;
- // -Wdouble-declaration
- // const int STAT_ARMOR                  = 4;
- // -Wdouble-declaration
- // const int STAT_WEAPONFRAME            = 5;
- // -Wdouble-declaration
- // const int STAT_SHELLS                 = 6;
- // -Wdouble-declaration
- // const int STAT_NAILS                  = 7;
- // -Wdouble-declaration
- // const int STAT_ROCKETS                = 8;
- // -Wdouble-declaration
- // const int STAT_CELLS                  = 9;
- // -Wdouble-declaration
- // const int STAT_ACTIVEWEAPON           = 10;
- // -Wdouble-declaration
- // const int STAT_TOTALSECRETS           = 11;
- // -Wdouble-declaration
- // const int STAT_TOTALMONSTERS          = 12;
- // -Wdouble-declaration
- // const int STAT_SECRETS                = 13;
- // -Wdouble-declaration
- // const int STAT_MONSTERS               = 14;
- // -Wdouble-declaration
- // const int STAT_ITEMS                  = 15;
- // -Wdouble-declaration
- // const int STAT_VIEWHEIGHT             = 16;
- // 17 empty?
- // 18 empty?
- // 19 empty?
- // 20 empty?
- const int STAT_VIEWZOOM               = 21;
- // 22 empty?
- // 23 empty?
- // 24 empty?
- // 25 empty?
- // 26 empty?
- // 27 empty?
- // 28 empty?
- // 29 empty?
- // 30 empty?
- // 31 empty?
- const int STAT_KH_KEYS                = 32;
- const int STAT_CTF_STATE              = 33;
- // 34 empty?
- const int STAT_WEAPONS                = 35;
- const int STAT_SWITCHWEAPON           = 36;
- const int STAT_GAMESTARTTIME          = 37;
- const int STAT_STRENGTH_FINISHED      = 38;
- const int STAT_INVINCIBLE_FINISHED    = 39;
- // 40 empty?
- const int STAT_ARC_HEAT               = 41;
- const int STAT_PRESSED_KEYS           = 42;
- const int STAT_ALLOW_OLDVORTEXBEAM    = 43; // this stat could later contain some other bits of info, like, more server-side particle config
- const int STAT_FUEL                   = 44;
- const int STAT_NB_METERSTART          = 45;
- const int STAT_SHOTORG                = 46; // compressShotOrigin
- const int STAT_LEADLIMIT              = 47;
- const int STAT_WEAPON_CLIPLOAD        = 48;
- const int STAT_WEAPON_CLIPSIZE        = 49;
- const int STAT_VORTEX_CHARGE          = 50;
- const int STAT_LAST_PICKUP            = 51;
- const int STAT_HUD                    = 52;
- const int STAT_VORTEX_CHARGEPOOL      = 53;
- const int STAT_HIT_TIME               = 54;
- const int STAT_DAMAGE_DEALT_TOTAL     = 55;
- const int STAT_TYPEHIT_TIME           = 56;
- const int STAT_LAYED_MINES            = 57;
- const int STAT_HAGAR_LOAD             = 58;
- const int STAT_SWITCHINGWEAPON        = 59;
- const int STAT_SUPERWEAPONS_FINISHED  = 60;
- const int STAT_VEHICLESTAT_HEALTH     = 61;
- const int STAT_VEHICLESTAT_SHIELD     = 62;
- const int STAT_VEHICLESTAT_ENERGY     = 63;
- const int STAT_VEHICLESTAT_AMMO1      = 64;
- const int STAT_VEHICLESTAT_RELOAD1    = 65;
- const int STAT_VEHICLESTAT_AMMO2      = 66;
- const int STAT_VEHICLESTAT_RELOAD2    = 67;
- const int STAT_VEHICLESTAT_W2MODE     = 68;
- const int STAT_NADE_TIMER             = 69;
- const int STAT_SECRETS_TOTAL          = 70;
- const int STAT_SECRETS_FOUND          = 71;
- const int STAT_RESPAWN_TIME           = 72;
- const int STAT_ROUNDSTARTTIME         = 73;
- const int STAT_WEAPONS2               = 74;
- const int STAT_WEAPONS3               = 75;
- const int STAT_MONSTERS_TOTAL         = 76;
- const int STAT_MONSTERS_KILLED        = 77;
- const int STAT_BUFFS                  = 78;
- const int STAT_NADE_BONUS             = 79;
- const int STAT_NADE_BONUS_TYPE        = 80;
- const int STAT_NADE_BONUS_SCORE       = 81;
- const int STAT_HEALING_ORB            = 82;
- const int STAT_HEALING_ORB_ALPHA      = 83;
- const int STAT_PLASMA                 = 84;
- const int STAT_OK_AMMO_CHARGE         = 85;
- const int STAT_OK_AMMO_CHARGEPOOL     = 86;
- const int STAT_FROZEN                 = 87;
- const int STAT_REVIVE_PROGRESS        = 88;
- const int STAT_WEAPON_NEXTTHINK       = 89;
- // 90 empty?
- // 91 empty?
- // 92 empty?
- // 93 empty?
- // 94 empty?
- // 95 empty?
- // 96 empty?
- // 97 empty?
- // 98 empty?
- const int STAT_ROUNDLOST              = 99;
+ const int MAX_CL_STATS = 256;
+ #ifndef CSQC
+ const int STAT_HEALTH = 0; // .health
+ const int STAT_ARMOR = 4; // .armorvalue
+ const int STAT_SHELLS = 6; // .ammo_shells
+ const int STAT_NAILS = 7; // .ammo_nails
+ const int STAT_ROCKETS = 8; // .ammo_rockets
+ const int STAT_CELLS = 9; // .ammo_cells
+ const int STAT_ACTIVEWEAPON = 10; // .weapon
+ const int STAT_ITEMS = 15; // .items | .items2 << 23 | serverflags << 28
+ const int STAT_VIEWHEIGHT = 16; // .view_ofs_z
+ #endif
+ REGISTER_STAT(WEAPONS, vectori)
+ REGISTER_STAT(WEAPONSINMAP, vectori)
+ REGISTER_STAT(PL_VIEW_OFS, vector, autocvar_sv_player_viewoffset)
+ REGISTER_STAT(PL_CROUCH_VIEW_OFS, vector, autocvar_sv_player_crouch_viewoffset)
+ REGISTER_STAT(PL_MIN, vector, autocvar_sv_player_mins)
+ REGISTER_STAT(PL_CROUCH_MIN, vector, autocvar_sv_player_crouch_mins)
+ REGISTER_STAT(PL_MAX, vector, autocvar_sv_player_maxs)
+ REGISTER_STAT(PL_CROUCH_MAX, vector, autocvar_sv_player_crouch_maxs)
+ REGISTER_STAT(KH_KEYS, int)
++
+ /** weapon requested to switch to; next WANTED weapon (for HUD) */
+ REGISTER_STAT(SWITCHWEAPON, int)
++/** weapon currently being switched to (is copied from switchweapon once switch is possible) */
++REGISTER_STAT(SWITCHINGWEAPON, int)
++REGISTER_STAT(WEAPON_NEXTTHINK, float)
++
+ REGISTER_STAT(GAMESTARTTIME, float)
+ REGISTER_STAT(STRENGTH_FINISHED, float)
+ REGISTER_STAT(INVINCIBLE_FINISHED, float)
+ /** arc heat in [0,1] */
+ REGISTER_STAT(ARC_HEAT, float)
+ REGISTER_STAT(PRESSED_KEYS, int)
+ /** this stat could later contain some other bits of info, like, more server-side particle config */
+ REGISTER_STAT(ALLOW_OLDVORTEXBEAM, bool)
+ REGISTER_STAT(FUEL, int)
+ REGISTER_STAT(NB_METERSTART, float)
+ /** compressShotOrigin */
+ REGISTER_STAT(SHOTORG, int)
+ REGISTER_STAT(LEADLIMIT, float)
+ REGISTER_STAT(WEAPON_CLIPLOAD, int)
+ REGISTER_STAT(WEAPON_CLIPSIZE, int)
+ REGISTER_STAT(VORTEX_CHARGE, float)
+ REGISTER_STAT(LAST_PICKUP, float)
+ REGISTER_STAT(HUD, int)
+ REGISTER_STAT(VORTEX_CHARGEPOOL, float)
+ REGISTER_STAT(HIT_TIME, float)
+ REGISTER_STAT(DAMAGE_DEALT_TOTAL, int)
+ REGISTER_STAT(TYPEHIT_TIME, float)
+ REGISTER_STAT(LAYED_MINES, int)
+ REGISTER_STAT(HAGAR_LOAD, int)
 -REGISTER_STAT(SWITCHINGWEAPON, int)
+ REGISTER_STAT(SUPERWEAPONS_FINISHED, float)
+ REGISTER_STAT(VEHICLESTAT_HEALTH, int)
+ REGISTER_STAT(VEHICLESTAT_SHIELD, int)
+ REGISTER_STAT(VEHICLESTAT_ENERGY, int)
+ REGISTER_STAT(VEHICLESTAT_AMMO1, int)
+ REGISTER_STAT(VEHICLESTAT_RELOAD1, int)
+ REGISTER_STAT(VEHICLESTAT_AMMO2, int)
+ REGISTER_STAT(VEHICLESTAT_RELOAD2, int)
+ REGISTER_STAT(VEHICLESTAT_W2MODE, int)
+ REGISTER_STAT(NADE_TIMER, float)
+ REGISTER_STAT(SECRETS_TOTAL, float)
+ REGISTER_STAT(SECRETS_FOUND, float)
+ REGISTER_STAT(RESPAWN_TIME, float)
+ REGISTER_STAT(ROUNDSTARTTIME, float)
+ REGISTER_STAT(MONSTERS_TOTAL, int)
+ REGISTER_STAT(MONSTERS_KILLED, int)
+ REGISTER_STAT(BUFFS, int)
+ REGISTER_STAT(NADE_BONUS, float)
+ REGISTER_STAT(NADE_BONUS_TYPE, int)
+ REGISTER_STAT(NADE_BONUS_SCORE, float)
+ REGISTER_STAT(HEALING_ORB, float)
+ REGISTER_STAT(HEALING_ORB_ALPHA, float)
+ REGISTER_STAT(PLASMA, int)
+ REGISTER_STAT(OK_AMMO_CHARGE, float)
+ REGISTER_STAT(OK_AMMO_CHARGEPOOL, float)
+ REGISTER_STAT(FROZEN, int)
+ REGISTER_STAT(REVIVE_PROGRESS, float)
+ REGISTER_STAT(ROUNDLOST, int)
+ REGISTER_STAT(BUFF_TIME, float)
+ REGISTER_STAT(CTF_FLAGSTATUS, int)
+ #ifdef SVQC
+ int autocvar_g_multijump;
+ float autocvar_g_multijump_add;
+ float autocvar_g_multijump_speed;
+ float autocvar_g_multijump_maxspeed;
+ float autocvar_g_multijump_dodging = 1;
+ #endif
+ REGISTER_STAT(MULTIJUMP_DODGING, int, autocvar_g_multijump_dodging)
+ REGISTER_STAT(MULTIJUMP_MAXSPEED, float, autocvar_g_multijump_maxspeed)
+ REGISTER_STAT(MULTIJUMP_ADD, int, autocvar_g_multijump_add)
+ REGISTER_STAT(MULTIJUMP_SPEED, float, autocvar_g_multijump_speed)
+ .int multijump_count;
+ REGISTER_STAT(MULTIJUMP_COUNT, int, this.multijump_count)
+ REGISTER_STAT(MULTIJUMP, int, autocvar_g_multijump)
+ REGISTER_STAT(DOUBLEJUMP, int, autocvar_sv_doublejump)
+ #ifdef SVQC
+ bool g_bugrigs;
+ bool g_bugrigs_planar_movement;
+ bool g_bugrigs_planar_movement_car_jumping;
+ float g_bugrigs_reverse_spinning;
+ float g_bugrigs_reverse_speeding;
+ float g_bugrigs_reverse_stopping;
+ float g_bugrigs_air_steering;
+ float g_bugrigs_angle_smoothing;
+ float g_bugrigs_friction_floor;
+ float g_bugrigs_friction_brake;
+ float g_bugrigs_friction_air;
+ float g_bugrigs_accel;
+ float g_bugrigs_speed_ref;
+ float g_bugrigs_speed_pow;
+ float g_bugrigs_steer;
+ #endif
+ REGISTER_STAT(BUGRIGS, int, g_bugrigs)
+ REGISTER_STAT(BUGRIGS_ACCEL, float, g_bugrigs_accel)
+ REGISTER_STAT(BUGRIGS_AIR_STEERING, int, g_bugrigs_air_steering)
+ REGISTER_STAT(BUGRIGS_ANGLE_SMOOTHING, int, g_bugrigs_angle_smoothing)
+ REGISTER_STAT(BUGRIGS_CAR_JUMPING, int, g_bugrigs_planar_movement_car_jumping)
+ REGISTER_STAT(BUGRIGS_FRICTION_AIR, float, g_bugrigs_friction_air)
+ REGISTER_STAT(BUGRIGS_FRICTION_BRAKE, float, g_bugrigs_friction_brake)
+ REGISTER_STAT(BUGRIGS_FRICTION_FLOOR, float, g_bugrigs_friction_floor)
+ REGISTER_STAT(BUGRIGS_PLANAR_MOVEMENT, int, g_bugrigs_planar_movement)
+ REGISTER_STAT(BUGRIGS_REVERSE_SPEEDING, int, g_bugrigs_reverse_speeding)
+ REGISTER_STAT(BUGRIGS_REVERSE_SPINNING, int, g_bugrigs_reverse_spinning)
+ REGISTER_STAT(BUGRIGS_REVERSE_STOPPING, int, g_bugrigs_reverse_stopping)
+ REGISTER_STAT(BUGRIGS_SPEED_POW, float, g_bugrigs_speed_pow)
+ REGISTER_STAT(BUGRIGS_SPEED_REF, float, g_bugrigs_speed_ref)
+ REGISTER_STAT(BUGRIGS_STEER, float, g_bugrigs_steer)
+ REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, cvar("sv_gameplayfix_downtracesupportsongroundflag"))
+ REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, cvar("sv_gameplayfix_easierwaterjump"))
+ REGISTER_STAT(GAMEPLAYFIX_STEPDOWN, int, cvar("sv_gameplayfix_stepdown"))
+ REGISTER_STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, int, cvar("sv_gameplayfix_stepmultipletimes"))
+ REGISTER_STAT(GAMEPLAYFIX_UNSTICKPLAYERS, int, cvar("sv_gameplayfix_unstickplayers"))
+ REGISTER_STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, int, autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag)
+ REGISTER_STAT(MOVEVARS_JUMPSTEP, int, cvar("sv_jumpstep"))
+ REGISTER_STAT(NOSTEP, int, cvar("sv_nostep"))
+ REGISTER_STAT(MOVEVARS_FRICTION, float)
+ REGISTER_STAT(MOVEVARS_FRICTION_SLICK, float, autocvar_sv_friction_slick)
+ REGISTER_STAT(MOVEVARS_FRICTION_ONLAND, float, autocvar_sv_friction_on_land)
+ REGISTER_STAT(MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, int, autocvar_sv_jumpspeedcap_max_disable_on_ramps)
+ REGISTER_STAT(MOVEVARS_TRACK_CANJUMP, int)
+ /** cvar loopback */
+ REGISTER_STAT(MOVEVARS_CL_TRACK_CANJUMP, int)
+ #ifdef SVQC
+ int g_dodging;
+ float autocvar_sv_dodging_delay;
+ float autocvar_sv_dodging_wall_distance_threshold;
+ bool autocvar_sv_dodging_frozen;
+ bool autocvar_sv_dodging_frozen_doubletap;
+ float autocvar_sv_dodging_height_threshold;
+ float autocvar_sv_dodging_horiz_speed;
+ float autocvar_sv_dodging_horiz_speed_frozen;
+ float autocvar_sv_dodging_ramp_time;
+ float autocvar_sv_dodging_up_speed;
+ bool autocvar_sv_dodging_wall_dodging;
+ #endif
+ REGISTER_STAT(DODGING, int, g_dodging)
+ REGISTER_STAT(DODGING_DELAY, float, autocvar_sv_dodging_delay)
+ REGISTER_STAT(DODGING_DISTANCE_THRESHOLD, float, autocvar_sv_dodging_wall_distance_threshold)
+ REGISTER_STAT(DODGING_FROZEN, int, autocvar_sv_dodging_frozen)
+ REGISTER_STAT(DODGING_FROZEN_NO_DOUBLETAP, int, autocvar_sv_dodging_frozen_doubletap)
+ REGISTER_STAT(DODGING_HEIGHT_THRESHOLD, float, autocvar_sv_dodging_height_threshold)
+ REGISTER_STAT(DODGING_HORIZ_SPEED, float, autocvar_sv_dodging_horiz_speed)
+ REGISTER_STAT(DODGING_HORIZ_SPEED_FROZEN, float, autocvar_sv_dodging_horiz_speed_frozen)
+ REGISTER_STAT(DODGING_RAMP_TIME, float, autocvar_sv_dodging_ramp_time)
+ /** cvar loopback */
+ REGISTER_STAT(DODGING_TIMEOUT, float)
+ REGISTER_STAT(DODGING_UP_SPEED, float, autocvar_sv_dodging_up_speed)
+ REGISTER_STAT(DODGING_WALL, int, autocvar_sv_dodging_wall_dodging)
+ REGISTER_STAT(JETPACK_ACCEL_SIDE, float, autocvar_g_jetpack_acceleration_side)
+ REGISTER_STAT(JETPACK_ACCEL_UP, float, autocvar_g_jetpack_acceleration_up)
+ REGISTER_STAT(JETPACK_ANTIGRAVITY, float, autocvar_g_jetpack_antigravity)
+ REGISTER_STAT(JETPACK_FUEL, float, autocvar_g_jetpack_fuel)
+ REGISTER_STAT(JETPACK_MAXSPEED_SIDE, float, autocvar_g_jetpack_maxspeed_side)
+ REGISTER_STAT(JETPACK_MAXSPEED_UP, float, autocvar_g_jetpack_maxspeed_up)
  
- /* The following stats change depending on the gamemode, so can share the same ID */
- // IDs 100 to 104 reserved for gamemodes
+ REGISTER_STAT(MOVEVARS_HIGHSPEED, float, autocvar_g_movement_highspeed)
  
- // freeze tag, clan arena, jailbreak
- const int STAT_REDALIVE               = 100;
- const int STAT_BLUEALIVE              = 101;
- const int STAT_YELLOWALIVE            = 102;
- const int STAT_PINKALIVE              = 103;
+ // freeze tag, clan arena
+ REGISTER_STAT(REDALIVE, int)
+ REGISTER_STAT(BLUEALIVE, int)
+ REGISTER_STAT(YELLOWALIVE, int)
+ REGISTER_STAT(PINKALIVE, int)
  
  // domination
- const int STAT_DOM_TOTAL_PPS          = 100;
- const int STAT_DOM_PPS_RED            = 101;
- const int STAT_DOM_PPS_BLUE           = 102;
- const int STAT_DOM_PPS_YELLOW         = 103;
- const int STAT_DOM_PPS_PINK           = 104;
+ REGISTER_STAT(DOM_TOTAL_PPS, float)
+ REGISTER_STAT(DOM_PPS_RED, float)
+ REGISTER_STAT(DOM_PPS_BLUE, float)
+ REGISTER_STAT(DOM_PPS_YELLOW, float)
+ REGISTER_STAT(DOM_PPS_PINK, float)
  
- // vip
- const int STAT_VIP                    = 100;
- const int STAT_VIP_RED                = 101;
- const int STAT_VIP_BLUE               = 102;
- const int STAT_VIP_YELLOW             = 103;
- const int STAT_VIP_PINK               = 104;
+ REGISTER_STAT(TELEPORT_MAXSPEED, float, autocvar_g_teleport_maxspeed)
+ REGISTER_STAT(TELEPORT_TELEFRAG_AVOID, int, autocvar_g_telefrags_avoid)
  
- // key hunt
- const int STAT_KH_REDKEY_TEAM         = 100;
- const int STAT_KH_BLUEKEY_TEAM        = 101;
- const int STAT_KH_YELLOWKEY_TEAM      = 102;
- const int STAT_KH_PINKKEY_TEAM        = 103;
+ #ifdef SVQC
+ #include "movetypes/movetypes.qh"
+ #endif
+ REGISTER_STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, float)
+ REGISTER_STAT(MOVEVARS_AIRCONTROL_PENALTY, float)
+ REGISTER_STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, float)
+ REGISTER_STAT(MOVEVARS_AIRSTRAFEACCEL_QW, float)
+ REGISTER_STAT(MOVEVARS_AIRCONTROL_POWER, float)
+ noref bool autocvar_sv_gameplayfix_nogravityonground;
+ REGISTER_STAT(MOVEFLAGS, int, MOVEFLAG_VALID
+                               | (autocvar_sv_gameplayfix_q2airaccelerate ? MOVEFLAG_Q2AIRACCELERATE : 0)
+                               | (autocvar_sv_gameplayfix_nogravityonground ? MOVEFLAG_NOGRAVITYONGROUND : 0)
+                               | (autocvar_sv_gameplayfix_gravityunaffectedbyticrate ? MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE : 0))
  
- /* Gamemode-specific stats end here */
+ REGISTER_STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, float)
+ REGISTER_STAT(MOVEVARS_WARSOWBUNNY_ACCEL, float)
+ REGISTER_STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, float)
+ REGISTER_STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, float)
+ REGISTER_STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, float)
  
- const int STAT_PL_VIEW_OFS1           = 105;
- const int STAT_PL_VIEW_OFS2           = 106;
- const int STAT_PL_VIEW_OFS3           = 107;
- const int STAT_PL_MIN1                = 108;
- const int STAT_PL_MIN2                = 109;
- const int STAT_PL_MIN3                = 110;
- const int STAT_PL_MAX1                = 111;
- const int STAT_PL_MAX2                = 112;
- const int STAT_PL_MAX3                = 113;
- const int STAT_PL_CROUCH_MIN1         = 114;
- const int STAT_PL_CROUCH_MIN2         = 115;
- const int STAT_PL_CROUCH_MIN3         = 116;
- const int STAT_PL_CROUCH_MAX1         = 117;
- const int STAT_PL_CROUCH_MAX2         = 118;
- const int STAT_PL_CROUCH_MAX3         = 119;
- const int STAT_PL_CROUCH_VIEW_OFS1    = 117;
- const int STAT_PL_CROUCH_VIEW_OFS2    = 118;
- const int STAT_PL_CROUCH_VIEW_OFS3    = 119;
- const int STAT_WEAPONSINMAP           = 120;
- const int STAT_WEAPONSINMAP2          = 121;
- const int STAT_WEAPONSINMAP3          = 122;
- const int STAT_BUFF_TIME              = 123;
- const int STAT_CTF_FLAGSTATUS         = 124;
- // 125 empty?
- // 126 empty?
- // 127 empty?
- // 128 empty?
- // 129 empty?
- // 130 empty?
- // 131 empty?
- // 132 empty?
- // 133 empty?
- // 134 empty?
- // 135 empty?
- // 136 empty?
- // 137 empty?
- // 138 empty?
- // 139 empty?
- // 140 reserved
- // 141 reserved
- // 142 reserved
- // 143 reserved
- // 144 reserved
- // 145 reserved
- // 146 reserved
- // 147 reserved
- // 148 reserved
- // 149 reserved
- // 150 reserved
- // 151 reserved
- // 152 reserved
- // 153 reserved
- // 154 reserved
- // 155 reserved
- // 156 empty?
- // 157 empty?
- // 158 empty?
- // 159 empty?
- // 160 empty?
- // 161 empty?
- // 162 empty?
- // 162 empty?
- // 163 empty?
- // 164 empty?
- // 165 empty?
- const int STAT_MULTIJUMP_DODGING                      = 166;
- const int STAT_MULTIJUMP_MAXSPEED                     = 167;
- const int STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND   = 168;
- const int STAT_BUGRIGS_REVERSE_STOPPING               = 169;
- const int STAT_BUGRIGS_REVERSE_SPINNING               = 170;
- const int STAT_BUGRIGS_CAR_JUMPING                    = 171;
- const int STAT_BUGRIGS_FRICTION_AIR                   = 172;
- const int STAT_BUGRIGS_STEER                          = 173;
- const int STAT_BUGRIGS_SPEED_POW                      = 174;
- const int STAT_BUGRIGS_SPEED_REF                      = 175;
- const int STAT_BUGRIGS_ACCEL                          = 176;
- const int STAT_BUGRIGS_FRICTION_BRAKE                 = 177;
- const int STAT_BUGRIGS_AIR_STEERING                   = 178;
- const int STAT_BUGRIGS_FRICTION_FLOOR                 = 179;
- const int STAT_BUGRIGS_REVERSE_SPEEDING               = 180;
- const int STAT_BUGRIGS_PLANAR_MOVEMENT                = 181;
- const int STAT_BUGRIGS_ANGLE_SMOOTHING                = 182;
- const int STAT_BUGRIGS                                = 183;
- const int STAT_GAMEPLAYFIX_STEPDOWN                   = 184;
- const int STAT_MOVEVARS_JUMPSTEP                      = 185;
- const int STAT_NOSTEP                                 = 186;
- const int STAT_GAMEPLAYFIX_UNSTICKPLAYERS             = 187;
- const int STAT_GAMEPLAYFIX_STEPMULTIPLETIMES          = 188;
- const int STAT_GAMEPLAYFIX_DOWNTRACEONGROUND          = 189;
- const int STAT_GAMEPLAYFIX_EASIERWATERJUMP            = 190;
- const int STAT_MOVEVARS_FRICTION_SLICK                = 191;
- const int STAT_MOVEVARS_FRICTION_ONLAND               = 192;
- const int STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS  = 193;
- const int STAT_MOVEVARS_TRACK_CANJUMP                 = 194;
- // 195 empty?
- const int STAT_DOUBLEJUMP                             = 196;
- const int STAT_MOVEVARS_CL_TRACK_CANJUMP              = 197;
- const int STAT_MULTIJUMP_ADD                          = 198;
- const int STAT_MULTIJUMP_SPEED                        = 199;
- const int STAT_MULTIJUMP                              = 200;
- const int STAT_DODGING_TIMEOUT                        = 201;
- const int STAT_DODGING_WALL                           = 202;
- const int STAT_DODGING_UP_SPEED                       = 203;
- const int STAT_DODGING_RAMP_TIME                      = 204;
- const int STAT_DODGING_HEIGHT_THRESHOLD               = 205;
- const int STAT_DODGING_DISTANCE_THRESHOLD             = 206;
- const int STAT_DODGING_HORIZ_SPEED                    = 207;
- const int STAT_DODGING_DELAY                          = 208;
- const int STAT_DODGING_FROZEN_NO_DOUBLETAP            = 209;
- const int STAT_DODGING_HORIZ_SPEED_FROZEN             = 210;
- const int STAT_DODGING                                = 211;
- const int STAT_DODGING_FROZEN                         = 212;
- const int STAT_JETPACK_MAXSPEED_UP                    = 213;
- const int STAT_JETPACK_MAXSPEED_SIDE                  = 214;
- const int STAT_JETPACK_FUEL                           = 215;
- const int STAT_JETPACK_ANTIGRAVITY                    = 216;
- const int STAT_JETPACK_ACCEL_SIDE                     = 217;
- const int STAT_JETPACK_ACCEL_UP                       = 218;
- const int STAT_MOVEVARS_HIGHSPEED                     = 219;
- const int STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR     = 220;
- const int STAT_MOVEVARS_AIRCONTROL_PENALTY            = 221;
- const int STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW           = 222;
- const int STAT_MOVEVARS_AIRSTRAFEACCEL_QW             = 223;
- const int STAT_MOVEVARS_AIRCONTROL_POWER              = 224;
- const int STAT_MOVEFLAGS                              = 225;
- const int STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL   = 226;
- const int STAT_MOVEVARS_WARSOWBUNNY_ACCEL             = 227;
- const int STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED          = 228;
- const int STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL         = 229;
- const int STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO   = 230;
- const int STAT_MOVEVARS_AIRSTOPACCELERATE             = 231;
- const int STAT_MOVEVARS_AIRSTRAFEACCELERATE           = 232;
- const int STAT_MOVEVARS_MAXAIRSTRAFESPEED             = 233;
- const int STAT_MOVEVARS_AIRCONTROL                    = 234;
- // -Wdouble-declaration
- // const int STAT_FRAGLIMIT                              = 235;
- // -Wdouble-declaration
- // const int STAT_TIMELIMIT                              = 236;
- const int STAT_MOVEVARS_WALLFRICTION                  = 237;
- const int STAT_MOVEVARS_FRICTION                      = 238;
- const int STAT_MOVEVARS_WATERFRICTION                 = 239;
- // -Wdouble-declaration
- // const int STAT_MOVEVARS_TICRATE                       = 240;
- // -Wdouble-declaration
- // const int STAT_MOVEVARS_TIMESCALE                     = 241;
- // -Wdouble-declaration
- // const int STAT_MOVEVARS_GRAVITY                       = 242;
- const int STAT_MOVEVARS_STOPSPEED                     = 243;
- const int STAT_MOVEVARS_MAXSPEED                      = 244;
- const int STAT_MOVEVARS_SPECTATORMAXSPEED             = 245;
- const int STAT_MOVEVARS_ACCELERATE                    = 246;
- const int STAT_MOVEVARS_AIRACCELERATE                 = 247;
- const int STAT_MOVEVARS_WATERACCELERATE               = 248;
- const int STAT_MOVEVARS_ENTGRAVITY                    = 249;
- const int STAT_MOVEVARS_JUMPVELOCITY                  = 250;
- const int STAT_MOVEVARS_EDGEFRICTION                  = 251;
- const int STAT_MOVEVARS_MAXAIRSPEED                   = 252;
- const int STAT_MOVEVARS_STEPHEIGHT                    = 253;
- const int STAT_MOVEVARS_AIRACCEL_QW                   = 254;
- const int STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION    = 255;
+ REGISTER_STAT(MOVEVARS_AIRSTOPACCELERATE, float)
+ REGISTER_STAT(MOVEVARS_AIRSTRAFEACCELERATE, float)
+ REGISTER_STAT(MOVEVARS_MAXAIRSTRAFESPEED, float)
+ REGISTER_STAT(MOVEVARS_AIRCONTROL, float)
+ REGISTER_STAT(FRAGLIMIT, float, autocvar_fraglimit)
+ REGISTER_STAT(TIMELIMIT, float, autocvar_timelimit)
+ #ifdef SVQC
+ float autocvar_sv_wallfriction;
+ #endif
+ REGISTER_STAT(MOVEVARS_WALLFRICTION, int, autocvar_sv_wallfriction)
+ REGISTER_STAT(MOVEVARS_TICRATE, float, autocvar_sys_ticrate)
+ REGISTER_STAT(MOVEVARS_TIMESCALE, float, autocvar_slowmo)
+ REGISTER_STAT(MOVEVARS_GRAVITY, float, autocvar_sv_gravity)
+ REGISTER_STAT(MOVEVARS_STOPSPEED, float)
+ REGISTER_STAT(MOVEVARS_MAXSPEED, float)
+ REGISTER_STAT(MOVEVARS_ACCELERATE, float)
+ REGISTER_STAT(MOVEVARS_AIRACCELERATE, float)
+ .float gravity;
+ // FIXME: Was 0 on server, 1 on client. Still want that?
+ REGISTER_STAT(MOVEVARS_ENTGRAVITY, float, (this.gravity) ? this.gravity : 1)
+ REGISTER_STAT(MOVEVARS_JUMPVELOCITY, float)
+ REGISTER_STAT(MOVEVARS_MAXAIRSPEED, float)
+ REGISTER_STAT(MOVEVARS_STEPHEIGHT, float, autocvar_sv_stepheight)
+ REGISTER_STAT(MOVEVARS_AIRACCEL_QW, float)
+ REGISTER_STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, float)
  #endif
index 5e3f543fa5441bcc757891fad5083df4f8a930c1,fa68533f4afcb594a6d727389fc65e4d23c78482..19ccde9dca08ec764fa86fd5a0a788e915642d36
@@@ -15,7 -15,7 +15,7 @@@
  
  #elif defined(CSQC)
  
-       void _Movetype_LinkEdict(float touch_triggers);
+       void _Movetype_LinkEdict(entity this, float touch_triggers);
  
        #define SUB_ANGLES(s)   (s).move_angles
        #define SUB_VELOCITY    move_velocity
        void SUB_SETORIGIN(entity s, vector v)
        {SELFPARAM();
                s.move_origin = v;
-               WITH(entity, self, s, _Movetype_LinkEdict(true));
+               _Movetype_LinkEdict(s, true);
        }
  
  #endif
  
- void SUB_Remove();
  void SUB_SetFade (entity ent, float when, float fading_time);
  void SUB_VanishOrRemove (entity ent);
  
  .vector destvec;
  .vector destvec2;
  
 -// player animation state
 -.float animstate_startframe;
 -.float animstate_numframes;
 -.float animstate_framerate;
 -.float animstate_starttime;
 -.float animstate_endtime;
 -.float animstate_override;
 -.float animstate_looping;
 -
  .float        delay;
  .float        wait;
  .float        lip;
index fed883f069ead505e0afe43ec181ac9b49be6534,f7ba35cc407ed9e2cea30a5bd6af2dc604da5fef..849403f8713740773c0c7d780b6213b073064f96
@@@ -11,7 -11,6 +11,6 @@@
        #include "../../lib/warpzone/common.qh"
        #include "../../lib/warpzone/client.qh"
        #include "../util.qh"
-       #include "../buffs/all.qh"
        #include "../../client/autocvars.qh"
        #include "../deathtypes/all.qh"
        #include "../../lib/csqcmodel/interpolate.qh"
        #include "../../lib/csqcmodel/cl_model.qh"
  #elif defined(MENUQC)
  #elif defined(SVQC)
-       #include "../../lib/warpzone/anglestransform.qh"
-       #include "../../lib/warpzone/common.qh"
-       #include "../../lib/warpzone/util_server.qh"
-       #include "../../lib/warpzone/server.qh"
-       #include "../constants.qh"
-       #include "../stats.qh"
-       #include "../teams.qh"
-       #include "../util.qh"
-       #include "../buffs/all.qh"
-       #include "../monsters/all.qh"
-       #include "config.qh"
-       #include "../../server/weapons/csqcprojectile.qh"
-       #include "../../server/weapons/tracing.qh"
-       #include "../../server/t_items.qh"
-       #include "../../server/autocvars.qh"
-       #include "../../server/constants.qh"
-       #include "../../server/defs.qh"
-       #include "../notifications.qh"
-       #include "../deathtypes/all.qh"
-       #include "../../server/mutators/all.qh"
-       #include "../mapinfo.qh"
-       #include "../../server/command/common.qh"
-       #include "../../lib/csqcmodel/sv_model.qh"
-       #include "../../server/portals.qh"
-       #include "../../server/g_hook.qh"
+     #include "../../lib/warpzone/anglestransform.qh"
+     #include "../../lib/warpzone/common.qh"
+     #include "../../lib/warpzone/util_server.qh"
+     #include "../../lib/warpzone/server.qh"
+     #include "../constants.qh"
+     #include "../stats.qh"
+     #include "../teams.qh"
+     #include "../util.qh"
+     #include "../monsters/all.qh"
+     #include "config.qh"
+     #include "../../server/weapons/csqcprojectile.qh"
+     #include "../../server/weapons/tracing.qh"
+     #include "../../server/t_items.qh"
+     #include "../../server/autocvars.qh"
+     #include "../../server/constants.qh"
+     #include "../../server/defs.qh"
+     #include "../notifications.qh"
+     #include "../deathtypes/all.qh"
+     #include "../../server/mutators/all.qh"
+     #include "../mapinfo.qh"
+     #include "../../server/command/common.qh"
+     #include "../../lib/csqcmodel/sv_model.qh"
+     #include "../../server/portals.qh"
+     #include "../../server/g_hook.qh"
  #endif
  #ifndef MENUQC
 -#include "calculations.qc"
 +      #include "calculations.qc"
  #endif
  #define IMPLEMENTATION
  #include "all.inc"
  
  // WEAPON PLUGIN SYSTEM
  
- WepSet WepSet_FromWeapon(int a)
 -WepSet _WepSet_FromWeapon(int a) {
++WepSet _WepSet_FromWeapon(int a)
 +{
        a -= WEP_FIRST;
        if (Weapons_MAX > 24)
 -      if (a >= 24) {
 -              a -= 24;
 -              if (Weapons_MAX > 48)
 -              if (a >= 24) {
 +              if (a >= 24)
 +              {
                        a -= 24;
 -                      return '0 0 1' * power2of(a);
 +                      if (Weapons_MAX > 48)
 +                              if (a >= 24)
 +                              {
 +                                      a -= 24;
 +                                      return '0 0 1' * power2of(a);
 +                              }
 +                      return '0 1 0' * power2of(a);
                }
 -              return '0 1 0' * power2of(a);
 -      }
        return '1 0 0' * power2of(a);
  }
  #ifdef SVQC
-       void WepSet_AddStat()
-       {
-               addstat(STAT_WEAPONS, AS_INT, weapons_x);
-               if (Weapons_MAX > 24) addstat(STAT_WEAPONS2, AS_INT, weapons_y);
-               if (Weapons_MAX > 48) addstat(STAT_WEAPONS3, AS_INT, weapons_z);
-       }
-       void WepSet_AddStat_InMap()
-       {
-               addstat(STAT_WEAPONSINMAP, AS_INT, weaponsinmap_x);
-               if (Weapons_MAX > 24) addstat(STAT_WEAPONSINMAP2, AS_INT, weaponsinmap_y);
-               if (Weapons_MAX > 48) addstat(STAT_WEAPONSINMAP3, AS_INT, weaponsinmap_z);
-       }
 -void WriteWepSet(float dst, WepSet w)
 -{
 -      if (Weapons_MAX > 48)
 -      WriteInt72_t(dst, w);
 -      else if (Weapons_MAX > 24)
 -      WriteInt48_t(dst, w);
 -      else
 -      WriteInt24_t(dst, w.x);
 -}
 +      void WriteWepSet(float dst, WepSet w)
 +      {
 +              if (Weapons_MAX > 48) WriteInt72_t(dst, w);
 +              else if (Weapons_MAX > 24) WriteInt48_t(dst, w);
 +              else WriteInt24_t(dst, w.x);
 +      }
  #endif
  #ifdef CSQC
 -WepSet WepSet_GetFromStat()
 -{
 -      return STAT(WEAPONS);
 -}
 -WepSet WepSet_GetFromStat_InMap()
 -{
 -      return STAT(WEAPONSINMAP);
 -}
 -WepSet ReadWepSet()
 -{
 -      if (Weapons_MAX > 48)
 -      return ReadInt72_t();
 -      if (Weapons_MAX > 24)
 -      return ReadInt48_t();
 -      return ReadInt24_t() * '1 0 0';
 -}
 +      WepSet WepSet_GetFromStat()
 +      {
-               WepSet w = '0 0 0';
-               w.x = getstati(STAT_WEAPONS);
-               if (Weapons_MAX > 24) w.y = getstati(STAT_WEAPONS2);
-               if (Weapons_MAX > 48) w.z = getstati(STAT_WEAPONS3);
-               return w;
++              return STAT(WEAPONS);
 +      }
 +      WepSet WepSet_GetFromStat_InMap()
 +      {
-               WepSet w = '0 0 0';
-               w_x = getstati(STAT_WEAPONSINMAP);
-               if (Weapons_MAX > 24) w_y = getstati(STAT_WEAPONSINMAP2);
-               if (Weapons_MAX > 48) w_z = getstati(STAT_WEAPONSINMAP3);
-               return w;
++              return STAT(WEAPONSINMAP);
 +      }
 +      WepSet ReadWepSet()
 +      {
 +              if (Weapons_MAX > 48) return ReadInt72_t();
 +              if (Weapons_MAX > 24) return ReadInt48_t();
 +              return ReadInt24_t() * '1 0 0';
 +      }
  #endif
  
  string W_FixWeaponOrder(string order, float complete)
  string W_NameWeaponOrder_MapFunc(string s)
  {
        entity wi;
 -      if(s == "0" || stof(s))
 +      if (s == "0" || stof(s))
        {
                wi = get_weaponinfo(stof(s));
 -              if(wi != WEP_Null)
 -                      return wi.netname;
 +              if (wi != WEP_Null) return wi.netname;
        }
        return s;
  }
  
  string W_UndeprecateName(string s)
  {
 -      switch ( s )
 +      switch (s)
        {
 -              case "nex"            : return "vortex";
 -              case "rocketlauncher" : return "devastator";
 -              case "laser"          : return "blaster";
 -              case "minstanex"      : return "vaporizer";
 +              case "nex": return "vortex";
 +              case "rocketlauncher": return "devastator";
 +              case "laser": return "blaster";
 +              case "minstanex": return "vaporizer";
                case "grenadelauncher": return "mortar";
 -              case "uzi"            : return "machinegun";
 -              default               : return s;
 +              case "uzi": return "machinegun";
 +              default: return s;
        }
  }
  string W_NameWeaponOrder(string order)
  string W_NumberWeaponOrder_MapFunc(string s)
  {
        int i;
 -      if(s == "0" || stof(s))
 -              return s;
 +      if (s == "0" || stof(s)) return s;
        s = W_UndeprecateName(s);
 -      for(i = WEP_FIRST; i <= WEP_LAST; ++i)
 -              if(s == get_weaponinfo(i).netname)
 -                      return ftos(i);
 +      for (i = WEP_FIRST; i <= WEP_LAST; ++i)
 +              if (s == get_weaponinfo(i).netname) return ftos(i);
        return s;
  }
  string W_NumberWeaponOrder(string order)
@@@ -179,24 -162,23 +157,24 @@@ float W_FixWeaponOrder_BuildImpulseList
        e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
        e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
        d = (e1.impulse + 9) % 10 - (e2.impulse + 9) % 10;
 -      if(d != 0)
 -              return -d; // high impulse first!
 -      return
 -              strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
 -              -
 -              strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
 -              ; // low char index first!
 +      if (d != 0) return -d;  // high impulse first!
 +      return strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "),
 +              sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
 +             -
 +             strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "),
 +              sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
 +       // low char index first!
  }
  string W_FixWeaponOrder_BuildImpulseList(string o)
  {
        int i;
        W_FixWeaponOrder_BuildImpulseList_order = o;
 -      for(i = WEP_FIRST; i <= WEP_LAST; ++i)
 +      for (i = WEP_FIRST; i <= WEP_LAST; ++i)
                W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
 -      heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
 +      heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp,
 +              world);
        o = "";
 -      for(i = WEP_FIRST; i <= WEP_LAST; ++i)
 +      for (i = WEP_FIRST; i <= WEP_LAST; ++i)
                o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
        W_FixWeaponOrder_BuildImpulseList_order = string_null;
        return substring(o, 1, -1);
@@@ -209,7 -191,8 +187,7 @@@ string W_FixWeaponOrder_AllowIncomplete
  
  string W_FixWeaponOrder_ForceComplete(string order)
  {
 -      if(order == "")
 -              order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
 +      if (order == "") order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
        return W_FixWeaponOrder(order, 1);
  }
  
@@@ -220,11 -203,12 +198,11 @@@ void W_RandomWeapons(entity e, float n
        WepSet result;
        remaining = e.weapons;
        result = '0 0 0';
 -      for(i = 0; i < n; ++i)
 +      for (i = 0; i < n; ++i)
        {
                RandomSelection_Init();
 -              for(j = WEP_FIRST; j <= WEP_LAST; ++j)
 -                      if(remaining & WepSet_FromWeapon(j))
 -                              RandomSelection_Add(world, j, string_null, 1, 1);
 +              for (j = WEP_FIRST; j <= WEP_LAST; ++j)
 +                      if (remaining & WepSet_FromWeapon(j)) RandomSelection_Add(world, j, string_null, 1, 1);
                result |= WepSet_FromWeapon(RandomSelection_chosen_float);
                remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float);
        }
@@@ -241,48 -225,48 +219,48 @@@ string GetAmmoPicture(.int ammotype
                case ammo_cells:   return ITEM_Cells.m_icon;
                case ammo_plasma:  return ITEM_Plasma.m_icon;
                case ammo_fuel:    return ITEM_JetpackFuel.m_icon;
 -              default: return ""; // wtf, no ammo type?
 +              default: return "";  // wtf, no ammo type?
        }
  }
  
  #ifdef CSQC
 -.int GetAmmoFieldFromNum(int i)
 -{
 -      switch(i)
 +      .int GetAmmoFieldFromNum(int i)
        {
 -              case 0: return ammo_shells;
 -              case 1: return ammo_nails;
 -              case 2: return ammo_rockets;
 -              case 3: return ammo_cells;
 -              case 4: return ammo_plasma;
 -              case 5: return ammo_fuel;
 -              default: return ammo_none;
 +              switch (i)
 +              {
 +                      case 0: return ammo_shells;
 +                      case 1: return ammo_nails;
 +                      case 2: return ammo_rockets;
 +                      case 3: return ammo_cells;
 +                      case 4: return ammo_plasma;
 +                      case 5: return ammo_fuel;
 +                      default: return ammo_none;
 +              }
        }
 -}
  
 -int GetAmmoStat(.int ammotype)
 -{
 -      switch(ammotype)
 +      int GetAmmoStat(.int ammotype)
        {
 -              case ammo_shells: return STAT_SHELLS;
 -              case ammo_nails: return STAT_NAILS;
 -              case ammo_rockets: return STAT_ROCKETS;
 -              case ammo_cells: return STAT_CELLS;
 -              case ammo_plasma: return STAT_PLASMA.m_id;
 -              case ammo_fuel: return STAT_FUEL.m_id;
 -              default: return -1;
 +              switch (ammotype)
 +              {
 +                      case ammo_shells: return STAT_SHELLS;
 +                      case ammo_nails: return STAT_NAILS;
 +                      case ammo_rockets: return STAT_ROCKETS;
 +                      case ammo_cells: return STAT_CELLS;
-                       case ammo_plasma: return STAT_PLASMA;
-                       case ammo_fuel: return STAT_FUEL;
++                      case ammo_plasma: return STAT_PLASMA.m_id;
++                      case ammo_fuel: return STAT_FUEL.m_id;
 +                      default: return -1;
 +              }
        }
 -}
  #endif
  
  string W_Sound(string w_snd)
  {
        string output = strcat("weapons/", w_snd);
  #ifdef SVQC
 -      MUTATOR_CALLHOOK(WeaponSound, w_snd, output);
 -      return weapon_sound_output;
 +              MUTATOR_CALLHOOK(WeaponSound, w_snd, output);
 +              return weapon_sound_output;
  #else
 -      return output;
 +              return output;
  #endif
  }
  
@@@ -290,346 -274,11 +268,346 @@@ string W_Model(string w_mdl
  {
        string output = strcat("models/weapons/", w_mdl);
  #ifdef SVQC
 -      MUTATOR_CALLHOOK(WeaponModel, w_mdl, output);
 -      return weapon_model_output;
 +              MUTATOR_CALLHOOK(WeaponModel, w_mdl, output);
 +              return weapon_model_output;
  #else
 -      return output;
 +              return output;
 +#endif
 +}
 +
 +#ifndef MENUQC
 +vector shotorg_adjustfromclient(vector vecs, float y_is_right, float algn)
 +{
 +      switch (algn)
 +      {
 +              default:
 +              case 3:
 +                      // right alignment
 +                      break;
 +              case 4:
 +                      // left
 +                      vecs.y = -vecs.y;
 +                      break;
 +              case 1:
 +              case 2:
 +                      // center
 +                      vecs.y = 0;
 +                      vecs.z -= 2;
 +                      break;
 +      }
 +      return vecs;
 +}
 +
 +vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn)
 +{
 +#ifdef SVQC
 +      string s;
  #endif
 +      if (visual)
 +      {
 +              vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
 +      }
 +#ifdef SVQC
 +      else if (autocvar_g_shootfromeye)
 +      {
 +              vecs.y = vecs.z = 0;
 +      }
 +      else if (autocvar_g_shootfromcenter)
 +      {
 +              vecs.y = 0;
 +              vecs.z -= 2;
 +      }
 +      else if ((s = autocvar_g_shootfromfixedorigin) != "")
 +      {
 +              vector v = stov(s);
 +              if (y_is_right) v.y = -v.y;
 +              if (v.x != 0) vecs.x = v.x;
 +              vecs.y = v.y;
 +              vecs.z = v.z;
 +      }
 +#endif
 +      else  // just do the same as top
 +      {
 +              vecs = shotorg_adjustfromclient(vecs, y_is_right, algn);
 +      }
 +
 +      return vecs;
  }
  
 +#define shotorg_adjust shotorg_adjust_values
 +
 +/**
 + * supported formats:
 + *
 + * 1. simple animated model, muzzle flash handling on h_ model:
 + *    h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
 + *      tags:
 + *        shot = muzzle end (shot origin, also used for muzzle flashes)
 + *        shell = casings ejection point (must be on the right hand side of the gun)
 + *        weapon = attachment for v_tuba.md3
 + *    v_tuba.md3 - first and third person model
 + *    g_tuba.md3 - pickup model
 + *
 + * 2. simple animated model, muzzle flash handling on v_ model:
 + *    h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
 + *      tags:
 + *        weapon = attachment for v_tuba.md3
 + *    v_tuba.md3 - first and third person model
 + *      tags:
 + *        shot = muzzle end (shot origin, also used for muzzle flashes)
 + *        shell = casings ejection point (must be on the right hand side of the gun)
 + *    g_tuba.md3 - pickup model
 + *
 + * 3. fully animated model, muzzle flash handling on h_ model:
 + *    h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
 + *      tags:
 + *        shot = muzzle end (shot origin, also used for muzzle flashes)
 + *        shell = casings ejection point (must be on the right hand side of the gun)
 + *        handle = corresponding to the origin of v_tuba.md3 (used for muzzle flashes)
 + *    v_tuba.md3 - third person model
 + *    g_tuba.md3 - pickup model
 + *
 + * 4. fully animated model, muzzle flash handling on v_ model:
 + *    h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
 + *      tags:
 + *        shot = muzzle end (shot origin)
 + *        shell = casings ejection point (must be on the right hand side of the gun)
 + *    v_tuba.md3 - third person model
 + *      tags:
 + *        shot = muzzle end (for muzzle flashes)
 + *    g_tuba.md3 - pickup model
 + *
 + * writes:
 + *   this.origin, this.angles
 + *   this.weaponchild
 + *   this.movedir, this.view_ofs
 + *   attachment stuff
 + *   anim stuff
 + * to free:
 + *   call again with ""
 + *   remove the ent
 + */
 +void CL_WeaponEntity_SetModel(entity this, string name)
 +{
 +      if (name == "")
 +      {
 +              this.model = "";
 +              if (this.weaponchild) remove(this.weaponchild);
 +              this.weaponchild = NULL;
 +              this.movedir = '0 0 0';
 +              this.spawnorigin = '0 0 0';
 +              this.oldorigin = '0 0 0';
 +              this.anim_fire1  = '0 1 0.01';
 +              this.anim_fire2  = '0 1 0.01';
 +              this.anim_idle   = '0 1 0.01';
 +              this.anim_reload = '0 1 0.01';
 +      }
 +      else
 +      {
 +              // if there is a child entity, hide it until we're sure we use it
 +              if (this.weaponchild) this.weaponchild.model = "";
 +              _setmodel(this, W_Model(strcat("v_", name, ".md3")));
 +              int v_shot_idx;  // used later
 +              (v_shot_idx = gettagindex(this, "shot")) || (v_shot_idx = gettagindex(this, "tag_shot"));
 +
 +              _setmodel(this, W_Model(strcat("h_", name, ".iqm")));
 +              // preset some defaults that work great for renamed zym files (which don't need an animinfo)
 +              this.anim_fire1  = animfixfps(this, '0 1 0.01', '0 0 0');
 +              this.anim_fire2  = animfixfps(this, '1 1 0.01', '0 0 0');
 +              this.anim_idle   = animfixfps(this, '2 1 0.01', '0 0 0');
 +              this.anim_reload = animfixfps(this, '3 1 0.01', '0 0 0');
 +
 +              // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
 +              // if we don't, this is a "real" animated model
 +              string t;
 +              if ((t = "weapon", gettagindex(this, t)) || (t = "tag_weapon", gettagindex(this, t)))
 +              {
 +                      if (!this.weaponchild)
 +                      {
 +                              this.weaponchild = new(weaponchild);
 +#ifdef CSQC
 +                              this.weaponchild.drawmask = MASK_NORMAL;
 +                              this.weaponchild.renderflags |= RF_VIEWMODEL;
 +#endif
 +                      }
 +                      _setmodel(this.weaponchild, W_Model(strcat("v_", name, ".md3")));
 +                      setattachment(this.weaponchild, this, t);
 +              }
 +              else
 +              {
 +                      if (this.weaponchild) remove(this.weaponchild);
 +                      this.weaponchild = NULL;
 +              }
 +
 +              setorigin(this, '0 0 0');
 +              this.angles = '0 0 0';
 +              this.frame = 0;
 +#ifdef SVQC
 +              this.viewmodelforclient = NULL;
 +#else
 +              this.renderflags &= ~RF_VIEWMODEL;
 +#endif
 +              if (v_shot_idx)  // v_ model attached to invisible h_ model
 +              {
 +                      this.movedir = gettaginfo(this.weaponchild, v_shot_idx);
 +              }
 +              else
 +              {
 +                      int idx;
 +                      if ((idx = gettagindex(this, "shot")) || (idx = gettagindex(this, "tag_shot")))
 +                      {
 +                              this.movedir = gettaginfo(this, idx);
 +                      }
 +                      else
 +                      {
 +                              LOG_WARNINGF("weapon model %s does not support the 'shot' tag, will display shots TOTALLY wrong\n",
 +                                      this.model);
 +                              this.movedir = '0 0 0';
 +                      }
 +              }
 +              {
 +                      int idx = 0;
 +                      // v_ model attached to invisible h_ model
 +                      if (this.weaponchild
 +                          && ((idx = gettagindex(this.weaponchild, "shell")) || (idx = gettagindex(this.weaponchild, "tag_shell"))))
 +                      {
 +                              this.spawnorigin = gettaginfo(this.weaponchild, idx);
 +                      }
 +                      else if ((idx = gettagindex(this, "shell")) || (idx = gettagindex(this, "tag_shell")))
 +                      {
 +                              this.spawnorigin = gettaginfo(this, idx);
 +                      }
 +                      else
 +                      {
 +                              LOG_WARNINGF("weapon model %s does not support the 'shell' tag, will display casings wrong\n",
 +                                      this.model);
 +                              this.spawnorigin = this.movedir;
 +                      }
 +              }
 +              if (v_shot_idx)
 +              {
 +                      this.oldorigin = '0 0 0';  // use regular attachment
 +              }
 +              else
 +              {
 +                      int idx;
 +                      if (this.weaponchild)
 +                              (idx = gettagindex(this, "weapon")) || (idx = gettagindex(this, "tag_weapon"));
 +                      else
 +                              (idx = gettagindex(this, "handle")) || (idx = gettagindex(this, "tag_handle"));
 +                      if (idx)
 +                      {
 +                              this.oldorigin = this.movedir - gettaginfo(this, idx);
 +                      }
 +                      else
 +                      {
 +                              LOG_WARNINGF(
 +                                      "weapon model %s does not support the 'handle' tag "
 +                                      "and neither does the v_ model support the 'shot' tag, "
 +                                      "will display muzzle flashes TOTALLY wrong\n",
 +                                      this.model);
 +                              this.oldorigin = '0 0 0';  // there is no way to recover from this
 +                      }
 +              }
 +
 +#ifdef SVQC
 +              this.viewmodelforclient = this.owner;
 +#else
 +              this.renderflags |= RF_VIEWMODEL;
 +#endif
 +      }
 +
 +      this.view_ofs = '0 0 0';
 +
 +      if (this.movedir.x >= 0)
 +      {
 +#ifdef SVQC
 +              int algn = this.owner.cvar_cl_gunalign;
 +#else
 +              int algn = autocvar_cl_gunalign;
 +#endif
 +              vector v = this.movedir;
 +              this.movedir = shotorg_adjust(v, false, false, algn);
 +              this.view_ofs = shotorg_adjust(v, false, true, algn) - v;
 +      }
 +      int compressed_shotorg = compressShotOrigin(this.movedir);
 +      // make them match perfectly
 +#ifdef SVQC
 +      this.movedir = decompressShotOrigin(this.owner.stat_shotorg = compressed_shotorg);
 +#else
 +      this.movedir = decompressShotOrigin(compressed_shotorg);
 +#endif
 +
 +      this.spawnorigin += this.view_ofs;  // offset the casings origin by the same amount
 +
 +      // check if an instant weapon switch occurred
 +      setorigin(this, this.view_ofs);
 +      // reset animstate now
 +      this.wframe = WFRAME_IDLE;
 +      setanim(this, this.anim_idle, true, false, true);
 +}
 +#endif
 +
 +#ifndef MENUQC
 +
 +REGISTER_NET_TEMP(wframe)
 +#ifdef CSQC
 +NET_HANDLE(wframe, bool isNew)
 +{
 +      vector a;
 +      a.x = ReadCoord();
 +    a.y = ReadCoord();
 +    a.z = ReadCoord();
 +      bool restartanim = ReadByte();
 +      anim_set(viewmodel, a, !restartanim, restartanim, restartanim);
 +      viewmodel.state = ReadByte();
 +      viewmodel.alpha = ReadByte() / 255;
 +      return true;
 +}
 +#endif
 +
 +#ifdef SVQC
 +void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim)
 +{
 +      if (!IS_REAL_CLIENT(actor)) return;
 +      int channel = MSG_ONE;
 +      msg_entity = actor;
 +      WriteHeader(channel, wframe);
 +      WriteCoord(channel, a.x);
 +      WriteCoord(channel, a.y);
 +      WriteCoord(channel, a.z);
 +      WriteByte(channel, restartanim);
 +      WriteByte(channel, weaponentity.state);
 +      WriteByte(channel, weaponentity.alpha * 255);
 +}
 +#endif
 +
 +REGISTER_NET_TEMP(wglow)
 +#ifdef CSQC
 +NET_HANDLE(wglow, bool isNew)
 +{
 +      vector g = '0 0 0';
 +      g.x = ReadCoord();
 +      g.y = ReadCoord();
 +      g.z = ReadCoord();
 +      viewmodel.glowmod = g;
 +      return true;
 +}
 +#endif
 +
 +#ifdef SVQC
 +void wglow_send(entity actor, vector g)
 +{
 +      if (!IS_REAL_CLIENT(actor)) return;
 +      int channel = MSG_ONE;
 +      msg_entity = actor;
 +      WriteHeader(channel, wglow);
 +      WriteCoord(channel, g.x);
 +      WriteCoord(channel, g.y);
 +      WriteCoord(channel, g.z);
 +}
 +#endif
 +
 +#endif
 +
  #endif
index 76d536b4a604719db1bd665bf2be92cc46f4b38d,eb7a48f7ff6a68c2c41a1c75adc105c8ee1037c2..47568b31a072fc94127d679fc6219aa910e1c88d
@@@ -2,15 -2,12 +2,12 @@@
  #define WEAPONS_ALL_H
  
  #include "../command/all.qh"
+ #include "../stats.qh"
  #include "config.qh"
  
  // weapon sets
  typedef vector WepSet;
- #define WEPSET(id) WepSet_FromWeapon(WEP_##id.m_id)
- WepSet WepSet_FromWeapon(int a);
  #ifdef SVQC
- void WepSet_AddStat();
- void WepSet_AddStat_InMap();
  void WriteWepSet(float dest, WepSet w);
  #endif
  
@@@ -36,9 -33,17 +33,17 @@@ WepSet ReadWepSet()
  REGISTRY(Weapons, 72) // Increase as needed. Can be up to 72.
  #define Weapons_from(i) _Weapons_from(i, WEP_Null)
  #define get_weaponinfo(i) Weapons_from(i)
- REGISTER_REGISTRY(RegisterWeapons)
+ REGISTER_REGISTRY(Weapons)
  STATIC_INIT(WeaponPickup) { FOREACH(Weapons, true, LAMBDA(it.m_pickup = NEW(WeaponPickup, it))); }
  
+ .WepSet m_wepset;
+ #define WEPSET(id) (WEP_##id.m_wepset)
+ #define WepSet_FromWeapon(i) (Weapons_from(i).m_wepset)
+ WepSet _WepSet_FromWeapon(int i);
+ STATIC_INIT(WepSets)
+ {
+     FOREACH(Weapons, true, LAMBDA(it.m_wepset = _WepSet_FromWeapon(it.m_id)));
+ }
  
  GENERIC_COMMAND(dumpweapons, "Dump all weapons into weapons_dump.txt") // WEAPONTODO: make this work with other progs than just server
  {
  
  #define REGISTER_WEAPON(id, inst) \
      /* WepSet WEPSET_##id; */ \
-     REGISTER(RegisterWeapons, WEP, Weapons, id, m_id, inst)
+     REGISTER(Weapons, WEP, id, m_id, inst)
  
  // create cvars for weapon settings
  #define WEP_ADD_CVAR_NONE(wepname,name) [[last]] float autocvar_g_balance_##wepname##_##name;
@@@ -146,7 -151,7 +151,7 @@@ STATIC_INIT(register_weapons_done
  {
      FOREACH(Weapons, true, LAMBDA(
          it.m_id = i;
-         WepSet set = WepSet_FromWeapon(it.m_id);
+         WepSet set = it.m_wepset;
          WEPSET_ALL |= set;
          if ((it.spawnflags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
          it.weapon = it.m_id;
      weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
  }
  
- .int switchweapon; // weapon requested to switch to
- .int switchingweapon; // weapon currently being switched to (is copied from switchweapon once switch is possible)
 +#ifndef MENUQC
 +
 +.entity weaponchild;
 +.entity exteriorweaponentity;
 +.vector weaponentity_glowmod;
 +
 +//.int weapon; // current weapon
++#ifdef SVQC
++.int switchweapon = _STAT(SWITCHWEAPON);
++.int switchingweapon = _STAT(SWITCHINGWEAPON);
++#endif
 +.string weaponname; // name of .weapon
 +
 +.vector spawnorigin; // for casings
 +
 +// weapon animation vectors:
 +.vector anim_fire1;
 +.vector anim_fire2;
 +.vector anim_idle;
 +.vector anim_reload;
 +
 +// static frame globals
 +
 +ENUMCLASS(WFRAME)
 +CASE(WFRAME, DONTCHANGE)
 +CASE(WFRAME, FIRE1)
 +CASE(WFRAME, FIRE2)
 +CASE(WFRAME, IDLE)
 +CASE(WFRAME, RELOAD)
 +ENUMCLASS_END(WFRAME)
 +
 +.WFRAME wframe;
 +
 +vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn);
 +void CL_WeaponEntity_SetModel(entity this, string name);
 +#endif
 +
  #endif
index 2a92f955b50fc1cd16beb89dbe64f50de2ec3c2f,3016b501f8941741dbba3ca8b1e97d5b7caa3fab..71e121f81201ea0b39504c46a63ed72290b0ddfd
@@@ -1,6 -1,7 +1,7 @@@
  #ifndef WEAPON_H
  #define WEAPON_H
  #include "../items/item/pickup.qh"
+ #include "../stats.qh"
  
  const int MAX_WEAPONSLOTS = 2;
  .entity weaponentities[MAX_WEAPONSLOTS];
@@@ -17,18 -18,15 +18,27 @@@ int weaponslot(.entity weaponentity
        return 0;
  }
  
 +// weapon states (actor.(weaponentity).state)
 +/** no weapon selected */
 +const int WS_CLEAR  = 0;
 +/** raise frame */
 +const int WS_RAISE  = 1;
 +/** deselecting frame */
 +const int WS_DROP   = 2;
 +/** fire state */
 +const int WS_INUSE  = 3;
 +/** idle frame */
 +const int WS_READY  = 4;
 +
+ #ifdef SVQC
+ .int ammo_shells;
+ .int ammo_nails;
+ .int ammo_rockets;
+ .int ammo_cells;
+ .int ammo_plasma = _STAT(PLASMA);
+ .int ammo_fuel = _STAT(FUEL);
+ .int ammo_none;
+ #else
  .int ammo_shells;
  .int ammo_nails;
  .int ammo_rockets;
@@@ -36,6 -34,7 +46,7 @@@
  .int ammo_plasma;
  .int ammo_fuel;
  .int ammo_none;
+ #endif
  
  /** fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A" */
  CLASS(Weapon, Object)
index 1fa8131363ec872fb8ab33b7e62765dde77a6dcb,83d7e3fcbf23ec1ca254557df940f6a94a5fade7..7c9d64c01abed4d09077f4a29d2e0546dee57ac2
@@@ -92,7 -92,7 +92,7 @@@ ARC_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP
  .float beam_heat; // (beam) amount of heat produced
  .float arc_overheat; // (dropped arc/player) time during which it's too hot
  .float arc_cooldown; // (dropped arc/player) cooling speed
- .float arc_heat_percent; // (player) arc heat in [0,1] (stat)
+ .float arc_heat_percent = _STAT(ARC_HEAT);
  .float arc_smoke_sound;
  #endif
  #ifdef CSQC
@@@ -670,7 -670,7 +670,7 @@@ void Arc_Smoke(
                                                weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime, w_ready);
                                        else
                                        #endif
 -                                              weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
 +                                              weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(arc, beam_animtime), w_ready);
                                }
  
                                if((!actor.arc_beam) || wasfreed(actor.arc_beam))
@@@ -857,7 -857,7 +857,7 @@@ void Draw_ArcBeam(entity this
  
        if(!self.beam_usevieworigin)
        {
-               InterpolateOrigin_Do();
+               InterpolateOrigin_Do(self);
        }
  
        // origin = beam starting origin
@@@ -1208,7 -1208,7 +1208,7 @@@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool is
                // self.iflags = IFLAG_ORIGIN | IFLAG_ANGLES | IFLAG_V_ANGLE; // why doesn't this work?
                self.iflags = IFLAG_ORIGIN;
  
-               InterpolateOrigin_Undo();
+               InterpolateOrigin_Undo(self);
        }
  
        if(sf & ARC_SF_START) // starting location
                else
                {
                        // use player origin so that third person display still works
-                       self.origin = getplayerorigin(player_localnum) + ('0 0 1' * getstati(STAT_VIEWHEIGHT));
+                       self.origin = entcs_receiver(player_localnum).origin + ('0 0 1' * getstati(STAT_VIEWHEIGHT));
                }
        }
  
  
        if(!self.beam_usevieworigin)
        {
-               InterpolateOrigin_Note();
+               InterpolateOrigin_Note(this);
        }
        return true;
  }
diff --combined qcsrc/lib/_all.inc
index a752898b43edbf86a7bc7816e06087f1bdcc3f9c,24d2df747cf1c3dd649189e8b4a77382532b9b7b..9f7004c345ae8ca98c05a83434112b17fab2360e
@@@ -28,6 -28,7 +28,7 @@@
  #include "warpzone/mathlib.qc"
  
  #include "accumulate.qh"
+ #include "arraylist.qh"
  #include "bits.qh"
  #include "bool.qh"
  #include "color.qh"
@@@ -35,7 -36,6 +36,7 @@@
  #include "cvar.qh"
  #include "defer.qh"
  #include "draw.qh"
 +#include "enumclass.qh"
  #include "file.qh"
  #include "functional.qh"
  #include "i18n.qh"
@@@ -52,7 -52,6 +53,6 @@@
  #include "noise.qc"
  #include "oo.qh"
  #include "p2mathlib.qc"
- #include "player.qh"
  #include "progname.qh"
  #include "random.qc"
  #include "registry.qh"
@@@ -63,6 -62,7 +63,7 @@@
  #include "sort.qh"
  #include "spawnfunc.qh"
  #include "static.qh"
+ #include "stats.qh"
  #include "string.qh"
  #include "struct.qh"
  #include "test.qc"
diff --combined qcsrc/lib/vector.qh
index 9813f2fa92d54b9ef2ccb9c1465e2d1e4c0eef3b,d6eee7aceae92104220446b7ee56659daa79c9b0..776bf6eedb888c8fd0df39b4d37b3ca0321894ca
@@@ -1,6 -1,31 +1,31 @@@
  #ifndef VECTOR_H
  #define VECTOR_H
  
+ noref vector _vlen2;
+ #define vlen2(v) \
+       (_vlen2 = (v), \
+         _vlen2.x * _vlen2.x \
+       + _vlen2.y * _vlen2.y \
+       + _vlen2.z * _vlen2.z)
+ noref float _vdist_f;
+ /** Vector distance comparison, avoids sqrt() */
+ #define vdist(v, cmp, f) (vlen2(v) cmp (_vdist_f = (f), _vdist_f * _vdist_f))
+ /*
+ #define vdist(v, cmp, f) (vlen(v) cmp (f))
+ */
+ #define cross(a, b) ((a) >< (b))
+ /*
+ vector cross(vector a, vector b)
+ {
+       return
+               '1 0 0' * (a.y * b.z - a.z * b.y)
+       +       '0 1 0' * (a.z * b.x - a.x * b.z)
+       +       '0 0 1' * (a.x * b.y - a.y * b.x);
+ }
+ */
  const vector eX = '1 0 0';
  const vector eY = '0 1 0';
  const vector eZ = '0 0 1';
@@@ -15,11 -40,6 +40,6 @@@ vector randompos(vector m1, vector m2
        return v;
  }
  
- float vlen2d(vector v)
- {
-       return sqrt(v.x * v.x + v.y * v.y);
- }
  float vlen_maxnorm2d(vector v)
  {
        return max(v.x, v.y, -v.x, -v.y);
@@@ -47,31 -67,12 +67,22 @@@ float boxesoverlap(vector m1, vector m2
  /** requires the same as boxesoverlap, but is a stronger condition */
  float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) { return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z; }
  
 +#define PITCH(v) (v).x
 +#define YAW(v) (v).y
 +#define ROLL(v) (v).z
 +
 +#define MAKEVECTORS(f, angles, forward, right, up) do { \
 +      f(angles); \
 +      forward = v_forward; \
 +      right = v_right; \
 +      up = v_up; \
 +} while (0)
  
- vector vec2(vector v)
- {
-       v.z = 0;
-       return v;
- }
+ noref vector _vec2;
+ #define vec2(v) (_vec2 = (v), _vec2.z = 0, _vec2)
  
- vector vec3(float x, float y, float z)
- {
-       vector v;
-       v.x = x;
-       v.y = y;
-       v.z = z;
-       return v;
- }
+ noref vector _vec3;
+ #define vec3(x, y, z) (_vec3_x = (x), _vec3_y = (y), _vec3_z = (z), _vec3)
  
  vector rotate(vector v, float a)
  {
        return r;
  }
  
- vector yinvert(vector v)
- {
-       v.y = 1 - v.y;
-       return v;
- }
+ noref vector _yinvert;
+ #define yinvert(v) (_yinvert = (v), _yinvert.y = 1 - _yinvert.y, _yinvert)
  
  #ifndef MENUQC
        vector get_corner_position(entity box, int corner)
index 9cd8da807ee9905600faba3fd31ef394c717bf19,2731c82445d3d82bffabb5b0017ba2069fd6f2f3..0cc6a0b65d745e6a0b784ecbf3fa362714df8a5e
@@@ -3,7 -3,6 +3,6 @@@
  #include "anticheat.qh"
  #include "cl_impulse.qh"
  #include "cl_player.qh"
- #include "ent_cs.qh"
  #include "ipban.qh"
  #include "miscfunctions.qh"
  #include "portals.qh"
@@@ -23,6 -22,7 +22,7 @@@
  #include "bot/bot.qh"
  #include "bot/navigation.qh"
  
+ #include "../common/ent_cs.qh"
  #include "../common/vehicles/all.qh"
  #include "../common/triggers/teleporters.qh"
  
@@@ -175,7 -175,6 +175,6 @@@ void setplayermodel(entity e, string mo
        precache_model(modelname);
        _setmodel(e, modelname);
        player_setupanimsformodel();
-       UpdatePlayerSounds();
  }
  
  /*
@@@ -319,6 -318,15 +318,15 @@@ void PutObserverInServer(
        self.event_damage = func_null;
  }
  
+ int player_getspecies(entity this)
+ {
+       get_model_parameters(this.model, this.skin);
+       int s = get_model_parameters_species;
+       get_model_parameters(string_null, 0);
+       if (s < 0) return SPECIES_HUMAN;
+       return s;
+ }
  .float model_randomizer;
  void FixPlayermodel(entity player)
  {
  
        if(chmdl || oldskin != player.skin) // model or skin has changed
        {
-               player.species = player_getspecies(); // update species
-               UpdatePlayerSounds(); // update skin sounds
+               player.species = player_getspecies(player); // update species
        }
  
        if(!teamplay)
@@@ -563,8 -570,6 +570,6 @@@ void PutClientInServer(
                this.bot_attack = true;
                this.monster_attack = true;
  
-               this.spider_slowness = 0;
                this.BUTTON_ATCK = this.BUTTON_JUMP = this.BUTTON_ATCK2 = false;
  
                if (this.killcount == FRAGS_SPECTATOR) {
@@@ -1171,7 -1176,7 +1176,7 @@@ void ClientConnect (
        else
                stuffcmd(self, "set _teams_available 0\n");
  
-       attach_entcs(self);
+       entcs_attach(self);
  
        bot_relinkplayerlist();
  
                        Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
                }
  
-               if(autocvar_g_bugrigs || (g_weaponarena_weapons == WEPSET(TUBA)))
+               if(g_weaponarena_weapons == WEPSET(TUBA))
                        stuffcmd(self, "cl_cmd settemp chase_active 1\n");
        }
  
        self.model_randomizer = random();
  
        if(IS_REAL_CLIENT(self))
-               sv_notice_join();
+               sv_notice_join(self);
  
        for (entity e = world; (e = findfloat(e, init_for_player_needed, 1)); ) {
                WITH(entity, self, e, e.init_for_player(this));
@@@ -1257,7 -1262,7 +1262,7 @@@ void ClientDisconnect (
  
        bot_clientdisconnect();
  
-       detach_entcs(self);
+       entcs_detach(self);
  
        if(autocvar_sv_eventlog)
                GameLogEcho(strcat(":part:", ftos(self.playerid)));
        if(self.weaponorder_byimpulse)
                strunzone(self.weaponorder_byimpulse);
  
-       ClearPlayerSounds();
        if(self.personal)
                remove(self.personal);
  
@@@ -1687,7 -1690,6 +1690,7 @@@ void SpectateCopy(entity spectatee
        self.switchweapon = spectatee.switchweapon;
        self.switchingweapon = spectatee.switchingweapon;
        self.weapon = spectatee.weapon;
 +      self.weapon_nextthink = spectatee.weapon_nextthink;
        self.vortex_charge = spectatee.vortex_charge;
        self.vortex_chargepool_ammo = spectatee.vortex_chargepool_ammo;
        self.hagar_load = spectatee.hagar_load;
@@@ -2145,8 -2147,6 +2148,8 @@@ void PlayerUseKey(
  }
  
  
 +void wglow_send(entity actor, vector g);
 +
  /*
  =============
  PlayerPreThink
@@@ -2322,28 -2322,22 +2325,28 @@@ void PlayerPreThink (
  
                if(frametime)
                {
 -                      if(self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge))
 +                      vector g;
 +                      if (IS_SPEC(self))
 +                      {
 +                              g = self.enemy.weaponentity_glowmod;
 +                      }
 +                      else if(self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge))
                        {
 -                              self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
 -                              self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
 -                              self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
 +                              g.x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
 +                              g.y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
 +                              g.z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
  
                                if(self.vortex_charge > WEP_CVAR(vortex, charge_animlimit))
                                {
 -                                      self.weaponentity_glowmod_x = self.weaponentity_glowmod.x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
 -                                      self.weaponentity_glowmod_y = self.weaponentity_glowmod.y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
 -                                      self.weaponentity_glowmod_z = self.weaponentity_glowmod.z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
 +                                      g.x += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
 +                                      g.y += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
 +                                      g.z += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
                                }
                        }
                        else
 -                              self.weaponentity_glowmod = colormapPaletteColor(self.clientcolors & 0x0F, true) * 2;
 -
 +                              g = colormapPaletteColor(self.clientcolors & 0x0F, true) * 2;
 +                      if (g != self.weaponentity_glowmod)
 +                              wglow_send(self, self.weaponentity_glowmod = g);
                        player_powerups();
                }
  
                        if (!self.crouch)
                        {
                                self.crouch = true;
-                               self.view_ofs = self.stat_pl_crouch_view_ofs;
-                               setsize (self, self.stat_pl_crouch_min, self.stat_pl_crouch_max);
+                               self.view_ofs = STAT(PL_CROUCH_VIEW_OFS, self);
+                               setsize (self, STAT(PL_CROUCH_MIN, self), STAT(PL_CROUCH_MAX, self));
                                // setanim(self, self.anim_duck, false, true, true); // this anim is BROKEN anyway
                        }
                }
                {
                        if (self.crouch)
                        {
-                               tracebox(self.origin, self.stat_pl_min, self.stat_pl_max, self.origin, false, self);
+                               tracebox(self.origin, STAT(PL_MIN, self), STAT(PL_MAX, self), self.origin, false, self);
                                if (!trace_startsolid)
                                {
                                        self.crouch = false;
-                                       self.view_ofs = self.stat_pl_view_ofs;
-                                       setsize (self, self.stat_pl_min, self.stat_pl_max);
+                                       self.view_ofs = STAT(PL_VIEW_OFS, self);
+                                       setsize (self, STAT(PL_MIN, self), STAT(PL_MAX, self));
                                }
                        }
                }
index bacb6bcb9e4c5c95cb044333a4056bcbc8e5d22f,a9a5d03cbe2e93965f73b25e603cfbc31a5f5288..22ef4bdffa5d2283d8170677850ee443ad731bff
@@@ -9,7 -9,6 +9,7 @@@
  #include "teamplay.qh"
  #include "weapons/throwing.qh"
  #include "command/common.qh"
 +#include "../common/anim.qh"
  #include "../common/animdecide.qh"
  #include "../common/csqcmodel_settings.qh"
  #include "../common/deathtypes/all.qh"
@@@ -124,17 -123,6 +124,6 @@@ void CopyBody(float keepvelocity
        setself(this);
  }
  
- float player_getspecies()
- {SELFPARAM();
-       float s;
-       get_model_parameters(self.model, self.skin);
-       s = get_model_parameters_species;
-       get_model_parameters(string_null, 0);
-       if(s < 0)
-               return SPECIES_HUMAN;
-       return s;
- }
  void player_setupanimsformodel()
  {SELFPARAM();
        // load animation info
@@@ -166,6 -154,16 +155,6 @@@ void player_anim (
                animbits |= ANIMSTATE_DUCK;
        animdecide_setstate(self, animbits, false);
        animdecide_setimplicitstate(self, (self.flags & FL_ONGROUND));
 -
 -      .entity weaponentity = weaponentities[0]; // TODO: unhardcode
 -      {
 -              if (self.(weaponentity))
 -              {
 -                      updateanim(self.(weaponentity));
 -                      if (!self.(weaponentity).animstate_override)
 -                              setanim(self.(weaponentity), self.(weaponentity).anim_idle, true, false, false);
 -              }
 -      }
  }
  
  void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
@@@ -480,7 -478,7 +469,7 @@@ void PlayerDamage (entity inflictor, en
                        PlayerScore_Add(self, SP_DMGTAKEN, realdmg);
                }
        }
-       
        bool abot = (IS_BOT_CLIENT(attacker));
        bool vbot = (IS_BOT_CLIENT(self));
  
        }
  }
  
- float Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol)
- // message "": do not say, just test flood control
- // return value:
- //   1 = accept
- //   0 = reject
- //  -1 = fake accept
+ void MoveToTeam(entity client, int team_colour, int type)
+ {
+       int lockteams_backup = lockteams;  // backup any team lock
+       lockteams = 0;  // disable locked teams
+       TeamchangeFrags(client);  // move the players frags
+       SetPlayerColors(client, team_colour - 1);  // set the players colour
+       Damage(client, client, client, 100000, DEATH_AUTOTEAMCHANGE.m_id, client.origin, '0 0 0');  // kill the player
+       lockteams = lockteams_backup;  // restore the team lock
+       LogTeamchange(client.playerid, client.team, type);
+ }
+ /**
+  * message "": do not say, just test flood control
+  * return value:
+  *   1 = accept
+  *   0 = reject
+  *  -1 = fake accept
+  */
+ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floodcontrol)
  {
        string msgstr, colorstr, cmsgstr, namestr, fullmsgstr, sourcemsgstr, fullcmsgstr, sourcecmsgstr, colorprefix;
        float flood;
  
        return ret;
  }
- float GetVoiceMessageVoiceType(string type)
- {
-       if(type == "taunt")
-               return VOICETYPE_TAUNT;
-       if(type == "teamshoot")
-               return VOICETYPE_LASTATTACKER;
-       return VOICETYPE_TEAMRADIO;
- }
- .string GetVoiceMessageSampleField(string type)
- {
-       GetPlayerSoundSampleField_notFound = 0;
-       switch(type)
-       {
- #define _VOICEMSG(m) case #m: return playersound_##m;
-               ALLVOICEMSGS
- #undef _VOICEMSG
-       }
-       GetPlayerSoundSampleField_notFound = 1;
-       return playersound_taunt;
- }
- .string GetPlayerSoundSampleField(string type)
- {
-       GetPlayerSoundSampleField_notFound = 0;
-       switch(type)
-       {
- #define _VOICEMSG(m) case #m: return playersound_##m;
-               ALLPLAYERSOUNDS
- #undef _VOICEMSG
-       }
-       GetPlayerSoundSampleField_notFound = 1;
-       return playersound_taunt;
- }
- void PrecacheGlobalSound(string samplestring)
- {
-       float n, i;
-       tokenize_console(samplestring);
-       n = stof(argv(1));
-       if(n > 0)
-       {
-               for(i = 1; i <= n; ++i)
-                       precache_sound(strcat(argv(0), ftos(i), ".wav"));
-       }
-       else
-       {
-               precache_sound(strcat(argv(0), ".wav"));
-       }
- }
- void PrecachePlayerSounds(string f)
- {
-       int fh = fopen(f, FILE_READ);
-       if (fh < 0)
-               return;
-       for (string s; (s = fgets(fh)); )
-       {
-               int n = tokenize_console(s);
-               if (n != 3)
-               {
-                       if (n != 0) LOG_TRACEF("Invalid sound info line: %s\n", s);
-                       continue;
-               }
-               PrecacheGlobalSound(strcat(argv(1), " ", argv(2)));
-       }
-       fclose(fh);
-       if (!allvoicesamples)
-       {
- #define _VOICEMSG(m) allvoicesamples = strcat(allvoicesamples, " ", #m);
-               ALLVOICEMSGS
- #undef _VOICEMSG
-               allvoicesamples = strzone(substring(allvoicesamples, 1, strlen(allvoicesamples) - 1));
-       }
- }
- void ClearPlayerSounds()
- {SELFPARAM();
- #define _VOICEMSG(m) if(self.playersound_##m) { strunzone(self.playersound_##m); self.playersound_##m = string_null; }
-       ALLPLAYERSOUNDS
-       ALLVOICEMSGS
- #undef _VOICEMSG
- }
- float LoadPlayerSounds(string f, float first)
- {SELFPARAM();
-       float fh;
-       string s;
-       var .string field;
-       fh = fopen(f, FILE_READ);
-       if(fh < 0)
-       {
-               LOG_TRACE("Player sound file not found: ", f, "\n");
-               return 0;
-       }
-       while((s = fgets(fh)))
-       {
-               if(tokenize_console(s) != 3)
-                       continue;
-               field = GetPlayerSoundSampleField(argv(0));
-               if(GetPlayerSoundSampleField_notFound)
-                       field = GetVoiceMessageSampleField(argv(0));
-               if(GetPlayerSoundSampleField_notFound)
-                       continue;
-               if (self.(field))
-                       strunzone(self.(field));
-               self.(field) = strzone(strcat(argv(1), " ", argv(2)));
-       }
-       fclose(fh);
-       return 1;
- }
- void UpdatePlayerSounds()
- {SELFPARAM();
-       if(self.modelindex == self.modelindex_for_playersound)
-       if(self.skin == self.skin_for_playersound)
-               return;
-       self.modelindex_for_playersound = self.modelindex;
-       self.skin_for_playersound = self.skin;
-       ClearPlayerSounds();
-       LoadPlayerSounds("sound/player/default.sounds", 1);
-       if(!autocvar_g_debug_defaultsounds)
-               if(!LoadPlayerSounds(get_model_datafilename(self.model, self.skin, "sounds"), 0))
-                       LoadPlayerSounds(get_model_datafilename(self.model, 0, "sounds"), 0);
- }
- void FakeGlobalSound(string sample, float chan, float voicetype)
- {SELFPARAM();
-       float n;
-       float tauntrand;
-       if(sample == "")
-               return;
-       tokenize_console(sample);
-       n = stof(argv(1));
-       if(n > 0)
-               sample = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
-       else
-               sample = strcat(argv(0), ".wav"); // randomization
-       switch(voicetype)
-       {
-               case VOICETYPE_LASTATTACKER_ONLY:
-                       break;
-               case VOICETYPE_LASTATTACKER:
-                       if(self.pusher)
-                       {
-                               msg_entity = self;
-                               if(IS_REAL_CLIENT(msg_entity))
-                                       soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTEN_NONE);
-                       }
-                       break;
-               case VOICETYPE_TEAMRADIO:
-                       msg_entity = self;
-                       if(msg_entity.cvar_cl_voice_directional == 1)
-                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_MIN);
-                       else
-                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
-                       break;
-               case VOICETYPE_AUTOTAUNT:
-                       if(!sv_autotaunt)
-                               break;
-                       if(!sv_taunt)
-                               break;
-                       if(autocvar_sv_gentle)
-                               break;
-                       tauntrand = random();
-                       msg_entity = self;
-                       if (tauntrand < msg_entity.cvar_cl_autotaunt)
-                       {
-                               if (msg_entity.cvar_cl_voice_directional >= 1)
-                                       soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTEN_MAX));
-                               else
-                                       soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
-                       }
-                       break;
-               case VOICETYPE_TAUNT:
-                       if(IS_PLAYER(self))
-                               if(self.deadflag == DEAD_NO)
-                                       animdecide_setaction(self, ANIMACTION_TAUNT, true);
-                       if(!sv_taunt)
-                               break;
-                       if(autocvar_sv_gentle)
-                               break;
-                       msg_entity = self;
-                       if (msg_entity.cvar_cl_voice_directional >= 1)
-                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTEN_MAX));
-                       else
-                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
-                       break;
-               case VOICETYPE_PLAYERSOUND:
-                       msg_entity = self;
-                       soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTEN_NORM);
-                       break;
-               default:
-                       backtrace("Invalid voice type!");
-                       break;
-       }
- }
- void GlobalSound(string sample, float chan, float voicetype)
- {SELFPARAM();
-       float n;
-       float tauntrand;
-       if(sample == "")
-               return;
-       tokenize_console(sample);
-       n = stof(argv(1));
-       if(n > 0)
-               sample = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
-       else
-               sample = strcat(argv(0), ".wav"); // randomization
-       switch(voicetype)
-       {
-               case VOICETYPE_LASTATTACKER_ONLY:
-                       if(self.pusher)
-                       {
-                               msg_entity = self.pusher;
-                               if(IS_REAL_CLIENT(msg_entity))
-                               {
-                                       if(msg_entity.cvar_cl_voice_directional == 1)
-                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_MIN);
-                                       else
-                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
-                               }
-                       }
-                       break;
-               case VOICETYPE_LASTATTACKER:
-                       if(self.pusher)
-                       {
-                               msg_entity = self.pusher;
-                               if(IS_REAL_CLIENT(msg_entity))
-                               {
-                                       if(msg_entity.cvar_cl_voice_directional == 1)
-                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_MIN);
-                                       else
-                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
-                               }
-                               msg_entity = self;
-                               if(IS_REAL_CLIENT(msg_entity))
-                                       soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTEN_NONE);
-                       }
-                       break;
-               case VOICETYPE_TEAMRADIO:
-                       FOR_EACH_REALCLIENT(msg_entity)
-                               if(!teamplay || msg_entity.team == self.team)
-                               {
-                                       if(msg_entity.cvar_cl_voice_directional == 1)
-                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_MIN);
-                                       else
-                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
-                               }
-                       break;
-               case VOICETYPE_AUTOTAUNT:
-                       if(!sv_autotaunt)
-                               break;
-                       if(!sv_taunt)
-                               break;
-                       if(autocvar_sv_gentle)
-                               break;
-                       tauntrand = random();
-                       FOR_EACH_REALCLIENT(msg_entity)
-                               if (tauntrand < msg_entity.cvar_cl_autotaunt)
-                               {
-                                       if (msg_entity.cvar_cl_voice_directional >= 1)
-                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTEN_MAX));
-                                       else
-                                               soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
-                               }
-                       break;
-               case VOICETYPE_TAUNT:
-                       if(IS_PLAYER(self))
-                               if(self.deadflag == DEAD_NO)
-                                       animdecide_setaction(self, ANIMACTION_TAUNT, true);
-                       if(!sv_taunt)
-                               break;
-                       if(autocvar_sv_gentle)
-                               break;
-                       FOR_EACH_REALCLIENT(msg_entity)
-                       {
-                               if (msg_entity.cvar_cl_voice_directional >= 1)
-                                       soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTEN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTEN_MAX));
-                               else
-                                       soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTEN_NONE);
-                       }
-                       break;
-               case VOICETYPE_PLAYERSOUND:
-                       _sound(self, chan, sample, VOL_BASE, ATTEN_NORM);
-                       break;
-               default:
-                       backtrace("Invalid voice type!");
-                       break;
-       }
- }
- void PlayerSound(.string samplefield, float chan, float voicetype)
- {SELFPARAM();
-       GlobalSound(self.(samplefield), chan, voicetype);
- }
- void VoiceMessage(string type, string msg)
- {SELFPARAM();
-       float voicetype, ownteam;
-       float flood;
-       var .string sample = GetVoiceMessageSampleField(type);
-       if(GetPlayerSoundSampleField_notFound)
-       {
-               sprint(self, strcat("Invalid voice. Use one of: ", allvoicesamples, "\n"));
-               return;
-       }
-       voicetype = GetVoiceMessageVoiceType(type);
-       ownteam = (voicetype == VOICETYPE_TEAMRADIO);
-       flood = Say(self, ownteam, world, msg, 1);
-       if (IS_SPEC(self) || IS_OBSERVER(self) || flood < 0)
-               FakeGlobalSound(self.(sample), CH_VOICE, voicetype);
-       else if (flood > 0)
-               GlobalSound(self.(sample), CH_VOICE, voicetype);
- }
- void MoveToTeam(entity client, float team_colour, float type)
- {
-       float lockteams_backup;
-       lockteams_backup = lockteams;  // backup any team lock
-       lockteams = 0;  // disable locked teams
-       TeamchangeFrags(client);  // move the players frags
-       SetPlayerColors(client, team_colour - 1);  // set the players colour
-       Damage(client, client, client, 100000, DEATH_AUTOTEAMCHANGE.m_id, client.origin, '0 0 0');  // kill the player
-       lockteams = lockteams_backup;  // restore the team lock
-       LogTeamchange(client.playerid, client.team, type);
- }
diff --combined qcsrc/server/defs.qh
index 0fc8381ace8e73b6c054df6fd60f156179101667,9c2dc4064097acbd97f5cc0ffb6260b3a89c57c4..a18dd3c43029e6d27c0c164fbc788d79738da5e7
@@@ -2,6 -2,7 +2,7 @@@
  #define SERVER_DEFS_H
  
  #include "../common/weapons/all.qh"
+ #include "../common/stats.qh"
  
  #define INDEPENDENT_ATTACK_FINISHED 1
  
@@@ -53,8 -54,6 +54,6 @@@ void UpdateFrags(entity player, float f
  
  float team1_score, team2_score, team3_score, team4_score;
  
- float maxclients;
  // flag set on worldspawn so that the code knows if it is dedicated or not
  float server_is_dedicated;
  
@@@ -76,9 -75,9 +75,9 @@@
  .float        pain_frame;                     //"
  .float  crouch;       // Crouching or not?
  
- .float        strength_finished;
- .float        invincible_finished;
- .float        superweapons_finished;
+ .float        strength_finished = _STAT(STRENGTH_FINISHED);
+ .float        invincible_finished = _STAT(INVINCIBLE_FINISHED);
+ .float        superweapons_finished = _STAT(SUPERWEAPONS_FINISHED);
  
  .float cnt; // used in too many places
  .float count;
  .float fade_time;
  .float fade_rate;
  
 -// weapon animation vectors:
 -.vector anim_fire1;
 -.vector anim_fire2;
 -.vector anim_idle;
 -.vector anim_reload;
 -
  void() player_setupanimsformodel;
 -void setanim(entity e, vector anim, float looping, float override, float restart);
  
  .string mdl;
  
@@@ -143,16 -149,33 +142,16 @@@ const float MAX_DAMAGEEXTRARADIUS = 16
  .entity item_pickupsound_ent;
  .entity item_model_ent;
  
 -// definitions for weaponsystem
 -// more WEAPONTODO: move these to their proper files
 -.entity exteriorweaponentity;
 -.vector weaponentity_glowmod;
 -
 -//.int weapon; // current weapon
 -.int switchweapon = _STAT(SWITCHWEAPON);
 -.int switchingweapon = _STAT(SWITCHINGWEAPON); // weapon currently being switched to (is copied from switchweapon once switch is possible)
 -.string weaponname; // name of .weapon
 -
  // WEAPONTODO
  .float autoswitch;
  float client_hasweapon(entity cl, float wpn, float andammo, float complain);
  void w_clear(Weapon thiswep, entity actor, .entity weaponentity, int fire);
  void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire);
  // VorteX: standalone think for weapons, so normal think on weaponentity can be reserved by weaponflashes (which needs update even player dies)
--.float weapon_nextthink;
++.float weapon_nextthink = _STAT(WEAPON_NEXTTHINK);
  .void(Weapon thiswep, entity actor, .entity weaponentity, int fire) weapon_think;
  
  
 -// weapon states (self.weaponentity.state)
 -const int WS_CLEAR                    = 0; // no weapon selected
 -const int WS_RAISE                    = 1; // raise frame
 -const int WS_DROP                             = 2; // deselecting frame
 -const int WS_INUSE                    = 3; // fire state
 -const int WS_READY                    = 4; // idle frame
 -
  // there is 2 weapon tics that can run in one server frame
  const int W_TICSPERFRAME = 2;
  
@@@ -189,6 -212,8 +188,6 @@@ float nJoinAllowed(entity ignore)
  float playerid_last;
  .float noalign;               // if set to 1, the item or spawnpoint won't be dropped to the floor
  
 -.vector spawnorigin;
 -
  .vector death_origin;
  .vector killer_origin;
  
@@@ -200,7 -225,7 +199,7 @@@ float default_weapon_alpha
  .float cvar_cl_clippedspectating;
  .float cvar_cl_autoscreenshot;
  .float cvar_cl_jetpack_jump;
- .float cvar_cl_movement_track_canjump;
+ .float cvar_cl_movement_track_canjump = _STAT(MOVEVARS_CL_TRACK_CANJUMP);
  .float cvar_cl_newusekeysupported;
  
  .string cvar_g_xonoticversion;
@@@ -229,7 -254,8 +228,8 @@@ void FixClientCvars(entity e)
  // WEAPONTODO: remove this
  WepSet weaponsInMap;
  
- .WepSet weaponsinmap;
+ #define weapons _STAT(WEAPONS)
+ #define weaponsinmap _STAT(WEAPONSINMAP)
  
  .float respawn_countdown; // next number to count
  
@@@ -276,75 -302,6 +276,6 @@@ float tracebox_hits_trigger_hurt(vecto
  
  float next_pingtime;
  
- // player sounds, voice messages
- // TODO implemented fall and falling
- #define ALLPLAYERSOUNDS \
-               _VOICEMSG(death) \
-               _VOICEMSG(drown) \
-               _VOICEMSG(fall) \
-               _VOICEMSG(falling) \
-               _VOICEMSG(gasp) \
-               _VOICEMSG(jump) \
-               _VOICEMSG(pain100) \
-               _VOICEMSG(pain25) \
-               _VOICEMSG(pain50) \
-               _VOICEMSG(pain75)
- #define ALLVOICEMSGS \
-               _VOICEMSG(attack) \
-               _VOICEMSG(attackinfive) \
-               _VOICEMSG(coverme) \
-               _VOICEMSG(defend) \
-               _VOICEMSG(freelance) \
-               _VOICEMSG(incoming) \
-               _VOICEMSG(meet) \
-               _VOICEMSG(needhelp) \
-               _VOICEMSG(seenflag) \
-               _VOICEMSG(taunt) \
-               _VOICEMSG(teamshoot)
- #define _VOICEMSG(m) .string playersound_##m;
- ALLPLAYERSOUNDS
- ALLVOICEMSGS
- #undef _VOICEMSG
- // reserved sound names for the future (some models lack sounds for them):
- //            _VOICEMSG(flagcarriertakingdamage) \
- //            _VOICEMSG(getflag) \
- // reserved sound names for the future (ALL models lack sounds for them):
- //            _VOICEMSG(affirmative) \
- //            _VOICEMSG(attacking) \
- //            _VOICEMSG(defending) \
- //            _VOICEMSG(roaming) \
- //            _VOICEMSG(onmyway) \
- //            _VOICEMSG(droppedflag) \
- //            _VOICEMSG(negative) \
- //            _VOICEMSG(seenenemy) \
- //      /**/
- string globalsound_fall;
- string globalsound_metalfall;
- string globalsound_step;
- string globalsound_metalstep;
- const float VOICETYPE_PLAYERSOUND = 10;
- const float VOICETYPE_TEAMRADIO = 11;
- const float VOICETYPE_LASTATTACKER = 12;
- const float VOICETYPE_LASTATTACKER_ONLY = 13;
- const float VOICETYPE_AUTOTAUNT = 14;
- const float VOICETYPE_TAUNT = 15;
- void PrecachePlayerSounds(string f);
- void PrecacheGlobalSound(string samplestring);
- void UpdatePlayerSounds();
- void ClearPlayerSounds();
- void PlayerSound(.string samplefield, float channel, float voicetype);
- void GlobalSound(string samplestring, float channel, float voicetype);
- void FakeGlobalSound(string samplestring, float channel, float voicetype);
- void VoiceMessage(string type, string message);
- float GetPlayerSoundSampleField_notFound;
- .string GetVoiceMessageSampleField(string type);
  // autotaunt system
  .float cvar_cl_autotaunt;
  .float cvar_cl_voice_directional;
@@@ -360,7 -317,7 +291,7 @@@ bool independent_players
  
  string clientstuff;
  .float phase;
- .int pressedkeys;
+ .int pressedkeys = _STAT(PRESSED_KEYS);
  
  .string fog;
  
@@@ -370,8 -327,8 +301,8 @@@ float cvar_purechanges_count
  
  float game_starttime; //point in time when the countdown to game start is over
  float round_starttime; //point in time when the countdown to round start is over
- .float stat_game_starttime;
- .float stat_round_starttime;
+ .float stat_game_starttime = _STAT(GAMESTARTTIME);
+ .float stat_round_starttime = _STAT(ROUNDSTARTTIME);
  
  void W_Porto_Remove (entity p);
  
  
  .string message2;
  
- .float stat_allow_oldvortexbeam;
+ .bool stat_allow_oldvortexbeam = _STAT(ALLOW_OLDVORTEXBEAM);
  
  // reset to 0 on weapon switch
  // may be useful to all weapons
@@@ -392,7 -349,7 +323,7 @@@ float g_nexball_meter_period
  void SUB_DontUseTargets();
  void SUB_UseTargets();
  
- .void() reset; // if set, an entity is reset using this
+ .void(entity this) reset; // if set, an entity is reset using this
  .void() reset2; // if set, an entity is reset using this (after calling ALL the reset functions for other entities)
  
  void ClientData_Touch(entity e);
@@@ -416,18 -373,18 +347,18 @@@ float servertime, serverprevtime, serve
  .float floodcontrol_voice;
  .float floodcontrol_voiceteam;
  
- .float stat_shotorg; // networked stat for trueaim HUD
+ .float stat_shotorg = _STAT(SHOTORG); // networked stat for trueaim HUD
  
  string matchid;
  
- .float last_pickup;
+ .float last_pickup = _STAT(LAST_PICKUP);
  
- .float hit_time;
- .float typehit_time;
+ .float hit_time = _STAT(HIT_TIME);
+ .float typehit_time = _STAT(TYPEHIT_TIME);
  
- .float damage_dealt_total;
+ .float damage_dealt_total = _STAT(DAMAGE_DEALT_TOTAL);
  
- .float stat_leadlimit;
+ .float stat_leadlimit = _STAT(LEADLIMIT);
  
  bool radar_showennemies;
  
@@@ -438,15 -395,15 +369,15 @@@ float client_cefc_accumulatortime
  
  .float weapon_load[Weapons_MAX];
  .int ammo_none; // used by the reloading system, must always be 0
- .float clip_load;
+ .float clip_load = _STAT(WEAPON_CLIPLOAD);
  .float old_clip_load;
- .float clip_size;
+ .float clip_size = _STAT(WEAPON_CLIPSIZE);
  
- .float minelayer_mines;
- .float vortex_charge;
+ .float minelayer_mines = _STAT(LAYED_MINES);
+ .float vortex_charge = _STAT(VORTEX_CHARGE);
  .float vortex_charge_rottime;
- .float vortex_chargepool_ammo;
- .float hagar_load;
+ .float vortex_chargepool_ammo = _STAT(VORTEX_CHARGEPOOL);
+ .float hagar_load = _STAT(HAGAR_LOAD);
  
  .int grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab
  
@@@ -486,8 -443,8 +417,8 @@@ const float ACTIVE_TOGGLE  = 3
  .float player_blocked;
  .float weapon_blocked; // weapon use disabled
  
- .float frozen; // for freeze attacks
- .float revive_progress;
+ .float frozen = _STAT(FROZEN); // for freeze attacks
+ .float revive_progress = _STAT(REVIVE_PROGRESS);
  .float revival_time; // time at which player was last revived
  .float revive_speed; // NOTE: multiplier (anything above 1 is instaheal)
  .entity iceblock;
  .entity muzzle_flash;
  .float misc_bulletcounter;    // replaces uzi & hlac bullet counter.
  
- .float stat_respawn_time; // shows respawn time, and is negative when awaiting respawn
+ .float stat_respawn_time = _STAT(RESPAWN_TIME); // shows respawn time, and is negative when awaiting respawn
  
  void PlayerUseKey();
  
diff --combined qcsrc/server/g_subs.qh
index 24cbe917e4ac428b3cf54bf7e7ef29e2e663578d,cebf61b7040d1b24302c4662e395272aadbd4a3f..81516f9357c56344f932fe70b439f282a6ddc72e
@@@ -6,19 -6,15 +6,9 @@@ void SUB_NullThink()
  void()  SUB_CalcMoveDone;
  void() SUB_CalcAngleMoveDone;
  //void() SUB_UseTargets;
- void() SUB_Remove;
  
  spawnfunc(info_null);
  
- /*
- ==================
- SUB_Remove
 -void setanim(entity e, vector anim, float looping, float override, float restart);
--
- Remove self
- ==================
- */
- void SUB_Remove ();
 -void updateanim(entity e);
 -
 -
--
  /*
  ==================
  SUB_Friction
diff --combined qcsrc/server/g_world.qc
index f8c1e15256c3cada6d91cdd0c42bc3dd92cce79e,a7036ca4f29b70fa19aeb25756d4cfc701de71af..9587d3cd1e2e4d103109bc77c8f3d21019eecea1
@@@ -18,7 -18,6 +18,6 @@@
  #include "scores.qh"
  #include "teamplay.qh"
  #include "weapons/weaponstats.qh"
- #include "../common/buffs/all.qh"
  #include "../common/constants.qh"
  #include "../common/deathtypes/all.qh"
  #include "../common/mapinfo.qh"
@@@ -552,13 -551,16 +551,16 @@@ spawnfunc(__init_dedicated_server
        MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
  }
  
+ void __init_dedicated_server_shutdown() {
+       MapInfo_Shutdown();
+ }
  void Map_MarkAsRecent(string m);
  float world_already_spawned;
  void Nagger_Init();
  void ClientInit_Spawn();
  void WeaponStats_Init();
  void WeaponStats_Shutdown();
- void Physics_AddStats();
  spawnfunc(worldspawn)
  {
        float fd, l, j, n;
  
        compressShortVector_init();
  
-       entity head;
-       head = nextent(world);
        maxclients = 0;
-       while(head)
+       for (entity head = nextent(world); head; head = nextent(head))
        {
                ++maxclients;
-               head = nextent(head);
        }
  
        server_is_dedicated = (stof(cvar_defstring("is_dedicated")) ? true : false);
  
        WeaponStats_Init();
  
-       WepSet_AddStat();
-       WepSet_AddStat_InMap();
-       addstat(STAT_SWITCHWEAPON, AS_INT, switchweapon);
-       addstat(STAT_SWITCHINGWEAPON, AS_INT, switchingweapon);
-       addstat(STAT_WEAPON_NEXTTHINK, AS_FLOAT, weapon_nextthink);
-       addstat(STAT_GAMESTARTTIME, AS_FLOAT, stat_game_starttime);
-       addstat(STAT_ROUNDSTARTTIME, AS_FLOAT, stat_round_starttime);
-       addstat(STAT_ALLOW_OLDVORTEXBEAM, AS_INT, stat_allow_oldvortexbeam);
        Nagger_Init();
  
-       addstat(STAT_STRENGTH_FINISHED, AS_FLOAT, strength_finished);
-       addstat(STAT_INVINCIBLE_FINISHED, AS_FLOAT, invincible_finished);
-       addstat(STAT_SUPERWEAPONS_FINISHED, AS_FLOAT, superweapons_finished);
-       addstat(STAT_PRESSED_KEYS, AS_FLOAT, pressedkeys);
-       addstat(STAT_FUEL, AS_INT, ammo_fuel);
-       addstat(STAT_PLASMA, AS_INT, ammo_plasma);
-       addstat(STAT_SHOTORG, AS_INT, stat_shotorg);
-       addstat(STAT_LEADLIMIT, AS_FLOAT, stat_leadlimit);
-       addstat(STAT_WEAPON_CLIPLOAD, AS_INT, clip_load);
-       addstat(STAT_WEAPON_CLIPSIZE, AS_INT, clip_size);
-       addstat(STAT_LAST_PICKUP, AS_FLOAT, last_pickup);
-       addstat(STAT_HIT_TIME, AS_FLOAT, hit_time);
-       addstat(STAT_DAMAGE_DEALT_TOTAL, AS_INT, damage_dealt_total);
-       addstat(STAT_TYPEHIT_TIME, AS_FLOAT, typehit_time);
-       addstat(STAT_LAYED_MINES, AS_INT, minelayer_mines);
-       addstat(STAT_VORTEX_CHARGE, AS_FLOAT, vortex_charge);
-       addstat(STAT_VORTEX_CHARGEPOOL, AS_FLOAT, vortex_chargepool_ammo);
-       addstat(STAT_HAGAR_LOAD, AS_INT, hagar_load);
-       addstat(STAT_ARC_HEAT, AS_FLOAT, arc_heat_percent);
-       // freeze attacks
-       addstat(STAT_FROZEN, AS_INT, frozen);
-       addstat(STAT_REVIVE_PROGRESS, AS_FLOAT, revive_progress);
-       // physics
-       Physics_AddStats();
-       // new properties
-       addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
-       addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
-       addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
-       addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
-       addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
-       addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
-       addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
-       addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
-       addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
-       addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
-       addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
-       addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
-       addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
-       addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
-       addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
-       // secrets
-       addstat(STAT_SECRETS_TOTAL, AS_FLOAT, stat_secrets_total);
-       addstat(STAT_SECRETS_FOUND, AS_FLOAT, stat_secrets_found);
-       // monsters
-       addstat(STAT_MONSTERS_TOTAL, AS_FLOAT, stat_monsters_total);
-       addstat(STAT_MONSTERS_KILLED, AS_FLOAT, stat_monsters_killed);
-       // misc
-       addstat(STAT_RESPAWN_TIME, AS_FLOAT, stat_respawn_time);
        next_pingtime = time + 5;
  
        detect_maptype();
@@@ -1466,7 -1395,6 +1395,6 @@@ void DumpStats(float final
  
  void FixIntermissionClient(entity e)
  {
-       string s;
        if(!e.autoscreenshot) // initial call
        {
                e.autoscreenshot = time + 0.8;  // used for autoscreenshot
                        if(e.(weaponentity))
                        {
                                e.(weaponentity).effects = EF_NODRAW;
 -                              if (e.(weaponentity).(weaponentity))
 -                                      e.(weaponentity).(weaponentity).effects = EF_NODRAW;
 +                              if (e.(weaponentity).weaponchild)
 +                                      e.(weaponentity).weaponchild.effects = EF_NODRAW;
                        }
                }
                if(IS_REAL_CLIENT(e))
                {
                        stuffcmd(e, "\nscr_printspeed 1000000\n");
-                       s = autocvar_sv_intermission_cdtrack;
-                       if(s != "")
-                               stuffcmd(e, strcat("\ncd loop ", s, "\n"));
+                       string list = autocvar_sv_intermission_cdtrack;
+                       for(string it; (it = car(list)); list = cdr(list))
+                               RandomSelection_Add(world, 0, it, 1, 1);
+                       if(RandomSelection_chosen_string && RandomSelection_chosen_string != "")
+                               stuffcmd(e, strcat("\ncd loop ", RandomSelection_chosen_string, "\n"));
                        msg_entity = e;
                        WriteByte(MSG_ONE, SVC_INTERMISSION);
                }
@@@ -1780,46 -1710,6 +1710,6 @@@ float WinningCondition_Scores(float lim
        );
  }
  
- float WinningCondition_Race(float fraglimit)
- {
-       float wc;
-       entity p;
-       float n, c;
-       n = 0;
-       c = 0;
-       FOR_EACH_PLAYER(p)
-       {
-               ++n;
-               if(p.race_completed)
-                       ++c;
-       }
-       if(n && (n == c))
-               return WINNING_YES;
-       wc = WinningCondition_Scores(fraglimit, 0);
-       // ALWAYS initiate overtime, unless EVERYONE has finished the race!
-       if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
-       // do NOT support equality when the laps are all raced!
-               return WINNING_STARTSUDDENDEATHOVERTIME;
-       else
-               return WINNING_NEVER;
- }
- float WinningCondition_QualifyingThenRace(float limit)
- {
-       float wc;
-       wc = WinningCondition_Scores(limit, 0);
-       // NEVER initiate overtime
-       if(wc == WINNING_YES || wc == WINNING_STARTSUDDENDEATHOVERTIME)
-       {
-               return WINNING_YES;
-       }
-       return wc;
- }
  float WinningCondition_RanOutOfSpawns()
  {
        entity head;
@@@ -2211,4 -2101,8 +2101,8 @@@ void Shutdown(
        {
                LOG_INFO("NOTE: crashed before even initializing the world, not saving persistent data\n");
        }
+       else
+       {
+               __init_dedicated_server_shutdown();
+       }
  }
diff --combined qcsrc/server/progs.inc
index d83234e906252eadb70ab9eb26b4f3afb0203639,e23909812d27dd6494ace3e26b6a9aa42ce49d7a..5c79a0d88429e478effa0bbd766e66b83e2d5d6a
@@@ -10,7 -10,6 +10,6 @@@
  #include "cl_client.qc"
  #include "cl_impulse.qc"
  #include "cl_player.qc"
- #include "ent_cs.qc"
  #include "g_damage.qc"
  #include "g_hook.qc"
  // #include "g_lights.qc" // TODO: was never used
  #include "weapons/weaponstats.qc"
  #include "weapons/weaponsystem.qc"
  
 +#include "../common/anim.qc"
  #include "../common/animdecide.qc"
  #include "../common/campaign_file.qc"
  #include "../common/campaign_setup.qc"
  #include "../common/effects/effectinfo.qc"
+ #include "../common/ent_cs.qc"
  #include "../common/mapinfo.qc"
  #include "../common/minigames/minigames.qc"
  #include "../common/minigames/sv_minigames.qc"
  #include "../common/viewloc.qc"
  
  #include "../common/deathtypes/all.qc"
- #include "../common/buffs/all.qc"
  #include "../common/effects/all.qc"
  #include "../common/gamemodes/all.qc"
  #include "../common/items/all.qc"
  #include "../common/monsters/all.qc"
- #include "../common/nades/all.qc"
  #include "../common/turrets/all.qc"
  #include "../common/vehicles/all.qc"
  #include "../common/weapons/all.qc"