]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge remote-tracking branch 'origin/master' into samual/respawn_improvements
authorSamual Lenks <samual@xonotic.org>
Mon, 29 Apr 2013 18:52:10 +0000 (14:52 -0400)
committerSamual Lenks <samual@xonotic.org>
Mon, 29 Apr 2013 18:52:10 +0000 (14:52 -0400)
Conflicts:
qcsrc/client/Main.qc
qcsrc/common/constants.qh

1  2 
qcsrc/client/Main.qc
qcsrc/common/constants.qh
qcsrc/server/cl_client.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/progs.src

diff --combined qcsrc/client/Main.qc
index 8e0689f000e12379955acbbaef29834c8f5a3ea6,ecc2000d7ccae32447fa4e78e75460a26e8f1f5a..9843033a1df20e49011c8852d22fb5fbd3ed1f14
@@@ -149,12 -149,14 +149,14 @@@ void CSQC_Init(void
        teams = Sort_Spawn();
        players = Sort_Spawn();
  
-       GetTeam(COLOR_SPECTATOR, true); // add specs first
+       GetTeam(NUM_SPECTATOR, true); // add specs first
  
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
+       CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
+       CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
+       
        WaypointSprite_Load();
  
        // precaches
        DamageInfo_Precache();
        Vehicles_Precache();
        turrets_precache();
-     Announcer_Precache();
        Tuba_Precache();
        CSQCPlayer_Precache();
        
  
        WarpZone_Init();
  
+       hud_skin_path = strzone(strcat("gfx/hud/", autocvar_hud_skin));
        hud_configure_prev = -1;
        tab_panel = -1;
  
@@@ -260,16 -262,16 +262,16 @@@ float SetTeam(entity o, float Team
                switch(Team)
                {
                        case -1:
-                       case COLOR_TEAM1:
-                       case COLOR_TEAM2:
-                       case COLOR_TEAM3:
-                       case COLOR_TEAM4:
+                       case NUM_TEAM_1:
+                       case NUM_TEAM_2:
+                       case NUM_TEAM_3:
+                       case NUM_TEAM_4:
                                break;
                        default:
                                if(GetTeam(Team, false) == world)
                                {
                                        print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
-                                       Team = COLOR_SPECTATOR;
+                                       Team = NUM_SPECTATOR;
                                }
                                break;
                }
                                if(GetTeam(Team, false) == world)
                                {
                                        print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
-                                       Team = COLOR_SPECTATOR;
+                                       Team = NUM_SPECTATOR;
                                }
                                break;
                }
@@@ -444,6 -446,7 +446,7 @@@ void Ent_ReadEntCS(
  
        entcs_receiver[self.sv_entnum] = self;
        self.entremove = Ent_RemoveEntCS;
+       self.iflags |= IFLAG_ORIGIN;
  
        InterpolateOrigin_Note();
  }
@@@ -693,34 -696,6 +696,34 @@@ void Ent_ReadAccuracy(void
        }
  }
  
 +void Spawn_Draw(void)
 +{
 +      pointparticles(particleeffectnum("EF_STARDUST"), self.origin, '0 0 2', bound(0, frametime, 0.1));
 +}
 +
 +void Ent_ReadSpawnPoint(float is_new)
 +{
 +      self.team = ReadByte();
 +      self.origin_x = ReadShort();
 +      self.origin_y = ReadShort();
 +      self.origin_z = ReadShort();
 +
 +      //self.colormod = colormapPaletteColor(self.team - 1, FALSE);
 +
 +      //setsize(self, PL_MIN, PL_MAX);
 +
 +      //droptofloor();
 +
 +      //self.mdl = "models/domination/dom_unclaimed.md3";
 +      //precache_model(self.mdl);
 +      //setmodel(self, self.mdl);
 +      self.drawmask = MASK_NORMAL;
 +      self.movetype = MOVETYPE_NOCLIP;
 +      self.draw = Spawn_Draw;
 +
 +      print(ftos(is_new), " - read a spawnpoint at ", vtos(self.origin), ", bitches.\n");
 +}
 +
  // CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
  // The only parameter reflects if the entity is "new" to the client, meaning it just came into the client's PVS.
  void Ent_RadarLink();
@@@ -806,7 -781,7 +809,9 @@@ void CSQC_Ent_Update(float bIsNewEntity
                case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
                case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;  
                case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
 +              case ENT_CLIENT_SPAWNPOINT: Ent_ReadSpawnPoint(bIsNewEntity); break;
+               case ENT_CLIENT_NOTIFICATION: Read_Notification(bIsNewEntity); break;
++
                default:
                        //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype));
                        error(sprintf(_("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n"), self.enttype, num_for_edict(self), self.classname));
@@@ -1130,6 -1105,12 +1135,12 @@@ void Net_ReadSpawn(
  {
        zoomin_effect = 1;
        current_viewzoom = (1 / bound(1, autocvar_cl_spawnzoom_factor, 16));
+       if(autocvar_cl_unpress_zoom_on_spawn)
+       {
+               localcmd("-zoom\n");
+               button_zoom = FALSE;
+       }
  }
  
  void Net_TeamNagger()
@@@ -1151,7 -1132,8 +1162,8 @@@ void Net_ReadPingPLReport(
        playerslots[e].ping_movementloss = ml / 255.0;
  }
  
- void Net_WeaponComplain() {
+ void Net_WeaponComplain()
+ {
        complain_weapon = ReadByte();
  
        if(complain_weapon_name)
  
        complain_weapon_time = time;
        weapontime = time; // ping the weapon panel
+       switch(complain_weapon_type)
+       {
+               case 0: Local_Notification(MSG_MULTI, ITEM_WEAPON_NOAMMO, complain_weapon); break;
+               case 1: Local_Notification(MSG_MULTI, ITEM_WEAPON_DONTHAVE, complain_weapon); break;
+               default: Local_Notification(MSG_MULTI, ITEM_WEAPON_UNAVAILABLE, complain_weapon); break;
+       }
  }
  
  // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
@@@ -1217,29 -1206,6 +1236,6 @@@ float CSQC_Parse_TempEntity(
                        Net_ReadPingPLReport();
                        bHandled = true;
                        break;
-               case TE_CSQC_ANNOUNCE:
-                       Announcer_Play(ReadString());
-                       bHandled = true;
-                       break;
-               case TE_CSQC_KILLNOTIFY:
-                       HUD_KillNotify(ReadString(), ReadString(), ReadString(), ReadShort(), ReadByte());
-                       bHandled = true;
-                       break;
-               case TE_CSQC_KILLCENTERPRINT:
-                       HUD_KillCenterprint(ReadString(), ReadString(), ReadShort(), ReadByte());
-                       bHandled = true;
-                       break;
-               case TE_CSQC_CENTERPRINT_GENERIC:
-                       float id;
-                       string s;
-                       id = ReadByte();
-                       s = ReadString();
-                       if (id != 0 && s != "")
-                               centerprint_generic(id, s, ReadByte(), ReadByte());
-                       else
-                               centerprint_generic(id, s, 0, 0);
-                       bHandled = true;
-                       break;
                case TE_CSQC_WEAPONCOMPLAIN:
                        Net_WeaponComplain();
                        bHandled = true;
index 44c8c1442117ad98b29566e8ea903b70da3d7caf,ffec62095b9b9466ffcf5db66a75251f254a18f5..a54a28456361fc2c67443521990b2fd29811284a
@@@ -36,17 -36,13 +36,13 @@@ const float TE_CSQC_NEXGUNBEAMPARTICLE 
  const float TE_CSQC_LIGHTNINGARC = 105;
  const float TE_CSQC_TEAMNAGGER = 106;
  const float TE_CSQC_PINGPLREPORT = 107;
- const float TE_CSQC_ANNOUNCE = 110;
- const float TE_CSQC_TARGET_MUSIC = 111;
- const float TE_CSQC_KILLNOTIFY = 112;
- const float TE_CSQC_KILLCENTERPRINT = 113;
- const float TE_CSQC_CENTERPRINT_GENERIC = 114;
- const float TE_CSQC_WEAPONCOMPLAIN = 115;
- const float TE_CSQC_NEX_SCOPE = 116;
- const float TE_CSQC_MINELAYER_MAXMINES = 117;
- const float TE_CSQC_HAGAR_MAXROCKETS = 118;
- const float TE_CSQC_VEHICLESETUP = 119;
- const float TE_CSQC_SVNOTICE = 120;
+ const float TE_CSQC_TARGET_MUSIC = 108;
+ const float TE_CSQC_WEAPONCOMPLAIN = 109;
+ const float TE_CSQC_NEX_SCOPE = 110;
+ const float TE_CSQC_MINELAYER_MAXMINES = 111;
+ const float TE_CSQC_HAGAR_MAXROCKETS = 112;
+ const float TE_CSQC_VEHICLESETUP = 113;
+ const float TE_CSQC_SVNOTICE = 114;
  
  const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
  const float RACE_NET_CHECKPOINT_CLEAR = 1;
@@@ -99,7 -95,7 +95,8 @@@ const float ENT_CLIENT_WARPZONE_TELEPOR
  const float ENT_CLIENT_MODEL = 33;
  const float ENT_CLIENT_ITEM = 34;
  const float ENT_CLIENT_BUMBLE_RAYGUN = 35;
 -const float ENT_CLIENT_NOTIFICATION = 36;
 +const float ENT_CLIENT_SPAWNPOINT = 36;
++const float ENT_CLIENT_NOTIFICATION = 37;
  
  const float ENT_CLIENT_TURRET = 40;
  const float ENT_CLIENT_AUXILIARYXHAIR = 50;
@@@ -365,85 -361,6 +362,6 @@@ float SPECIES_ROBOT_RUSTY  =  4
  float SPECIES_ROBOT_SHINY  =  5;
  float SPECIES_RESERVED     = 15;
  
- // Deathtypes (weapon deathtypes are the IT_* constants below)
- // NOTE: when adding death types, please add an explanation to Docs/spamlog.txt too.
- float DEATH_SPECIAL_START = 10000;
- float DEATH_FALL = 10000;
- float DEATH_TELEFRAG = 10001;
- float DEATH_DROWN = 10002;
- float DEATH_HURTTRIGGER = 10003;
- float DEATH_LAVA = 10004;
- float DEATH_SLIME = 10005;
- float DEATH_KILL = 10006;
- float DEATH_NOAMMO = 10007;
- float DEATH_SWAMP = 10008;
- float DEATH_TEAMCHANGE = 10009;
- float DEATH_AUTOTEAMCHANGE = 10010;
- float DEATH_CAMP = 10011;
- float DEATH_SHOOTING_STAR = 10012;
- float DEATH_ROT = 10013;
- float DEATH_MIRRORDAMAGE = 10014;
- float DEATH_TOUCHEXPLODE = 10015;
- float DEATH_CHEAT = 10016;
- float DEATH_FIRE = 10017;
- float DEATH_QUIET = 10021;
- float  DEATH_VHFIRST       = 10030;
- float  DEATH_VHCRUSH       = 10030;
- float  DEATH_SBMINIGUN     = 10031;
- float  DEATH_SBROCKET      = 10032;
- float  DEATH_SBBLOWUP      = 10033;
- float  DEATH_WAKIGUN       = 10034;
- float  DEATH_WAKIROCKET    = 10035;
- float  DEATH_WAKIBLOWUP    = 10036;
- float  DEATH_RAPTOR_CANNON = 10037;
- float  DEATH_RAPTOR_BOMB   = 10038;
- float  DEATH_RAPTOR_BOMB_SPLIT = 10039;
- float  DEATH_RAPTOR_DEATH   = 10040;
- float  DEATH_BUMB_GUN       = 10041;
- float  DEATH_BUMB_RAY       = 10042;
- float  DEATH_BUMB_RAY_HEAL  = 10043;
- float  DEATH_BUMB_DEATH     = 10044;
- float  DEATH_VHLAST         = 10044;
- #define DEATH_ISVEHICLE(t)  ((t) >= DEATH_VHFIRST && (t) <= DEATH_VHLAST)
- float DEATH_GENERIC = 10050;
- float DEATH_WEAPON = 10100;
- float DEATH_CUSTOM = 10300;
- float DEATH_TURRET                  = 10500;
- float DEATH_TURRET_EWHEEL           = 10501;
- float DEATH_TURRET_FLAC             = 10502;
- float DEATH_TURRET_MACHINEGUN       = 10503;
- float DEATH_TURRET_WALKER_GUN       = 10504;
- float DEATH_TURRET_WALKER_MEELE     = 10505;
- float DEATH_TURRET_WALKER_ROCKET    = 10506;
- float DEATH_TURRET_HELLION          = 10507;
- float DEATH_TURRET_HK               = 10508;
- float DEATH_TURRET_MLRS             = 10509;
- float DEATH_TURRET_PLASMA           = 10510;
- float DEATH_TURRET_PHASER           = 10511;
- float DEATH_TURRET_TESLA            = 10512;
- float DEATH_TURRET_LAST            = 10512;
- float DEATH_WEAPONMASK = 0xFF;
- float DEATH_HITTYPEMASK = 0x1F00; // which is WAY below 10000 used for normal deaths
- float HITTYPE_SECONDARY = 0x100;
- float HITTYPE_SPLASH = 0x200; // automatically set by RadiusDamage
- float HITTYPE_BOUNCE = 0x400;
- float HITTYPE_HEADSHOT = 0x800; // automatically set by Damage (if headshotbonus is set)
- float HITTYPE_RESERVED = 0x1000; // unused yet
- // macros to access these
- #define DEATH_ISTURRET(t)            ((t) >= DEATH_TURRET && (t) <= DEATH_TURRET_LAST)
- #define DEATH_ISSPECIAL(t)            ((t) >= DEATH_SPECIAL_START)
- #define DEATH_WEAPONOFWEAPONDEATH(t)  ((t) & DEATH_WEAPONMASK)
- #define DEATH_ISWEAPON(t,w)           (!DEATH_ISSPECIAL(t) && DEATH_WEAPONOFWEAPONDEATH(t) == (w))
- #define DEATH_WEAPONOF(t)             (DEATH_ISSPECIAL(t) ? 0 : DEATH_WEAPONOFWEAPONDEATH(t))
- #define WEP_VALID(w)                  ((w) >= WEP_FIRST && (w) <= WEP_LAST)
  #define FRAGS_PLAYER 0
  #define FRAGS_SPECTATOR -666
  #define FRAGS_LMS_LOSER -616
@@@ -458,62 -375,6 +376,6 @@@ float WATERLEVEL_SUBMERGED = 3
  
  float MAX_SHOT_DISTANCE = 32768;
  
- //centerprint ID list
- float CPID_TEAMCHANGE = 1;
- float CPID_CTF_CAPTURESHIELD = 2;
- float CPID_MINSTA_FINDAMMO = 3;
- float CPID_NIX_WPNCHANGE = 4;
- float CPID_DISCONNECT_IDLING = 5;
- float CPID_ROUND_STARTING = 6;
- float CPID_GAME_STARTING = 7;
- float CPID_TIMEOUT_COUNTDOWN = 8;
- float CPID_MOTD = 9;
- float CPID_KH_MSG = 10;
- float CPID_PREVENT_JOIN = 11;
- // CSQC centerprint/notify message types
- float MSG_SUICIDE = 0;
- float MSG_KILL = 1;
- float MSG_SPREE = 2;
- float MSG_KILL_ACTION = 3;
- float MSG_KILL_ACTION_SPREE = 4;
- float MSG_INFO = 5;
- float MSG_KA = 6;
- float MSG_RACE = 10;
- float KILL_TEAM_RED = 12001;
- float KILL_TEAM_BLUE = 12002;
- float KILL_TEAM_SPREE = 12003;
- float KILL_FIRST_BLOOD = 12004;
- float KILL_FIRST_VICTIM = 12005;
- float KILL_TYPEFRAG = 12006;
- float KILL_TYPEFRAGGED = 12007;
- float KILL_FRAG = 12008;
- float KILL_FRAGGED = 12009;
- float KILL_SPREE = 12010;
- float KILL_END_SPREE = 12011;
- float KILL_SPREE_3 = 12012;
- float KILL_SPREE_5 = 12013;
- float KILL_SPREE_10 = 12014;
- float KILL_SPREE_15 = 12015;
- float KILL_SPREE_20 = 12016;
- float KILL_SPREE_25 = 12017;
- float KILL_SPREE_30 = 12018;
- float INFO_GOTFLAG = 13001;
- float INFO_PICKUPFLAG = 13002;
- float INFO_LOSTFLAG = 13003;
- float INFO_RETURNFLAG = 13004;
- float INFO_CAPTUREFLAG = 13005;
- float KA_PICKUPBALL = 14001;
- float KA_DROPBALL = 14002;
- float RACE_SERVER_RECORD = 15001;
- float RACE_NEW_TIME = 15002;
- float RACE_NEW_RANK = 15003;
- float RACE_FAIL = 15004;
  // weapon requests
  float WR_SETUP                = 1; // (SVQC) setup weapon data
  float WR_THINK                = 2; // (SVQC) logic to run every frame
@@@ -521,8 -382,8 +383,8 @@@ float WR_CHECKAMMO1        = 3; // (SVQC) chec
  float WR_CHECKAMMO2   = 4; // (SVQC) checks ammo for weapon
  float WR_AIM          = 5; // (SVQC) runs bot aiming code for this weapon
  float WR_PRECACHE     = 6; // (CSQC and SVQC) precaches models/sounds used by this weapon
- float WR_SUICIDEMESSAGE = 7; // (CSQC) sets w_deathtypestring or leaves it alone (and may inspect w_deathtype for details)
- float WR_KILLMESSAGE    = 8; // (CSQC) sets w_deathtypestring or leaves it alone
+ float WR_SUICIDEMESSAGE = 7; // (SVQC) notification number for suicide message (may inspect w_deathtype for details)
+ float WR_KILLMESSAGE    = 8; // (SVQC) notification number for kill message (may inspect w_deathtype for details)
  float WR_RELOAD         = 9; // (SVQC) does not need to do anything
  float WR_RESETPLAYER    = 10; // (SVQC) does not need to do anything
  float WR_IMPACTEFFECT = 11; // (CSQC) impact effect
index 5f1fdfcd60dcca9059fbc3081763163a00954979,7f16dfd74ba449302824326641e3d6cdd07da71e..1dcd95ff952a13f127a6beb26628ba2993e72645
@@@ -6,22 -6,6 +6,6 @@@ void send_CSQC_teamnagger() 
        WriteByte(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
  }
  
- void Announce(string snd) {
-       WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
-       WriteByte(MSG_BROADCAST, TE_CSQC_ANNOUNCE);
-       WriteString(MSG_BROADCAST, snd);
- }
- void AnnounceTo(entity e, string snd) {
-       if (clienttype(e) == CLIENTTYPE_REAL)
-       {
-               msg_entity = e;
-               WriteByte(MSG_ONE, SVC_TEMPENTITY);
-               WriteByte(MSG_ONE, TE_CSQC_ANNOUNCE);
-               WriteString(MSG_ONE, snd);
-       }
- }
  float ClientData_Send(entity to, float sf)
  {
        if(to != self.owner)
@@@ -90,8 -74,240 +74,8 @@@ void ClientData_Touch(entity e
        }
  }
  
 -
 -.vector spawnpoint_score;
  .string netname_previous;
  
 -void spawnfunc_info_player_survivor (void)
 -{
 -      spawnfunc_info_player_deathmatch();
 -}
 -
 -void spawnfunc_info_player_start (void)
 -{
 -      spawnfunc_info_player_deathmatch();
 -}
 -
 -void spawnfunc_info_player_deathmatch (void)
 -{
 -      self.classname = "info_player_deathmatch";
 -      relocate_spawnpoint();
 -}
 -
 -void spawnpoint_use()
 -{
 -      if(teamplay)
 -      if(have_team_spawns > 0)
 -      {
 -              self.team = activator.team;
 -              some_spawn_has_been_used = 1;
 -      }
 -}
 -
 -// Returns:
 -//   _x: prio (-1 if unusable)
 -//   _y: weight
 -vector Spawn_Score(entity spot, float mindist, float teamcheck)
 -{
 -      float shortest, thisdist;
 -      float prio;
 -      entity player;
 -
 -      prio = 0;
 -
 -      // filter out spots for the wrong team
 -      if(teamcheck >= 0)
 -              if(spot.team != teamcheck)
 -                      return '-1 0 0';
 -
 -      if(race_spawns)
 -              if(spot.target == "")
 -                      return '-1 0 0';
 -
 -      if(clienttype(self) == CLIENTTYPE_REAL)
 -      {
 -              if(spot.restriction == 1)
 -                      return '-1 0 0';
 -      }
 -      else
 -      {
 -              if(spot.restriction == 2)
 -                      return '-1 0 0';
 -      }
 -
 -      shortest = vlen(world.maxs - world.mins);
 -      FOR_EACH_PLAYER(player) if (player != self)
 -      {
 -              thisdist = vlen(player.origin - spot.origin);
 -              if (thisdist < shortest)
 -                      shortest = thisdist;
 -      }
 -      if(shortest > mindist)
 -              prio += SPAWN_PRIO_GOOD_DISTANCE;
 -
 -      spawn_score = prio * '1 0 0' + shortest * '0 1 0';
 -      spawn_spot = spot;
 -
 -      // filter out spots for assault
 -      if(spot.target != "") {
 -              entity ent;
 -              float found;
 -
 -              found = 0;
 -              for(ent = world; (ent = find(ent, targetname, spot.target)); )
 -              {
 -                      ++found;
 -                      if(ent.spawn_evalfunc)
 -                      {
 -                              entity oldself = self;
 -                              self = ent;
 -                              spawn_score = ent.spawn_evalfunc(oldself, spot, spawn_score);
 -                              self = oldself;
 -                              if(spawn_score_x < 0)
 -                                      return spawn_score;
 -                      }
 -              }
 -
 -              if(!found)
 -              {
 -                      dprint("WARNING: spawnpoint at ", vtos(spot.origin), " could not find its target ", spot.target, "\n");
 -                      return '-1 0 0';
 -              }
 -      }
 -
 -      MUTATOR_CALLHOOK(Spawn_Score);
 -      return spawn_score;
 -}
 -
 -void Spawn_ScoreAll(entity firstspot, float mindist, float teamcheck)
 -{
 -      entity spot;
 -      for(spot = firstspot; spot; spot = spot.chain)
 -              spot.spawnpoint_score = Spawn_Score(spot, mindist, teamcheck);
 -}
 -
 -entity Spawn_FilterOutBadSpots(entity firstspot, float mindist, float teamcheck)
 -{
 -      entity spot, spotlist, spotlistend;
 -
 -      spotlist = world;
 -      spotlistend = world;
 -
 -      Spawn_ScoreAll(firstspot, mindist, teamcheck);
 -
 -      for(spot = firstspot; spot; spot = spot.chain)
 -      {
 -              if(spot.spawnpoint_score_x >= 0) // spawning allowed here
 -              {
 -                      if(spotlistend)
 -                              spotlistend.chain = spot;
 -                      spotlistend = spot;
 -                      if(!spotlist)
 -                              spotlist = spot;
 -              }
 -      }
 -      if(spotlistend)
 -              spotlistend.chain = world;
 -
 -      return spotlist;
 -}
 -
 -entity Spawn_WeightedPoint(entity firstspot, float lower, float upper, float exponent)
 -{
 -      // weight of a point: bound(lower, mindisttoplayer, upper)^exponent
 -      // multiplied by spot.cnt (useful if you distribute many spawnpoints in a small area)
 -      entity spot;
 -
 -      RandomSelection_Init();
 -      for(spot = firstspot; spot; spot = spot.chain)
 -              RandomSelection_Add(spot, 0, string_null, pow(bound(lower, spot.spawnpoint_score_y, upper), exponent) * spot.cnt, (spot.spawnpoint_score_y >= lower) * 0.5 + spot.spawnpoint_score_x);
 -
 -      return RandomSelection_chosen_ent;
 -}
 -
 -/*
 -=============
 -SelectSpawnPoint
 -
 -Finds a point to respawn
 -=============
 -*/
 -entity SelectSpawnPoint (float anypoint)
 -{
 -      float teamcheck;
 -      entity spot, firstspot;
 -
 -      spot = find (world, classname, "testplayerstart");
 -      if (spot)
 -              return spot;
 -
 -      if(anypoint || autocvar_g_spawn_useallspawns)
 -              teamcheck = -1;
 -      else if(have_team_spawns > 0)
 -      {
 -              if(have_team_spawns_forteam[self.team] == 0)
 -              {
 -                      // we request a spawn for a team, and we have team
 -                      // spawns, but that team has no spawns?
 -                      if(have_team_spawns_forteam[0])
 -                              // try noteam spawns
 -                              teamcheck = 0;
 -                      else
 -                              // if not, any spawn has to do
 -                              teamcheck = -1;
 -              }
 -              else
 -                      teamcheck = self.team; // MUST be team
 -      }
 -      else if(have_team_spawns == 0 && have_team_spawns_forteam[0])
 -              teamcheck = 0; // MUST be noteam
 -      else
 -              teamcheck = -1;
 -              // if we get here, we either require team spawns but have none, or we require non-team spawns and have none; use any spawn then
 -
 -
 -      // get the entire list of spots
 -      firstspot = findchain(classname, "info_player_deathmatch");
 -      // filter out the bad ones
 -      // (note this returns the original list if none survived)
 -      if(anypoint)
 -      {
 -              spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
 -      }
 -      else
 -      {
 -              float mindist;
 -              if (arena_roundbased && !g_ca)
 -                      mindist = 800;
 -              else
 -                      mindist = 100;
 -              firstspot = Spawn_FilterOutBadSpots(firstspot, mindist, teamcheck);
 -
 -              // there is 50/50 chance of choosing a random spot or the furthest spot
 -              // (this means that roughly every other spawn will be furthest, so you
 -              // usually won't get fragged at spawn twice in a row)
 -              if (random() > autocvar_g_spawn_furthest)
 -                      spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
 -              else
 -                      spot = Spawn_WeightedPoint(firstspot, 1, 5000, 5); // chooses a far far away spawnpoint
 -      }
 -
 -      if (!spot)
 -      {
 -              if(autocvar_spawn_debug)
 -                      GotoNextMap(0);
 -              else
 -              {
 -                      if(some_spawn_has_been_used)
 -                              return world; // team can't spawn any more, because of actions of other team
 -                      else
 -                              error("Cannot find a spawn point - please fix the map!");
 -              }
 -      }
 -
 -      return spot;
 -}
 -
  /*
  =============
  CheckPlayerModel
@@@ -169,7 -385,6 +153,6 @@@ void PutObserverInServer (void
                WriteEntity(MSG_ONE, self);
        }
  
-       DropAllRunes(self);
        MUTATOR_CALLHOOK(MakePlayerObserver);
  
        minstagib_stop_countdown(self);
  
        if(self.killcount != -666) {
                if(g_lms) {
-                       if(PlayerScore_Add(self, SP_LMS_RANK, 0) > 0)
-                               bprint ("^4", self.netname, "^4 has no more lives left\n");
+                       if(PlayerScore_Add(self, SP_LMS_RANK, 0) > 0 && self.lms_spectate_warning != 2)
+                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_LMS_NOLIVES, self.netname);
                        else
-                               bprint ("^4", self.netname, "^4 is spectating now\n"); // TODO turn this into a proper forfeit?
-               } else
-                       bprint ("^4", self.netname, "^4 is spectating now\n");
+                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_LMS_FORFEIT, self.netname);
+               } else { Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_SPECTATE, self.netname); }
  
                if(self.just_joined == FALSE) {
                        LogTeamchange(self.playerid, -1, 4);
        self.think = func_null;
        self.nextthink = 0;
        self.hook_time = 0;
-       self.runes = 0;
        self.deadflag = DEAD_NO;
        self.angles = spot.angles;
        self.angles_z = 0;
@@@ -332,7 -545,7 +313,7 @@@ void FixPlayermodel(
                if(teamplay)
                {
                        string s;
-                       s = Team_ColorNameLowerCase(self.team);
+                       s = Team_ColorName_Lower(self.team);
                        if(s != "neutral")
                        {
                                defaultmodel = cvar_string(strcat("sv_defaultplayermodel_", s));
                self.skin = stof(self.playerskin);
        }
  
-       if(chmdl || oldskin != self.skin)
-               self.species = player_getspecies(); // model or skin has changed
+       if(chmdl || oldskin != self.skin) // model or skin has changed
+       {
+               self.species = player_getspecies(); // update species
+               UpdatePlayerSounds(); // update skin sounds
+       }
  
        if(!teamplay)
                if(strlen(autocvar_sv_defaultplayercolors))
                                setcolor(self, stof(autocvar_sv_defaultplayercolors));
  }
  
- void PlayerTouchExplode(entity p1, entity p2)
- {
-       vector org;
-       org = (p1.origin + p2.origin) * 0.5;
-       org_z += (p1.mins_z + p2.mins_z) * 0.5;
-       te_explosion(org);
-       entity e;
-       e = spawn();
-       setorigin(e, org);
-       RadiusDamage(e, world, g_touchexplode_damage, g_touchexplode_edgedamage, g_touchexplode_radius, world, g_touchexplode_force, DEATH_TOUCHEXPLODE, world);
-       remove(e);
- }
  /*
  =============
  PutClientInServer
@@@ -464,7 -665,7 +433,7 @@@ void PutClientInServer (void
                spot = SelectSpawnPoint (FALSE);
                if(!spot)
                {
-                       centerprint(self, "Sorry, no spawnpoints available!\nHope your team can fix it...");
+                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_JOIN_NOSPAWNS);
                        return; // spawn failed
                }
  
  
                self.metertime = 0;
  
-               self.runes = 0;
                self.deadflag = DEAD_NO;
  
                self.angles = spot.angles;
  
                if(g_assault) {
                        if(self.team == assault_attacker_team)
-                               centerprint(self, "You are attacking!");
+                               Send_Notification(NOTIF_TEAM, self, MSG_CENTER, CENTER_ASSAULT_ATTACKING);
                        else
-                               centerprint(self, "You are defending!");
+                               Send_Notification(NOTIF_TEAM, self, MSG_CENTER, CENTER_ASSAULT_DEFENDING);
                }
  
                target_voicescript_clear(self);
@@@ -851,7 -1050,7 +818,7 @@@ void ClientKill_Now_TeamChange(
                if(g_ca)
                        self.caplayer = 0;
                if(blockSpectators)
-                       sprint(self, strcat("^7You have to become a player within the next ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n"));
+                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
                PutObserverInServer();
        }
        else
@@@ -917,7 -1116,7 +884,7 @@@ void KillIndicator_Think(
                if(clienttype(self.owner) == CLIENTTYPE_REAL)
                {
                        if(self.cnt <= 10)
-                               AnnounceTo(self.owner, strcat(ftos(self.cnt), ""));
+                               { Send_Notification(NOTIF_ONE, self.owner, MSG_ANNCE, Announcer_PickNumber(self.cnt)); }
                }
                self.nextthink = time + 1;
                self.cnt -= 1;
@@@ -1002,28 -1201,28 +969,28 @@@ void ClientKill_TeamChange (float targe
                        self.killindicator.colormod = '0 0 0';
                        if(clienttype(self) == CLIENTTYPE_REAL)
                        if(self.killindicator.cnt > 0)
-                               Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "^1Suicide in %d seconds", 1, self.killindicator.cnt);
+                               Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_SUICIDE, self.killindicator.cnt);
                }
                else if(targetteam == -1) // auto
                {
                        self.killindicator.colormod = '0 1 0';
                        if(clienttype(self) == CLIENTTYPE_REAL)
                        if(self.killindicator.cnt > 0)
-                               Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "Changing team in %d seconds", 1, self.killindicator.cnt);
+                               Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_AUTO, self.killindicator.cnt);
                }
                else if(targetteam == -2) // spectate
                {
                        self.killindicator.colormod = '0.5 0.5 0.5';
                        if(clienttype(self) == CLIENTTYPE_REAL)
                        if(self.killindicator.cnt > 0)
-                               Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "Spectating in %d seconds", 1, self.killindicator.cnt);
+                               Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_SPECTATE, self.killindicator.cnt);
                }
                else
                {
-                       self.killindicator.colormod = TeamColor(targetteam);
+                       self.killindicator.colormod = Team_ColorRGB(targetteam);
                        if(clienttype(self) == CLIENTTYPE_REAL)
                        if(self.killindicator.cnt > 0)
-                               Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, strcat("Changing to ", ColoredTeamName(targetteam), " in %d seconds"), 1, self.killindicator.cnt);
+                               Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, APP_TEAM_NUM_4(targetteam, CENTER_TEAMCHANGE_), self.killindicator.cnt);
                }
        }
  
@@@ -1065,7 -1264,7 +1032,7 @@@ void FixClientCvars(entity e
                stuffcmd(e, "cl_cmd settemp cl_movecliptokeyboard 2\n");
        if(autocvar_g_antilag == 3) // client side hitscan
                stuffcmd(e, "cl_cmd settemp cl_prydoncursor_notrace 0\n");
-       if(sv_gentle)
+       if(autocvar_sv_gentle)
                stuffcmd(e, "cl_cmd settemp cl_gentle 1\n");
        /*
         * we no longer need to stuff this. Remove this comment block if you feel
@@@ -1114,7 -1313,6 +1081,6 @@@ ClientConnec
  Called when a client connects to the server
  =============
  */
- string ColoredTeamName(float t);
  void DecodeLevelParms (void);
  //void dom_player_join_team(entity pl);
  void set_dom_state(entity e);
@@@ -1134,7 -1332,7 +1100,7 @@@ void ClientConnect (void
        DecodeLevelParms();
  
  #ifdef WATERMARK
-       sprint(self, strcat("^4SVQC Build information: ^1", WATERMARK, "\n"));
+       Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_WATERMARK, WATERMARK);
  #endif
  
        self.classname = "player_joining";
                {
                        switch(autocvar_g_campaign_forceteam)
                        {
-                               case 1: self.team_forced = COLOR_TEAM1; break;
-                               case 2: self.team_forced = COLOR_TEAM2; break;
-                               case 3: self.team_forced = COLOR_TEAM3; break;
-                               case 4: self.team_forced = COLOR_TEAM4; break;
+                               case 1: self.team_forced = NUM_TEAM_1; break;
+                               case 2: self.team_forced = NUM_TEAM_2; break;
+                               case 3: self.team_forced = NUM_TEAM_3; break;
+                               case 4: self.team_forced = NUM_TEAM_4; break;
                                default: self.team_forced = 0;
                        }
                }
        }
        else if(PlayerInIDList(self, autocvar_g_forced_team_red))
-               self.team_forced = COLOR_TEAM1;
+               self.team_forced = NUM_TEAM_1;
        else if(PlayerInIDList(self, autocvar_g_forced_team_blue))
-               self.team_forced = COLOR_TEAM2;
+               self.team_forced = NUM_TEAM_2;
        else if(PlayerInIDList(self, autocvar_g_forced_team_yellow))
-               self.team_forced = COLOR_TEAM3;
+               self.team_forced = NUM_TEAM_3;
        else if(PlayerInIDList(self, autocvar_g_forced_team_pink))
-               self.team_forced = COLOR_TEAM4;
+               self.team_forced = NUM_TEAM_4;
        else if(autocvar_g_forced_team_otherwise == "red")
-               self.team_forced = COLOR_TEAM1;
+               self.team_forced = NUM_TEAM_1;
        else if(autocvar_g_forced_team_otherwise == "blue")
-               self.team_forced = COLOR_TEAM2;
+               self.team_forced = NUM_TEAM_2;
        else if(autocvar_g_forced_team_otherwise == "yellow")
-               self.team_forced = COLOR_TEAM3;
+               self.team_forced = NUM_TEAM_3;
        else if(autocvar_g_forced_team_otherwise == "pink")
-               self.team_forced = COLOR_TEAM4;
+               self.team_forced = NUM_TEAM_4;
        else if(autocvar_g_forced_team_otherwise == "spectate")
                self.team_forced = -1;
        else if(autocvar_g_forced_team_otherwise == "spectator")
  
        self.netname_previous = strzone(self.netname);
  
-       bprint("^4", self.netname, "^4 connected");
-       if(self.classname != "observer" && (g_domination || g_ctf))
-               bprint(" and joined the ", ColoredTeamName(self.team));
-       bprint("\n");
+       if((self.classname == STR_PLAYER && teamplay))
+               Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(self, INFO_JOIN_CONNECT_TEAM_), self.netname);
+       else
+               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_JOIN_CONNECT, self.netname);
  
        stuffcmd(self, strcat(clientstuff, "\n"));
        stuffcmd(self, "cl_particles_reloadeffects\n"); // TODO do we still need this?
        self.spectatortime = time;
        if(blockSpectators)
        {
-               sprint(self, strcat("^7You have to become a player within the next ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n"));
+               Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
        }
  
        self.jointime = time;
  
        if(clienttype(self) == CLIENTTYPE_REAL)
        {
+               if(!autocvar_g_campaign)
+               {
+                       self.motd_actived_time = -1;
+                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
+               }
                if(autocvar_g_bugrigs || WEPSET_EQ_AW(g_weaponarena_weapons, WEP_TUBA))
                        stuffcmd(self, "cl_cmd settemp chase_active 1\n");
        }
  
        CheatInitClient();
  
-       if(!autocvar_g_campaign)
-               Send_CSQC_Centerprint_Generic(self, CPID_MOTD, getwelcomemessage(), autocvar_welcome_message_time, 0);
        CSQCMODEL_AUTOINIT();
  
        self.model_randomizer = random();
@@@ -1403,10 -1602,9 +1370,9 @@@ void ClientDisconnect (void
  
        if(autocvar_sv_eventlog)
                GameLogEcho(strcat(":part:", ftos(self.playerid)));
-       bprint ("^4",self.netname);
-       bprint ("^4 disconnected\n");
+               
+       Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_DISCONNECT, self.netname);
  
-       DropAllRunes(self);
        MUTATOR_CALLHOOK(ClientDisconnect);
  
        Portal_ClearAll(self);
@@@ -1575,7 -1773,8 +1541,8 @@@ void player_powerups (void
                                self.alpha = default_player_alpha;
                                self.exteriorweaponentity.alpha = default_weapon_alpha;
                                self.items &~= IT_STRENGTH;
-                               sprint(self, "^3Invisibility has worn off\n");
+                               //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_INVISIBILITY, self.netname);
+                               Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_INVISIBILITY);
                        }
                }
                else
                                self.alpha = g_minstagib_invis_alpha;
                                self.exteriorweaponentity.alpha = g_minstagib_invis_alpha;
                                self.items |= IT_STRENGTH;
-                               sprint(self, "^3You are invisible\n");
+                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_INVISIBILITY, self.netname);
+                               Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_INVISIBILITY);
                        }
                }
  
                        if (time > self.invincible_finished)
                        {
                                self.items = self.items - (self.items & IT_INVINCIBLE);
-                               sprint(self, "^3Speed has worn off\n");
+                               //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_SPEED, self.netname);
+                               Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SPEED);
                        }
                }
                else
                        if (time < self.invincible_finished)
                        {
                                self.items = self.items | IT_INVINCIBLE;
-                               sprint(self, "^3You are on speed\n");
+                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SPEED, self.netname);
+                               Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SPEED);
                        }
                }
        }
                        if (time > self.strength_finished)
                        {
                                self.items = self.items - (self.items & IT_STRENGTH);
-                               sprint(self, "^3Strength has worn off\n");
+                               //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_STRENGTH, self.netname);
+                               Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_STRENGTH);
                        }
                }
                else
                        if (time < self.strength_finished)
                        {
                                self.items = self.items | IT_STRENGTH;
-                               sprint(self, "^3Strength infuses your weapons with devastating power\n");
+                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_STRENGTH, self.netname);
+                               Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_STRENGTH);
                        }
                }
                if (self.items & IT_INVINCIBLE)
                        if (time > self.invincible_finished)
                        {
                                self.items = self.items - (self.items & IT_INVINCIBLE);
-                               sprint(self, "^3Shield has worn off\n");
+                               //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_SHIELD, self.netname);
+                               Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SHIELD);
                        }
                }
                else
                        if (time < self.invincible_finished)
                        {
                                self.items = self.items | IT_INVINCIBLE;
-                               sprint(self, "^3Shield surrounds you\n");
+                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SHIELD, self.netname);
+                               Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SHIELD);
                        }
                }
                if (self.items & IT_SUPERWEAPON)
                        {
                                self.superweapons_finished = 0;
                                self.items = self.items - (self.items & IT_SUPERWEAPON);
-                               sprint(self, "^3Superweapons have been lost\n");
+                               //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_LOST, self.netname);
+                               Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_SUPERWEAPON_LOST);
                        }
                        else if (self.items & IT_UNLIMITED_SUPERWEAPONS)
                        {
                                {
                                        self.items = self.items - (self.items & IT_SUPERWEAPON);
                                        WEPSET_ANDNOT_EA(self, WEPBIT_SUPERWEAPONS);
-                                       sprint(self, "^3Superweapons have broken down\n");
+                                       //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_BROKEN, self.netname);
+                                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_SUPERWEAPON_BROKEN);
                                }
                        }
                }
                        if (time < self.superweapons_finished || (self.items & IT_UNLIMITED_SUPERWEAPONS))
                        {
                                self.items = self.items | IT_SUPERWEAPON;
-                               sprint(self, "^3You now have a superweapon\n");
+                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_PICKUP, self.netname);
+                               Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_SUPERWEAPON_PICKUP);
                        }
                        else
                        {
@@@ -1769,32 -1978,6 +1746,6 @@@ void player_regen (void
  
        max_mod = regen_mod = rot_mod = limit_mod = 1;
  
-       if (self.runes & RUNE_REGEN)
-       {
-               if (self.runes & CURSE_VENOM) // do we have both rune/curse?
-               {
-                       regen_mod = autocvar_g_balance_rune_regen_combo_regenrate;
-                       max_mod = autocvar_g_balance_rune_regen_combo_hpmod;
-                       limit_mod = autocvar_g_balance_rune_regen_combo_limitmod;
-               }
-               else
-               {
-                       regen_mod = autocvar_g_balance_rune_regen_regenrate;
-                       max_mod = autocvar_g_balance_rune_regen_hpmod;
-                       limit_mod = autocvar_g_balance_rune_regen_limitmod;
-               }
-       }
-       else if (self.runes & CURSE_VENOM)
-       {
-               max_mod = autocvar_g_balance_curse_venom_hpmod;
-               if (self.runes & RUNE_REGEN) // do we have both rune/curse?
-                       rot_mod = autocvar_g_balance_rune_regen_combo_rotrate;
-               else
-                       rot_mod = autocvar_g_balance_curse_venom_rotrate;
-               limit_mod = autocvar_g_balance_curse_venom_limitmod;
-               //if (!self.runes & RUNE_REGEN)
-               //      rot_mod = autocvar_g_balance_curse_venom_rotrate;
-       }
        maxh = maxh * max_mod;
        //maxa = maxa * max_mod;
        //maxf = maxf * max_mod;
@@@ -2074,55 -2257,37 +2025,37 @@@ void ShowRespawnCountdown(
                {
                        self.respawn_countdown = number - 1;
                        if(ceil(self.respawn_time - (time + 0.5)) == number) // only say it if it is the same number even in 0.5s; to prevent overlapping sounds
-                               AnnounceTo(self, strcat(ftos(number), ""));
+                               Send_Notification(NOTIF_ONE, self, MSG_ANNCE, Announcer_PickNumber(number)); 
                }
        }
  }
  
- .float prevent_join_msgtime;
  void LeaveSpectatorMode()
  {
-       if(nJoinAllowed(self)) {
-               if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0) {
+       if(nJoinAllowed(self))
+       {
+               if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0)
+               {
                        self.classname = "player";
  
                        if(autocvar_g_campaign || autocvar_g_balance_teams)
-                               JoinBestTeam(self, FALSE, TRUE);
+                               { JoinBestTeam(self, FALSE, TRUE); }
  
                        if(autocvar_g_campaign)
-                               campaign_bots_may_start = 1;
-                       PutClientInServer();
-                       if(self.classname == "player")
-                               bprint ("^4", self.netname, "^4 is playing now\n");
+                               { campaign_bots_may_start = 1; }
  
-                       if(!autocvar_g_campaign)
-                       if (time < self.jointime + autocvar_welcome_message_time)
-                               Send_CSQC_Centerprint_Generic_Expire(self, CPID_MOTD); // clear MOTD
+                       Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_PREVENT_JOIN);
  
-                       if (self.prevent_join_msgtime)
-                       {
-                               Send_CSQC_Centerprint_Generic_Expire(self, CPID_PREVENT_JOIN);
-                               self.prevent_join_msgtime = 0;
-                       }
+                       PutClientInServer();
  
-                       return;
-               } else {
-                       if (g_ca && self.caplayer) {
-                       }       // do nothing
-                       else
-                               stuffcmd(self,"menu_showteamselect\n");
-                       return;
+                       if(IS_PLAYER(self)) { Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_JOIN_PLAY, self.netname); }
                }
+               else if not(g_ca && self.caplayer) { stuffcmd(self, "menu_showteamselect\n"); }
        }
-       else {
-               //player may not join because of g_maxplayers is set
-               if (time - self.prevent_join_msgtime > 2)
-               {
-                       Send_CSQC_Centerprint_Generic(self, CPID_PREVENT_JOIN, PREVENT_JOIN_TEXT, 0, 0);
-                       self.prevent_join_msgtime = time;
-               }
+       else
+       {
+               // Player may not join because g_maxplayers is set
+               Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_JOIN_PREVENT);
        }
  }
  
@@@ -2173,46 -2338,57 +2106,57 @@@ float nJoinAllowed(entity ignore) 
  void checkSpectatorBlock() {
        if(self.classname == "spectator" || self.classname == "observer") {
                if( time > (self.spectatortime + autocvar_g_maxplayers_spectator_blocktime) ) {
-                       sprint(self, "^7You were kicked from the server because you are spectator and spectators aren't allowed at the moment.\n");
+                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_QUIT_KICK_SPECTATING);
                        dropclient(self);
                }
        }
  }
  
- .float motd_actived_time; // used for both motd and campaign_message
  void PrintWelcomeMessage()
  {
-       if (self.motd_actived_time == 0) { // is there already a message showing?
+       if(self.motd_actived_time == 0)
+       {
                if (autocvar_g_campaign) {
                        if ((self.classname == "player" && self.BUTTON_INFO) || (self.classname != "player")) {
                                self.motd_actived_time = time;
-                               Send_CSQC_Centerprint_Generic(self, CPID_MOTD, campaign_message, -1, 0);
+                               Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, campaign_message);
                        }
                } else {
-                       if ((time - self.jointime > autocvar_welcome_message_time) && self.BUTTON_INFO) {
+                       if (self.BUTTON_INFO) {
                                self.motd_actived_time = time;
-                               Send_CSQC_Centerprint_Generic(self, CPID_MOTD, getwelcomemessage(), -1, 0);
+                               Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
                        }
                }
-       } else { // showing MOTD or campaign message
+       }
+       else if(self.motd_actived_time > 0) // showing MOTD or campaign message
+       {
                if (autocvar_g_campaign) {
                        if (self.BUTTON_INFO)
                                self.motd_actived_time = time;
                        else if ((time - self.motd_actived_time > 2) && self.classname == "player") { // hide it some seconds after BUTTON_INFO has been released
                                self.motd_actived_time = 0;
-                               Send_CSQC_Centerprint_Generic_Expire(self, CPID_MOTD);
+                               Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD);
                        }
                } else {
-                       if ((time - self.jointime) > autocvar_welcome_message_time) {
-                               if (self.BUTTON_INFO)
-                                       self.motd_actived_time = time;
-                               else if (time - self.motd_actived_time > 2) { // hide it some seconds after BUTTON_INFO has been released
-                                       self.motd_actived_time = 0;
-                                       Send_CSQC_Centerprint_Generic_Expire(self, CPID_MOTD);
-                               }
+                       if (self.BUTTON_INFO)
+                               self.motd_actived_time = time;
+                       else if (time - self.motd_actived_time > 2) { // hide it some seconds after BUTTON_INFO has been released
+                               self.motd_actived_time = 0;
+                               Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD);
                        }
                }
        }
+       else //if(self.motd_actived_time < 0) // just connected, motd is active
+       {
+               if(self.BUTTON_INFO) // BUTTON_INFO hides initial MOTD
+                       self.motd_actived_time = -2; // wait until BUTTON_INFO gets released
+               else if(self.motd_actived_time == -2 || IS_PLAYER(self) || time - self.jointime > autocvar_welcome_message_time)
+               {
+                       // instanctly hide MOTD
+                       self.motd_actived_time = 0;
+                       Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD);
+               }
+       }
  }
  
  void ObserverThink()
                        }
                }
        }
-       PrintWelcomeMessage();
  }
  
  void SpectatorThink()
                        PutObserverInServer();
        }
  
-       PrintWelcomeMessage();
        self.flags |= FL_CLIENT | FL_NOTARGET;
  }
  
@@@ -2302,8 -2475,6 +2243,6 @@@ void PlayerUseKey(
        MUTATOR_CALLHOOK(PlayerUseKey);
  }
  
- .float touchexplode_time;
  /*
  =============
  PlayerPreThink
@@@ -2360,7 -2531,7 +2299,7 @@@ void PlayerPreThink (void
                                        {
                                                // notify release users if connecting to git
                                                dprint("^1NOTE^7 to ", self.netname, "^7 - the server is running ^3Xonotic ", autocvar_g_xonoticversion, " (beta)^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n");
-                                               sprint(self, strcat("\{1}^1NOTE: ^7the server is running ^3Xonotic ", autocvar_g_xonoticversion, " (beta)^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n"));
+                                               Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_VERSION_BETA, autocvar_g_xonoticversion, self.cvar_g_xonoticversion);
                                        }
                                        else
                                        {
                                                {
                                                        // give users new version
                                                        dprint("^1NOTE^7 to ", self.netname, "^7 - ^3Xonotic ", autocvar_g_xonoticversion, "^7 is out, and you still have ^3Xonotic ", self.cvar_g_xonoticversion, "^1 - get the update from ^4http://www.xonotic.org/^1!\n");
-                                                       sprint(self, strcat("\{1}^1NOTE: ^3Xonotic ", autocvar_g_xonoticversion, "^7 is out, and you still have ^3Xonotic ", self.cvar_g_xonoticversion, "^1 - get the update from ^4http://www.xonotic.org/^1!\n"));
+                                                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_VERSION_OUTDATED, autocvar_g_xonoticversion, self.cvar_g_xonoticversion);
                                                }
                                                else if(r > 0)
                                                {
                                                        // notify users about old server version
                                                        print("^1NOTE^7 to ", self.netname, "^7 - the server is running ^3Xonotic ", autocvar_g_xonoticversion, "^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n");
-                                                       sprint(self, strcat("\{1}^1NOTE: ^7the server is running ^3Xonotic ", autocvar_g_xonoticversion, "^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n"));
+                                                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_VERSION_OLD, autocvar_g_xonoticversion, self.cvar_g_xonoticversion);
                                                }
                                        }
                                }
        // GOD MODE info
        if(!(self.flags & FL_GODMODE)) if(self.max_armorvalue)
        {
-               sprint(self, strcat("godmode saved you ", ftos(self.max_armorvalue), " units of damage, cheater!\n"));
+               Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_GODMODE_OFF, self.max_armorvalue);
                self.max_armorvalue = 0;
        }
  
                self.usekeypressed = self.BUTTON_USE;
        }
  
-       PrintWelcomeMessage();
+       if(clienttype(self) == CLIENTTYPE_REAL)
+               PrintWelcomeMessage();
  
        if(self.classname == "player") {
- //            if(self.netname == "Wazat")
- //                    bprint(self.classname, "\n");
  
                CheckRules_Player();
  
  
                if(frametime)
                {
- #ifndef NO_LEGACY_NETWORKING
-                       self.glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2;
- #endif
                        if(self.weapon == WEP_NEX && autocvar_g_balance_nex_charge)
                        {
                                self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
  
                        return;
                }
-               // FIXME from now on self.deadflag is always 0 (and self.health is never < 1)
-               // so (self.deadflag == DEAD_NO) is always true in the code below
-               if(g_touchexplode)
-               if(time > self.touchexplode_time)
-               if(self.classname == "player")
-               if(self.deadflag == DEAD_NO)
-               if not(IS_INDEPENDENT_PLAYER(self))
-               FOR_EACH_PLAYER(other) if(self != other)
-               {
-                       if(time > other.touchexplode_time)
-                       if(other.deadflag == DEAD_NO)
-                       if not(IS_INDEPENDENT_PLAYER(other))
-                       if(boxesoverlap(self.absmin, self.absmax, other.absmin, other.absmax))
-                       {
-                               PlayerTouchExplode(self, other);
-                               self.touchexplode_time = other.touchexplode_time = time + 0.2;
-                       }
-               }
  
                if(g_lms && !self.deadflag && autocvar_g_lms_campcheck_interval)
                {
                                //sprint(self, "distance: ", ftos(self.lms_traveled_distance), "\n");
                                if(self.lms_traveled_distance < autocvar_g_lms_campcheck_distance)
                                {
-                                       centerprint(self, autocvar_g_lms_campcheck_message);
+                                       Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_LMS_CAMPCHECK);
                                        // FIXME KadaverJack: gibbing player here causes playermodel to bounce around, instead of eye.md3
                                        // I wasn't able to find out WHY that happens, so I put a workaround in place that shall prevent players from being gibbed :(
-                                       Damage(self, self, self, bound(0, autocvar_g_lms_campcheck_damage, self.health + self.armorvalue * autocvar_g_balance_armor_blockpercent + 5), DEATH_CAMP, self.origin, '0 0 0');
+                                       if(self.vehicle)
+                                               Damage(self.vehicle, self, self, autocvar_g_lms_campcheck_damage * 2, DEATH_CAMP, self.vehicle.origin, '0 0 0');
+                                       else
+                                               Damage(self, self, self, bound(0, autocvar_g_lms_campcheck_damage, self.health + self.armorvalue * autocvar_g_balance_armor_blockpercent + 5), DEATH_CAMP, self.origin, '0 0 0');
                                }
                                self.lms_nextcheck = time + autocvar_g_lms_campcheck_interval;
                                self.lms_traveled_distance = 0;
  
                self.prevorigin = self.origin;
  
-               if (!self.vehicle)
-               if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x && !self.freezetag_frozen) // prevent crouching if using melee attack
+               float do_crouch = self.BUTTON_CROUCH;
+               if(self.hook.state)
+                       do_crouch = 0;
+               if(self.health <= g_bloodloss)
+                       do_crouch = 1;
+               if(self.vehicle)
+                       do_crouch = 0;
+               if(self.freezetag_frozen)
+                       do_crouch = 0;
+               if(self.weapon == WEP_SHOTGUN && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink)
+                       do_crouch = 0;
+               if (do_crouch)
                {
                        if (!self.crouch)
                        {
@@@ -2722,18 -2883,6 +2651,6 @@@ Called every frame for each client afte
  =============
  */
  .float idlekick_lasttimeleft;
- .entity showheadshotbbox;
- void showheadshotbbox_think()
- {
-       if(self.owner.showheadshotbbox != self)
-       {
-               remove(self);
-               return;
-       }
-       self.nextthink = time;
-       setorigin(self, self.owner.origin);
-       setsize(self, GetHeadshotMins(self.owner), GetHeadshotMaxs(self.owner));
- }
  void PlayerPostThink (void)
  {
        // Savage: Check for nameless players
        {
                if (time - self.parm_idlesince < 1) // instead of (time == self.parm_idlesince) to support sv_maxidle <= 10
                {
-                       if(self.idlekick_lasttimeleft)
-                       {
-                               Send_CSQC_Centerprint_Generic_Expire(self, CPID_DISCONNECT_IDLING);
-                               self.idlekick_lasttimeleft = 0;
-                       }
+                       if(self.idlekick_lasttimeleft) { self.idlekick_lasttimeleft = 0; }
                }
                else
                {
                        if(timeleft == min(10, sv_maxidle - 1)) // - 1 to support sv_maxidle <= 10
                        {
                                if(!self.idlekick_lasttimeleft)
-                                       Send_CSQC_Centerprint_Generic(self, CPID_DISCONNECT_IDLING, "^3Stop idling!\n^3Disconnecting in %d seconds...", 1, timeleft);
+                                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_DISCONNECT_IDLING, timeleft);
                        }
                        if(timeleft <= 0)
                        {
-                               bprint("^3", self.netname, "^3 was kicked for idling.\n");
-                               AnnounceTo(self, "terminated");
+                               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_KICK_IDLING, self.netname);
                                dropclient(self);
                                return;
                        }
                        else if(timeleft <= 10)
                        {
                                if(timeleft != self.idlekick_lasttimeleft)
-                                       AnnounceTo(self, ftos(timeleft));
+                                       Send_Notification(NOTIF_ONE, self, MSG_ANNCE, Announcer_PickNumber(timeleft));
                                self.idlekick_lasttimeleft = timeleft;
                        }
                }
        if(self.waypointsprite_attachedforcarrier)
                WaypointSprite_UpdateHealth(self.waypointsprite_attachedforcarrier, '1 0 0' * healtharmor_maxdamage(self.health, self.armorvalue, autocvar_g_balance_armor_blockpercent));
  
-       if(self.classname == "player" && self.deadflag == DEAD_NO && autocvar_r_showbboxes)
-       {
-               if(!self.showheadshotbbox)
-               {
-                       self.showheadshotbbox = spawn();
-                       self.showheadshotbbox.classname = "headshotbbox";
-                       self.showheadshotbbox.owner = self;
-                       self.showheadshotbbox.think = showheadshotbbox_think;
-                       self.showheadshotbbox.nextthink = time;
-                       self = self.showheadshotbbox;
-                       self.think();
-                       self = self.owner;
-               }
-       }
-       else
-       {
-               if(self.showheadshotbbox)
-                       if(self.showheadshotbbox && !wasfreed(self.showheadshotbbox))
-                 remove(self.showheadshotbbox);
-       }
        playerdemo_write();
  
        if((g_cts || g_race) && self.cvar_cl_allow_uidtracking == 1 && self.cvar_cl_allow_uid2name == 1)
index 7f288a6b6c248621b7731bc75ea4cc490249291a,545aa31b258f5dd64f888f834b3226c297ad1c5b..d57b28624aaf84a31ca1d5f5e542aca9f8b7397c
@@@ -32,7 -32,6 +32,6 @@@ void WarpZone_crosshair_trace(entity pl
  void() spawnfunc_info_player_deathmatch; // needed for the other spawnpoints
  void() spawnpoint_use;
  string GetMapname();
- string ColoredTeamName(float t);
  
  string admin_name(void)
  {
@@@ -80,26 -79,27 +79,27 @@@ float DistributeEvenly_GetRandomized(fl
  
  #define move_out_of_solid(e) WarpZoneLib_MoveOutOfSolid(e)
  
  string STR_PLAYER = "player";
  string STR_SPECTATOR = "spectator";
  string STR_OBSERVER = "observer";
  
- #if 0
- #define FOR_EACH_CLIENT(v) for(v = world; (v = findflags(v, flags, FL_CLIENT)) != world; )
- #define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(clienttype(v) == CLIENTTYPE_REAL)
- #define FOR_EACH_PLAYER(v) for(v = world; (v = find(v, classname, STR_PLAYER)) != world; )
- #define FOR_EACH_REALPLAYER(v) FOR_EACH_PLAYER(v) if(clienttype(v) == CLIENTTYPE_REAL)
- #else
+ #define IS_PLAYER(v)                  (v.classname == STR_PLAYER)
+ #define IS_SPEC(v)                            (v.classname == STR_SPECTATOR)
+ #define IS_OBSERVER(v)                        (v.classname == STR_OBSERVER)
+ #define IS_CLIENT(v)                  (v.flags & FL_CLIENT)
+ #define IS_BOT_CLIENT(v)              (clienttype(v) == CLIENTTYPE_BOT)
+ #define IS_REAL_CLIENT(v)             (clienttype(v) == CLIENTTYPE_REAL)
+ #define IS_NOT_A_CLIENT(v)            (clienttype(v) == CLIENTTYPE_NOTACLIENT)
  #define FOR_EACH_CLIENTSLOT(v) for(v = world; (v = nextent(v)) && (num_for_edict(v) <= maxclients); )
- #define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(v.flags & FL_CLIENT)
- #define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(clienttype(v) == CLIENTTYPE_REAL)
- #define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if(v.classname == STR_PLAYER)
- #define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if(v.classname != STR_PLAYER)
- #define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if(v.classname == STR_PLAYER)
- #endif
+ #define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(IS_CLIENT(v))
+ #define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(IS_REAL_CLIENT(v))
  
- #define CENTER_OR_VIEWOFS(ent) (ent.origin + ((ent.classname == STR_PLAYER) ? ent.view_ofs : ((ent.mins + ent.maxs) * 0.5)))
+ #define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if(IS_PLAYER(v))
+ #define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if not(IS_PLAYER(v)) // Samual: shouldn't this be IS_SPEC(v)? and rather create a separate macro to include observers too
+ #define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if(IS_PLAYER(v))
+ #define CENTER_OR_VIEWOFS(ent) (ent.origin + (IS_PLAYER(ent) ? ent.view_ofs : ((ent.mins + ent.maxs) * 0.5)))
  
  // copies a string to a tempstring (so one can strunzone it)
  string strcat1(string s) = #115; // FRIK_FILE
  float logfile_open;
  float logfile;
  
- void bcenterprint(string s)
- {
-     // TODO replace by MSG_ALL (would show it to spectators too, though)?
-     entity head;
-     FOR_EACH_PLAYER(head)
-     if (clienttype(head) == CLIENTTYPE_REAL)
-         centerprint(head, s);
- }
  void GameLogEcho(string s)
  {
      string fn;
@@@ -164,6 -155,63 +155,6 @@@ void GameLogClose(
      }
  }
  
 -float spawnpoint_nag;
 -void relocate_spawnpoint()
 -{
 -    // nudge off the floor
 -    setorigin(self, self.origin + '0 0 1');
 -
 -    tracebox(self.origin, PL_MIN, PL_MAX, self.origin, TRUE, self);
 -    if (trace_startsolid)
 -    {
 -        vector o;
 -        o = self.origin;
 -        self.mins = PL_MIN;
 -        self.maxs = PL_MAX;
 -        if (!move_out_of_solid(self))
 -            objerror("could not get out of solid at all!");
 -        print("^1NOTE: this map needs FIXING. Spawnpoint at ", vtos(o - '0 0 1'));
 -        print(" needs to be moved out of solid, e.g. by '", ftos(self.origin_x - o_x));
 -        print(" ", ftos(self.origin_y - o_y));
 -        print(" ", ftos(self.origin_z - o_z), "'\n");
 -        if (autocvar_g_spawnpoints_auto_move_out_of_solid)
 -        {
 -            if (!spawnpoint_nag)
 -                print("\{1}^1NOTE: this map needs FIXING (it contains spawnpoints in solid, see server log)\n");
 -            spawnpoint_nag = 1;
 -        }
 -        else
 -        {
 -            setorigin(self, o);
 -            self.mins = self.maxs = '0 0 0';
 -            objerror("player spawn point in solid, mapper sucks!\n");
 -            return;
 -        }
 -    }
 -
 -    self.use = spawnpoint_use;
 -    self.team_saved = self.team;
 -    if (!self.cnt)
 -        self.cnt = 1;
 -
 -    if (have_team_spawns != 0)
 -        if (self.team)
 -            have_team_spawns = 1;
 -    have_team_spawns_forteam[self.team] = 1;
 -
 -    if (autocvar_r_showbboxes)
 -    {
 -        // show where spawnpoints point at too
 -        makevectors(self.angles);
 -        entity e;
 -        e = spawn();
 -        e.classname = "info_player_foo";
 -        setorigin(e, self.origin + v_forward * 24);
 -        setsize(e, '-8 -8 -8', '8 8 8');
 -        e.solid = SOLID_TRIGGER;
 -    }
 -}
 -
  #define strstr strstrofs
  /*
  // NOTE: DO NOT USE THIS FUNCTION TOO OFTEN.
@@@ -489,7 -537,11 +480,11 @@@ void GetCvars(float f
  
        get_cvars_f = f;
        get_cvars_s = s;
        MUTATOR_CALLHOOK(GetCvars);
+       Notification_GetCvars();
        GetCvars_handleFloat(s, f, autoswitch, "cl_autoswitch");
        GetCvars_handleFloat(s, f, cvar_cl_autoscreenshot, "cl_autoscreenshot");
        GetCvars_handleString(s, f, cvar_g_xonoticversion, "g_xonoticversion");
        self.cvar_cl_accuracy_data_share = boolean(self.cvar_cl_accuracy_data_share);
        self.cvar_cl_accuracy_data_receive = boolean(self.cvar_cl_accuracy_data_receive);
  
- #ifdef ALLOW_FORCEMODELS
-       GetCvars_handleFloat(s, f, cvar_cl_forceplayermodels, "cl_forceplayermodels");
-       GetCvars_handleFloat(s, f, cvar_cl_forceplayermodelsfromxonotic, "cl_forceplayermodelsfromxonotic");
- #endif
        GetCvars_handleFloatOnce(s, f, cvar_cl_gunalign, "cl_gunalign");
        GetCvars_handleFloat(s, f, cvar_cl_allow_uid2name, "cl_allow_uid2name");
        GetCvars_handleFloat(s, f, cvar_cl_allow_uidtracking, "cl_allow_uidtracking");
        }
  }
  
- void backtrace(string msg)
- {
-     float dev, war;
-     dev = autocvar_developer;
-     war = autocvar_prvm_backtraceforwarnings;
-     cvar_set("developer", "1");
-     cvar_set("prvm_backtraceforwarnings", "1");
-     print("\n");
-     print("--- CUT HERE ---\nWARNING: ");
-     print(msg);
-     print("\n");
-     remove(world); // isn't there any better way to cause a backtrace?
-     print("\n--- CUT UNTIL HERE ---\n");
-     cvar_set("developer", ftos(dev));
-     cvar_set("prvm_backtraceforwarnings", ftos(war));
- }
- string Team_ColorCode(float teamid)
- {
-     if (teamid == COLOR_TEAM1)
-         return "^1";
-     else if (teamid == COLOR_TEAM2)
-         return "^4";
-     else if (teamid == COLOR_TEAM3)
-         return "^3";
-     else if (teamid == COLOR_TEAM4)
-         return "^6";
-     else
-         return "^7";
- }
- string Team_ColorName(float t)
- {
-     // fixme: Search for team entities and get their .netname's!
-     if (t == COLOR_TEAM1)
-         return "Red";
-     if (t == COLOR_TEAM2)
-         return "Blue";
-     if (t == COLOR_TEAM3)
-         return "Yellow";
-     if (t == COLOR_TEAM4)
-         return "Pink";
-     return "Neutral";
- }
- string Team_ColorNameLowerCase(float t)
- {
-     // fixme: Search for team entities and get their .netname's!
-     if (t == COLOR_TEAM1)
-         return "red";
-     if (t == COLOR_TEAM2)
-         return "blue";
-     if (t == COLOR_TEAM3)
-         return "yellow";
-     if (t == COLOR_TEAM4)
-         return "pink";
-     return "neutral";
- }
- float ColourToNumber(string team_colour)
- {
-       if (team_colour == "red")
-               return COLOR_TEAM1;
-       if (team_colour == "blue")
-               return COLOR_TEAM2;
-       if (team_colour == "yellow")
-               return COLOR_TEAM3;
-       if (team_colour == "pink")
-               return COLOR_TEAM4;
-       if (team_colour == "auto")
-               return 0;
-       return -1;
- }
- float NumberToTeamNumber(float number)
- {
-       if (number == 1)
-               return COLOR_TEAM1;
-       if (number == 2)
-               return COLOR_TEAM2;
-       if (number == 3)
-               return COLOR_TEAM3;
-       if (number == 4)
-               return COLOR_TEAM4;
-       return -1;
- }
  // decolorizes and team colors the player name when needed
  string playername(entity p)
  {
@@@ -1041,19 -993,9 +936,9 @@@ float g_bugrigs_speed_ref
  float g_bugrigs_speed_pow;
  float g_bugrigs_steer;
  
- float g_touchexplode;
- float g_touchexplode_radius;
- float g_touchexplode_damage;
- float g_touchexplode_edgedamage;
- float g_touchexplode_force;
  float sv_autotaunt;
  float sv_taunt;
  
- float sv_pitch_min;
- float sv_pitch_max;
- float sv_pitch_fixyaw;
  string GetGametype(); // g_world.qc
  void readlevelcvars(void)
  {
                MUTATOR_ADD(mutator_spawn_near_teammate);
        if(cvar("g_physical_items"))
                MUTATOR_ADD(mutator_physical_items);
+       if(cvar("g_touchexplode"))
+               MUTATOR_ADD(mutator_touchexplode);
        if(!g_minstagib)
        {
                if(cvar("g_invincible_projectiles"))
      g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
      g_bugrigs_steer = cvar("g_bugrigs_steer");
  
-     g_touchexplode = cvar("g_touchexplode");
-     g_touchexplode_radius = cvar("g_touchexplode_radius");
-     g_touchexplode_damage = cvar("g_touchexplode_damage");
-     g_touchexplode_edgedamage = cvar("g_touchexplode_edgedamage");
-     g_touchexplode_force = cvar("g_touchexplode_force");
- #ifdef ALLOW_FORCEMODELS
-       sv_clforceplayermodels = cvar("sv_clforceplayermodels");
- #endif
        sv_clones = cvar("sv_clones");
-       sv_gentle = cvar("sv_gentle");
        sv_foginterval = cvar("sv_foginterval");
        g_cloaked = cvar("g_cloaked");
      if(g_cts)
        g_warmup_allguns = cvar("g_warmup_allguns");
        g_warmup_allow_timeout = cvar("g_warmup_allow_timeout");
  
-       if ((g_race && g_race_qualifying == 2) || g_runematch || g_arena || g_assault || cvar("g_campaign"))
+       if ((g_race && g_race_qualifying == 2) || g_arena || g_assault || cvar("g_campaign"))
                inWarmupStage = 0; // these modes cannot work together, sorry
  
        g_pickup_respawntime_weapon = cvar("g_pickup_respawntime_weapon");
        if not(inWarmupStage && !g_ca)
                game_starttime = cvar("g_start_delay");
  
-       sv_pitch_min = cvar("sv_pitch_min");
-       sv_pitch_max = cvar("sv_pitch_max");
-       sv_pitch_fixyaw = cvar("sv_pitch_fixyaw");
        readplayerstartcvars();
  }
  
@@@ -1475,11 -1404,6 +1347,6 @@@ void precache(
  {
      // gamemode related things
      precache_model ("models/misc/chatbubble.spr");
-     if (g_runematch)
-     {
-         precache_model ("models/runematch/curse.mdl");
-         precache_model ("models/runematch/rune.mdl");
-     }
  
  #ifdef TTURRETS_ENABLED
      if (autocvar_g_turrets)
  #endif
  }
  
- // sorry, but using \ in macros breaks line numbers
- #define WRITESPECTATABLE_MSG_ONE_VARNAME(varname,statement) entity varname; varname = msg_entity; FOR_EACH_REALCLIENT(msg_entity) if(msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) statement msg_entity = varname
- #define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
- #define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
- void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, float countdown_num)
- {
-       if ((clienttype(e) == CLIENTTYPE_REAL) && (e.flags & FL_CLIENT))
-       {
-               msg_entity = e;
-               WRITESPECTATABLE_MSG_ONE({
-                       WriteByte(MSG_ONE, SVC_TEMPENTITY);
-                       WriteByte(MSG_ONE, TE_CSQC_CENTERPRINT_GENERIC);
-                       WriteByte(MSG_ONE, id);
-                       WriteString(MSG_ONE, s);
-                       if (id != 0 && s != "")
-                       {
-                               WriteByte(MSG_ONE, duration);
-                               WriteByte(MSG_ONE, countdown_num);
-                       }
-               });
-       }
- }
- void Send_CSQC_Centerprint_Generic_Expire(entity e, float id)
- {
-       Send_CSQC_Centerprint_Generic(e, id, "", 1, 0);
- }
  // WARNING: this kills the trace globals
  #define EXACTTRIGGER_TOUCH if(WarpZoneLib_ExactTrigger_Touch()) return
  #define EXACTTRIGGER_INIT  WarpZoneLib_ExactTrigger_Init()
@@@ -2105,22 -2001,6 +1944,6 @@@ string race_readName(string map, float 
        return uid2name(db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos))));
  }
  
- string race_placeName(float pos) {
-       if(floor((mod(pos, 100))/10) * 10 != 10) // examples: 12th, 111th, 213th will not execute this block
-       {
-               if(mod(pos, 10) == 1)
-                       return strcat(ftos(pos), "st");
-               else if(mod(pos, 10) == 2)
-                       return strcat(ftos(pos), "nd");
-               else if(mod(pos, 10) == 3)
-                       return strcat(ftos(pos), "rd");
-               else
-                       return strcat(ftos(pos), "th");
-       }
-       else
-               return strcat(ftos(pos), "th");
- }
  float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
  {
      float m, i;
diff --combined qcsrc/server/progs.src
index f6cd487658abb12bfff9c12ba5244136f5e7aeb1,157aa38a4377e2dfc74927f741c3e1cd577cd1f7..2bfab3778297c0be50c223e151ba62cbba816320
@@@ -13,7 -13,9 +13,9 @@@ sys-post.q
  ../warpzonelib/server.qh
  
  ../common/constants.qh
+ ../common/teams.qh
  ../common/util.qh
+ ../common/counting.qh
  ../common/items.qh
  ../common/explosion_equation.qh
  ../common/urllib.qh
  ../common/command/generic.qh
  ../common/command/shared_defs.qh
  ../common/net_notice.qh
+ ../common/animdecide.qh
  
  autocvars.qh
  constants.qh
  defs.qh               // Should rename this, it has fields and globals
  
+ ../common/notifications.qh // must be after autocvars
+ ../common/deathtypes.qh // must be after notifications
  mutators/base.qh
  mutators/mutators.qh
  mutators/gamemode_ctf.qh
@@@ -71,8 -77,6 +77,8 @@@ w_laser.q
  
  scores.qh
  
 +spawnpoints.qh
 +
  ipban.qh
  
  race.qh
@@@ -97,7 -101,7 +103,7 @@@ g_subs.q
  
  g_tetris.qc
  
- runematch.qc
//runematch.qc
  arena.qc
  
  g_violence.qc
@@@ -188,8 -192,6 +194,8 @@@ vehicles/vehicles.q
  
  scores.qc
  
 +spawnpoints.qc
 +
  portals.qc
  
  target_spawn.qc
@@@ -229,6 -231,7 +235,7 @@@ mutators/mutator_spawn_near_teammate.q
  mutators/mutator_physical_items.qc
  mutators/sandbox.qc
  mutators/mutator_superspec.qc
+ mutators/mutator_touchexplode.qc
  
  ../warpzonelib/anglestransform.qc
  ../warpzonelib/mathlib.qc
  ../warpzonelib/util_server.qc
  ../warpzonelib/server.qc
  
+ ../common/animdecide.qc
  ../common/util.qc
+ ../common/notifications.qc
  
  ../common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail