Merge branch 'master' into Mario/race_cts_mutators
authorMario <zacjardine@y7mail.com>
Thu, 13 Nov 2014 14:02:30 +0000 (01:02 +1100)
committerMario <zacjardine@y7mail.com>
Thu, 13 Nov 2014 14:02:30 +0000 (01:02 +1100)
1  2 
qcsrc/server/anticheat.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_physics.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/mutators.qh
qcsrc/server/progs.src
qcsrc/server/sv_main.qc

@@@ -76,7 -76,8 +76,7 @@@ float movement_oddity(vector m0, vecto
  
  void anticheat_physics()
  {
 -      float f, wishspeed;
 -      vector wishvel;
 +      float f;
  
        // div0_evade -> SPECTATORS
        makevectors(self.v_angle);
                self.anticheat_speedhack_accu = 1;
                self.anticheat_speedhack_lasttime = servertime;
        }
 -
 -      // race/CTS: force kbd movement for fairness
 -      if(g_race || g_cts)
 -      {
 -              // if record times matter
 -              // ensure nothing EVIL is being done (i.e. div0_evade)
 -              // this hinders joystick users though
 -              // but it still gives SOME analog control
 -              wishvel_x = fabs(self.movement_x);
 -              wishvel_y = fabs(self.movement_y);
 -              if(wishvel_x != 0 && wishvel_y != 0 && wishvel_x != wishvel_y)
 -              {
 -                      wishvel_z = 0;
 -                      wishspeed = vlen(wishvel);
 -                      if(wishvel_x >= 2 * wishvel_y)
 -                      {
 -                              // pure X motion
 -                              if(self.movement_x > 0)
 -                                      self.movement_x = wishspeed;
 -                              else
 -                                      self.movement_x = -wishspeed;
 -                              self.movement_y = 0;
 -                      }
 -                      else if(wishvel_y >= 2 * wishvel_x)
 -                      {
 -                              // pure Y motion
 -                              self.movement_x = 0;
 -                              if(self.movement_y > 0)
 -                                      self.movement_y = wishspeed;
 -                              else
 -                                      self.movement_y = -wishspeed;
 -                      }
 -                      else
 -                      {
 -                              // diagonal
 -                              if(self.movement_x > 0)
 -                                      self.movement_x = M_SQRT1_2 * wishspeed;
 -                              else
 -                                      self.movement_x = -M_SQRT1_2 * wishspeed;
 -                              if(self.movement_y > 0)
 -                                      self.movement_y = M_SQRT1_2 * wishspeed;
 -                              else
 -                                      self.movement_y = -M_SQRT1_2 * wishspeed;
 -                      }
 -              }
 -      }
  }
  
  void anticheat_spectatecopy(entity spectatee)
@@@ -190,23 -237,23 +190,23 @@@ void anticheat_report(
                return;
        // TODO(divVerent): Use xonstat to acquire good thresholds.
        GameLogEcho(strcat(":anticheat:_time:", ftos(self.playerid), ":", ftos(servertime - self.anticheat_jointime)));
-       GameLogEcho(strcat(":anticheat:speedhack:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack), 240, 0.1, 0.15)));
-       GameLogEcho(strcat(":anticheat:speedhack_m1:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m1), 240, 0.1, 0.15)));
-       GameLogEcho(strcat(":anticheat:speedhack_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m2), 240, 0.1, 0.15)));
-       GameLogEcho(strcat(":anticheat:speedhack_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m3), 240, 0.1, 0.15)));
-       GameLogEcho(strcat(":anticheat:speedhack_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m4), 240, 0.1, 0.15)));
-       GameLogEcho(strcat(":anticheat:speedhack_m5:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m5), 240, 0.1, 0.15)));
-       GameLogEcho(strcat(":anticheat:div0_strafebot_old:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_strafebot_old), 120, 0.3, 0.4)));
-       GameLogEcho(strcat(":anticheat:div0_strafebot_new:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_strafebot_new), 120, 0.3, 0.4)));
-       GameLogEcho(strcat(":anticheat:div0_evade:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_evade), 120, 0.1, 0.2)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_signal) - MEAN_EVALUATE(anticheat_idle_snapaim_noise), 120, 0.1, 0.2)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_signal:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_signal), 120, 0.1, 0.2)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_noise:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_noise), 120, 0.1, 0.2)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m2), 120, 0.1, 0.2)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m3), 120, 0.1, 0.2)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m4), 120, 0.1, 0.2)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_m7:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m7), 120, 0.1, 0.2)));
-       GameLogEcho(strcat(":anticheat:idle_snapaim_m10:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m10), 120, 0.1, 0.2)));
+       GameLogEcho(strcat(":anticheat:speedhack:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack), 240, 0, 9999))); // Actually this one seems broken.
+       GameLogEcho(strcat(":anticheat:speedhack_m1:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m1), 240, 1.01, 1.25)));
+       GameLogEcho(strcat(":anticheat:speedhack_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m2), 240, 1.01, 1.25)));
+       GameLogEcho(strcat(":anticheat:speedhack_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m3), 240, 1.01, 1.25)));
+       GameLogEcho(strcat(":anticheat:speedhack_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m4), 240, 1.01, 1.25)));
+       GameLogEcho(strcat(":anticheat:speedhack_m5:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_speedhack_m5), 240, 1.01, 1.25)));
+       GameLogEcho(strcat(":anticheat:div0_strafebot_old:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_strafebot_old), 120, 0.15, 0.4)));
+       GameLogEcho(strcat(":anticheat:div0_strafebot_new:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_strafebot_new), 120, 0.25, 0.8)));
+       GameLogEcho(strcat(":anticheat:div0_evade:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_div0_evade), 120, 0.2, 0.5)));
+       GameLogEcho(strcat(":anticheat:idle_snapaim:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_signal) - MEAN_EVALUATE(anticheat_idle_snapaim_noise), 120, 0, 9999)));
+       GameLogEcho(strcat(":anticheat:idle_snapaim_signal:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_signal), 120, 0, 9999)));
+       GameLogEcho(strcat(":anticheat:idle_snapaim_noise:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_noise), 120, 0, 9999)));
+       GameLogEcho(strcat(":anticheat:idle_snapaim_m2:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m2), 120, 0, 9999)));
+       GameLogEcho(strcat(":anticheat:idle_snapaim_m3:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m3), 120, 0, 9999)));
+       GameLogEcho(strcat(":anticheat:idle_snapaim_m4:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m4), 120, 0, 9999)));
+       GameLogEcho(strcat(":anticheat:idle_snapaim_m7:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m7), 120, 0, 9999)));
+       GameLogEcho(strcat(":anticheat:idle_snapaim_m10:", ftos(self.playerid), ":", anticheat_display(MEAN_EVALUATE(anticheat_idle_snapaim_m10), 120, 0, 9999)));
  }
  
  float anticheat_getvalue(string id)
@@@ -1,3 -1,6 +1,3 @@@
 -void race_send_recordtime(float msg);
 -void race_SendRankings(float pos, float prevpos, float del, float msg);
 -
  void send_CSQC_teamnagger() {
        WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
        WriteByte(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
@@@ -137,6 -140,7 +137,6 @@@ void PutObserverInServer (void
  {
        entity  spot;
      self.hud = HUD_NORMAL;
 -      race_PreSpawnObserver();
  
        spot = SelectSpawnPoint (TRUE);
        if(!spot)
                WriteEntity(MSG_ONE, self);
        }
  
 -      if((g_race && g_race_qualifying) || g_cts)
 -      {
 -              if(PlayerScore_Add(self, SP_RACE_FASTEST, 0))
 -                      self.frags = FRAGS_LMS_LOSER;
 -              else
 -                      self.frags = FRAGS_SPECTATOR;
 -      }
 -      else
 -              self.frags = FRAGS_SPECTATOR;
 +      self.frags = FRAGS_SPECTATOR;
  
        MUTATOR_CALLHOOK(MakePlayerObserver);
  
@@@ -379,6 -391,8 +379,6 @@@ void PutClientInServer (void
                if(self.team < 0)
                        JoinBestTeam(self, FALSE, TRUE);
  
 -              race_PreSpawn();
 -
                spot = SelectSpawnPoint (FALSE);
                if(!spot)
                {
                spawnevent.owner = self;
                Net_LinkEntity(spawnevent, FALSE, 0.5, SpawnEvent_Send);
  
+               // Cut off any still running player sounds.
+               stopsound(self, CH_PLAYER_SINGLE);
                self.model = "";
                FixPlayermodel();
                self.drawonlytoclient = world;
  
                self.speedrunning = FALSE;
  
 -              race_PostSpawn(spot);
 -
                //stuffcmd(self, "chase_active 0");
                //stuffcmd(self, "set viewsize $tmpviewsize \n");
  
@@@ -1041,6 -1060,8 +1044,6 @@@ void ClientConnect (void
  
        anticheat_init();
  
 -      race_PreSpawnObserver();
 -
        // identify the right forced team
        if(autocvar_g_campaign)
        {
        else
                self.hitplotfh = -1;
  
 -      if(g_race || g_cts) {
 -              string rr;
 -              if(g_cts)
 -                      rr = CTS_RECORD;
 -              else
 -                      rr = RACE_RECORD;
 -
 -              msg_entity = self;
 -              race_send_recordtime(MSG_ONE);
 -              race_send_speedaward(MSG_ONE);
 -
 -              speedaward_alltimebest = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "speed/speed")));
 -              speedaward_alltimebest_holder = uid2name(db_get(ServerProgsDB, strcat(GetMapname(), rr, "speed/crypto_idfp")));
 -              race_send_speedaward_alltimebest(MSG_ONE);
 -
 -              float i;
 -              for (i = 1; i <= RANKINGS_CNT; ++i) {
 -                      race_SendRankings(i, 0, 0, MSG_ONE);
 -              }
 -      }
 -      else if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca) // teamnagger is currently bad for ca
 +      if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca && !g_cts && !g_race) // teamnagger is currently bad for ca, race & cts
                send_CSQC_teamnagger();
  
        CheatInitClient();
@@@ -1547,17 -1588,26 +1550,26 @@@ float CalcRotRegen(float current, floa
  
  void player_regen (void)
  {
+       float max_mod, regen_mod, rot_mod, limit_mod;
+       max_mod = regen_mod = rot_mod = limit_mod = 1;
+       regen_mod_max = max_mod;
+       regen_mod_regen = regen_mod;
+       regen_mod_rot = rot_mod;
+       regen_mod_limit = limit_mod;
        if(!MUTATOR_CALLHOOK(PlayerRegen))
        {
-               float minh, mina, maxh, maxa, limith, limita, max_mod, regen_mod, rot_mod, limit_mod;
+               float minh, mina, maxh, maxa, limith, limita;
                maxh = autocvar_g_balance_health_rotstable;
                maxa = autocvar_g_balance_armor_rotstable;
                minh = autocvar_g_balance_health_regenstable;
                mina = autocvar_g_balance_armor_regenstable;
                limith = autocvar_g_balance_health_limit;
                limita = autocvar_g_balance_armor_limit;
-               max_mod = regen_mod = rot_mod = limit_mod = 1;
+               
+               max_mod = regen_mod_max;
+               regen_mod = regen_mod_regen;
+               rot_mod = regen_mod_rot;
+               limit_mod = regen_mod_limit;
  
                maxh = maxh * max_mod;
                minh = minh * max_mod;
@@@ -2417,6 -2467,8 +2429,6 @@@ void PlayerPreThink (void
        if(self.spectatee_status != oldspectatee_status)
        {
                ClientData_Touch(self);
 -              if(g_race || g_cts)
 -                      race_InitSpectator();
        }
  
        if(self.teamkill_soundtime)
@@@ -2575,5 -2627,22 +2587,5 @@@ void PlayerPostThink (void
  
        playerdemo_write();
  
 -      if((g_cts || g_race) && self.cvar_cl_allow_uidtracking == 1 && self.cvar_cl_allow_uid2name == 1)
 -      {
 -              if (!self.stored_netname)
 -                      self.stored_netname = strzone(uid2name(self.crypto_idfp));
 -              if(self.stored_netname != self.netname)
 -              {
 -                      db_put(ServerProgsDB, strcat("/uid2name/", self.crypto_idfp), self.netname);
 -                      strunzone(self.stored_netname);
 -                      self.stored_netname = strzone(self.netname);
 -              }
 -      }
 -
 -      /*
 -      if(g_race)
 -              dprintf("%f %.6f\n", time, race_GetFractionalLapCount(self));
 -      */
 -
        CSQCMODEL_AUTOUPDATE();
  }
@@@ -23,14 -23,15 +23,15 @@@ void PlayerJump (void
                return; // no jumping while blocked
  
        float doublejump = FALSE;
+       float mjumpheight = autocvar_sv_jumpvelocity;
  
        player_multijump = doublejump;
+       player_jumpheight = mjumpheight;
        if(MUTATOR_CALLHOOK(PlayerJump))
                return;
  
        doublejump = player_multijump;
-       float mjumpheight;
+       mjumpheight = player_jumpheight;
  
        if (autocvar_sv_doublejump)
        {
@@@ -47,7 -48,6 +48,6 @@@
                }
        }
  
-       mjumpheight = autocvar_sv_jumpvelocity;
        if (self.waterlevel >= WATERLEVEL_SWIMMING)
        {
                self.velocity_z = self.stat_sv_maxspeed * 0.7;
@@@ -1250,22 -1250,22 +1250,22 @@@ void SV_PlayerPhysics(
                }
        }
  
 -      if((g_cts || g_race) && !IS_OBSERVER(self)) {
 -              if(vlen(self.velocity - self.velocity_z * '0 0 1') > speedaward_speed) {
 +      if((g_cts || g_race) && !IS_OBSERVER(self))
 +      {
 +              if(vlen(self.velocity - self.velocity_z * '0 0 1') > speedaward_speed)
 +              {
                        speedaward_speed = vlen(self.velocity - self.velocity_z * '0 0 1');
                        speedaward_holder = self.netname;
                        speedaward_uid = self.crypto_idfp;
                        speedaward_lastupdate = time;
                }
 -              if(speedaward_speed > speedaward_lastsent && time - speedaward_lastupdate > 1) {
 -                      string rr;
 -                      if(g_cts)
 -                              rr = CTS_RECORD;
 -                      else
 -                              rr = RACE_RECORD;
 +              if(speedaward_speed > speedaward_lastsent && time - speedaward_lastupdate > 1)
 +              {
 +                      string rr = (g_cts) ? CTS_RECORD : RACE_RECORD;
                        race_send_speedaward(MSG_ALL);
                        speedaward_lastsent = speedaward_speed;
 -                      if (speedaward_speed > speedaward_alltimebest && speedaward_uid != "") {
 +                      if (speedaward_speed > speedaward_alltimebest && speedaward_uid != "")
 +                      {
                                speedaward_alltimebest = speedaward_speed;
                                speedaward_alltimebest_holder = speedaward_holder;
                                speedaward_alltimebest_uid = speedaward_uid;
@@@ -930,6 -930,7 +930,7 @@@ void readlevelcvars(void
        CHECK_MUTATOR_ADD("g_nades", mutator_nades, 1);
        CHECK_MUTATOR_ADD("g_sandbox", sandbox, 1);
        CHECK_MUTATOR_ADD("g_campcheck", mutator_campcheck, 1);
+       CHECK_MUTATOR_ADD("g_buffs", mutator_buffs, 1);
  
        #undef CHECK_MUTATOR_ADD
  
        sv_clones = cvar("sv_clones");
        sv_foginterval = cvar("sv_foginterval");
        g_cloaked = cvar("g_cloaked");
 -    if(g_cts)
 -        g_cloaked = 1; // always enable cloak in CTS
        g_footsteps = cvar("g_footsteps");
        g_grappling_hook = cvar("g_grappling_hook");
        g_jetpack = cvar("g_jetpack");
@@@ -1080,15 -1083,6 +1081,6 @@@ float sound_allowed(float dest, entity 
      return TRUE;
  }
  
- #ifdef COMPAT_XON010_CHANNELS
- void(entity e, float chan, string samp, float vol, float atten) builtin_sound = #8;
- void sound(entity e, float chan, string samp, float vol, float atten)
- {
-     if (!sound_allowed(MSG_BROADCAST, e))
-         return;
-     builtin_sound(e, chan, samp, vol, atten);
- }
- #else
  #undef sound
  void sound(entity e, float chan, string samp, float vol, float atten)
  {
          return;
      sound7(e, chan, samp, vol, atten, 0, 0);
  }
- #endif
  
  void soundtoat(float dest, entity e, vector o, float chan, string samp, float vol, float atten)
  {
@@@ -1824,6 -1817,82 +1815,6 @@@ string uid2name(string myuid) 
        return s;
  }
  
 -float race_readTime(string map, float pos)
 -{
 -      string rr;
 -      if(g_cts)
 -              rr = CTS_RECORD;
 -      else
 -              rr = RACE_RECORD;
 -
 -      return stof(db_get(ServerProgsDB, strcat(map, rr, "time", ftos(pos))));
 -}
 -
 -string race_readUID(string map, float pos)
 -{
 -      string rr;
 -      if(g_cts)
 -              rr = CTS_RECORD;
 -      else
 -              rr = RACE_RECORD;
 -
 -      return db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos)));
 -}
 -
 -float race_readPos(string map, float t) {
 -      float i;
 -      for (i = 1; i <= RANKINGS_CNT; ++i)
 -              if (race_readTime(map, i) == 0 || race_readTime(map, i) > t)
 -                      return i;
 -
 -      return 0; // pos is zero if unranked
 -}
 -
 -void race_writeTime(string map, float t, string myuid)
 -{
 -      string rr;
 -      if(g_cts)
 -              rr = CTS_RECORD;
 -      else
 -              rr = RACE_RECORD;
 -
 -      float newpos;
 -      newpos = race_readPos(map, t);
 -
 -      float i, prevpos = 0;
 -      for(i = 1; i <= RANKINGS_CNT; ++i)
 -      {
 -              if(race_readUID(map, i) == myuid)
 -                      prevpos = i;
 -      }
 -      if (prevpos) { // player improved his existing record, only have to iterate on ranks between new and old recs
 -              for (i = prevpos; i > newpos; --i) {
 -                      db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), ftos(race_readTime(map, i - 1)));
 -                      db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), race_readUID(map, i - 1));
 -              }
 -      } else { // player has no ranked record yet
 -              for (i = RANKINGS_CNT; i > newpos; --i) {
 -                      db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), ftos(race_readTime(map, i - 1)));
 -                      db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), race_readUID(map, i - 1));
 -              }
 -      }
 -
 -      // store new time itself
 -      db_put(ServerProgsDB, strcat(map, rr, "time", ftos(newpos)), ftos(t));
 -      db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(newpos)), myuid);
 -}
 -
 -string race_readName(string map, float pos)
 -{
 -      string rr;
 -      if(g_cts)
 -              rr = CTS_RECORD;
 -      else
 -              rr = RACE_RECORD;
 -
 -      return uid2name(db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos))));
 -}
 -
  float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
  {
      float m, i;
@@@ -9,8 -9,6 +9,8 @@@ MUTATOR_DECLARATION(gamemode_onslaught)
  MUTATOR_DECLARATION(gamemode_domination);
  MUTATOR_DECLARATION(gamemode_lms);
  MUTATOR_DECLARATION(gamemode_invasion);
 +MUTATOR_DECLARATION(gamemode_cts);
 +MUTATOR_DECLARATION(gamemode_race);
  
  MUTATOR_DECLARATION(mutator_dodging);
  MUTATOR_DECLARATION(mutator_invincibleprojectiles);
@@@ -31,5 -29,6 +31,6 @@@ MUTATOR_DECLARATION(mutator_multijump)
  MUTATOR_DECLARATION(mutator_melee_only);
  MUTATOR_DECLARATION(mutator_nades);
  MUTATOR_DECLARATION(mutator_campcheck);
+ MUTATOR_DECLARATION(mutator_buffs);
  
  MUTATOR_DECLARATION(sandbox);
diff --combined qcsrc/server/progs.src
@@@ -13,8 -13,10 +13,10 @@@ sys-post.q
  ../warpzonelib/server.qh
  
  ../common/constants.qh
+ ../common/stats.qh
  ../common/teams.qh
  ../common/util.qh
+ ../common/buffs.qh
  ../common/test.qh
  ../common/counting.qh
  ../common/items.qh
@@@ -48,10 -50,9 +50,11 @@@ mutators/gamemode_keepaway.q
  mutators/gamemode_nexball.qh 
  mutators/gamemode_lms.qh
  mutators/gamemode_invasion.qh
 +mutators/gamemode_cts.qh
 +mutators/gamemode_race.qh
  mutators/mutator_dodging.qh
  mutators/mutator_nades.qh
+ mutators/mutator_buffs.qh
  
  //// tZork Turrets ////
  tturrets/include/turrets_early.qh
@@@ -90,6 -91,8 +93,8 @@@ scores.q
  
  spawnpoints.qh
  
+ mapvoting.qh
  ipban.qh
  
  race.qh
@@@ -133,6 -136,8 +138,8 @@@ pathlib/pathlib.q
  g_world.qc
  g_casings.qc
  
+ mapvoting.qc
  t_jumppads.qc
  t_teleporters.qc
  
@@@ -216,6 -221,8 +223,8 @@@ target_music.q
  
  ../common/items.qc
  
+ ../common/buffs.qc
  
  accuracy.qc
  ../csqcmodellib/sv_model.qc
@@@ -248,8 -255,6 +257,8 @@@ mutators/gamemode_nexball.q
  mutators/gamemode_onslaught.qc
  mutators/gamemode_lms.qc
  mutators/gamemode_invasion.qc
 +mutators/gamemode_cts.qc
 +mutators/gamemode_race.qc
  mutators/mutator_invincibleproj.qc
  mutators/mutator_new_toys.qc
  mutators/mutator_nix.qc
@@@ -270,6 -275,7 +279,7 @@@ mutators/mutator_multijump.q
  mutators/mutator_melee_only.qc
  mutators/mutator_nades.qc
  mutators/mutator_campcheck.qc
+ mutators/mutator_buffs.qc
  
  ../warpzonelib/anglestransform.qc
  ../warpzonelib/mathlib.qc
diff --combined qcsrc/server/sv_main.qc
@@@ -62,7 -62,7 +62,7 @@@ void CreatureFrame (void
                                                if (self.watersound_finished < time)
                                                {
                                                        self.watersound_finished = time + 0.5;
-                                                       sound (self, CH_PLAYER, "player/lava.wav", VOL_BASE, ATTEN_NORM);
+                                                       sound (self, CH_PLAYER_SINGLE, "player/lava.wav", VOL_BASE, ATTEN_NORM);
                                                }
                                                Damage (self, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA, self.origin, '0 0 0');
                                        }
@@@ -71,7 -71,7 +71,7 @@@
                                                if (self.watersound_finished < time)
                                                {
                                                        self.watersound_finished = time + 0.5;
-                                                       sound (self, CH_PLAYER, "player/slime.wav", VOL_BASE, ATTEN_NORM);
+                                                       sound (self, CH_PLAYER_SINGLE, "player/slime.wav", VOL_BASE, ATTEN_NORM);
                                                }
                                                Damage (self, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0');
                                        }
@@@ -94,7 -94,7 +94,7 @@@
                {
                        // check for falling damage
                        float velocity_len = vlen(self.velocity);
 -                      if(!self.hook.state && !(g_cts && !autocvar_g_cts_selfdamage))
 +                      if(!self.hook.state)
                        {
                                dm = vlen(self.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
                                if (self.deadflag)