]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge remote-tracking branch 'origin/master' into Mario/assault_mutator
authorSamual Lenks <samual@xonotic.org>
Tue, 7 May 2013 05:42:27 +0000 (01:42 -0400)
committerSamual Lenks <samual@xonotic.org>
Tue, 7 May 2013 05:42:27 +0000 (01:42 -0400)
Conflicts:
qcsrc/server/cl_client.qc
qcsrc/server/mutators/mutators.qh
qcsrc/server/progs.src

1  2 
qcsrc/server/attic/assault.qc
qcsrc/server/autocvars.qh
qcsrc/server/bot/havocbot/roles.qc
qcsrc/server/cl_client.qc
qcsrc/server/mutators/base.qh
qcsrc/server/mutators/mutators.qh
qcsrc/server/progs.src
qcsrc/server/scores_rules.qc
qcsrc/server/teamplay.qc
qcsrc/server/vehicles/vehicles.qc

index 2562dca3df803fa93725204eb01f7059ef1cd189,0000000000000000000000000000000000000000..7a5662c9799fb51f738b7293a3e5ce04f9a99f44
mode 100644,000000..100644
--- /dev/null
@@@ -1,376 -1,0 +1,376 @@@
-       self.team = COLOR_TEAM1; // red, gets swapped every round
 +void spawnfunc_func_breakable();
 +void target_objective_decrease_activate();
 +.entity assault_decreaser;
 +.entity assault_sprite;
 +
 +void spawnfunc_info_player_attacker() {
 +      if(!g_assault)
 +      {
 +              remove(self);
 +              return;
 +      }
-       self.team = COLOR_TEAM2; // blue, gets swapped every round
++      self.team = NUM_TEAM_1; // red, gets swapped every round
 +      spawnfunc_info_player_deathmatch();
 +}
 +
 +void spawnfunc_info_player_defender() {
 +      if(!g_assault)
 +      {
 +              remove(self);
 +              return;
 +      }
-       if(assault_attacker_team == COLOR_TEAM1) {
-               self.team = COLOR_TEAM2;
++      self.team = NUM_TEAM_2; // blue, gets swapped every round
 +      spawnfunc_info_player_deathmatch();
 +}
 +
 +// reset this objective. Used when spawning an objective
 +// and when a new round starts
 +void assault_objective_reset() {
 +      self.health = ASSAULT_VALUE_INACTIVE;
 +}
 +
 +void assault_objective_use() {
 +      // activate objective
 +      self.health = 100;
 +      //print("^2Activated objective ", self.targetname, "=", etos(self), "\n");
 +      //print("Activator is ", activator.classname, "\n");
 +
 +      entity oldself;
 +      oldself = self;
 +
 +      for(self = world; (self = find(self, target, oldself.targetname)); )
 +      {
 +              if(self.classname == "target_objective_decrease")
 +                      target_objective_decrease_activate();
 +      }
 +
 +      self = oldself;
 +}
 +
 +vector target_objective_spawn_evalfunc(entity player, entity spot, vector current)
 +{
 +      if(self.health < 0 || self.health >= ASSAULT_VALUE_INACTIVE)
 +              return '-1 0 0';
 +      return current;
 +}
 +
 +void spawnfunc_target_objective() {
 +      if(!g_assault)
 +      {
 +              remove(self);
 +              return;
 +      }
 +      self.classname = "target_objective";
 +      self.use = assault_objective_use;
 +      assault_objective_reset();
 +      self.reset = assault_objective_reset;
 +      self.spawn_evalfunc = target_objective_spawn_evalfunc;
 +}
 +
 +
 +// decrease the health of targeted objectives
 +void assault_objective_decrease_use() {
 +      if(activator.team != assault_attacker_team) {
 +              // wrong team triggered decrease
 +              return;
 +      }
 +
 +      if(other.assault_sprite)
 +      {
 +              WaypointSprite_Disown(other.assault_sprite, waypointsprite_deadlifetime);
 +              if(other.classname == "func_assault_destructible")
 +                      other.sprite = world;
 +      }
 +      else
 +              return; // already activated! cannot activate again!
 +
 +      if(self.enemy.health < ASSAULT_VALUE_INACTIVE)
 +      {
 +              if(self.enemy.health - self.dmg > 0.5)
 +              {
 +                      PlayerTeamScore_Add(activator, SP_SCORE, ST_SCORE, self.dmg);
 +                      self.enemy.health = self.enemy.health - self.dmg;
 +              }
 +              else
 +              {
 +                      PlayerTeamScore_Add(activator, SP_SCORE, ST_SCORE, self.enemy.health);
 +                      PlayerTeamScore_Add(activator, SP_ASSAULT_OBJECTIVES, ST_ASSAULT_OBJECTIVES, 1);
 +                      self.enemy.health = -1;
 +
 +                      entity oldself, oldactivator;
 +
 +                      oldself = self;
 +                      self = oldself.enemy;
 +                              if(self.message)
 +                              {
 +                                      entity player;
 +                                      string s;
 +                                      FOR_EACH_PLAYER(player)
 +                                      {
 +                                              s = strcat(self.message, "\n");
 +                                              centerprint(player, s);
 +                                      }
 +                              }
 +
 +                              oldactivator = activator;
 +                              activator = oldself;
 +                                      SUB_UseTargets();
 +                              activator = oldactivator;
 +                      self = oldself;
 +              }
 +      }
 +}
 +
 +void assault_setenemytoobjective()
 +{
 +      entity objective;
 +      for(objective = world; (objective = find(objective, targetname, self.target)); ) {
 +              if(objective.classname == "target_objective") {
 +                      if(self.enemy == world)
 +                              self.enemy = objective;
 +                      else
 +                              objerror("more than one objective as target - fix the map!");
 +                      break;
 +              }
 +      }
 +
 +      if(self.enemy == world)
 +              objerror("no objective as target - fix the map!");
 +}
 +
 +float assault_decreaser_sprite_visible(entity e)
 +{
 +      entity decreaser;
 +
 +      decreaser = self.assault_decreaser;
 +
 +      if(decreaser.enemy.health >= ASSAULT_VALUE_INACTIVE)
 +              return FALSE;
 +
 +      return TRUE;
 +}
 +
 +void target_objective_decrease_activate()
 +{
 +      entity ent, spr;
 +      self.owner = world;
 +      for(ent = world; (ent = find(ent, target, self.targetname)); )
 +      {
 +              if(ent.assault_sprite != world)
 +              {
 +                      WaypointSprite_Disown(ent.assault_sprite, waypointsprite_deadlifetime);
 +                      if(ent.classname == "func_assault_destructible")
 +                              ent.sprite = world;
 +              }
 +
 +              spr = WaypointSprite_SpawnFixed("<placeholder>", 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite, RADARICON_OBJECTIVE, '1 0.5 0');
 +              spr.assault_decreaser = self;
 +              spr.waypointsprite_visible_for_player = assault_decreaser_sprite_visible;
 +              spr.classname = "sprite_waypoint";
 +              WaypointSprite_UpdateRule(spr, assault_attacker_team, SPRITERULE_TEAMPLAY);
 +              if(ent.classname == "func_assault_destructible")
 +              {
 +                      WaypointSprite_UpdateSprites(spr, "as-defend", "as-destroy", "as-destroy");
 +                      WaypointSprite_UpdateMaxHealth(spr, ent.max_health);
 +                      WaypointSprite_UpdateHealth(spr, ent.health);
 +                      ent.sprite = spr;
 +              }
 +              else
 +                      WaypointSprite_UpdateSprites(spr, "as-defend", "as-push", "as-push");
 +      }
 +}
 +
 +void target_objective_decrease_findtarget()
 +{
 +      assault_setenemytoobjective();
 +}
 +
 +//=============================================================================
 +
 +void spawnfunc_target_objective_decrease() {
 +      if(!g_assault)
 +      {
 +              remove(self);
 +              return;
 +      }
 +
 +      self.classname = "target_objective_decrease";
 +
 +      if(!self.dmg) {
 +              self.dmg = 101;
 +      }
 +      self.use = assault_objective_decrease_use;
 +      self.health = ASSAULT_VALUE_INACTIVE;
 +      self.max_health = ASSAULT_VALUE_INACTIVE;
 +      self.enemy = world;
 +
 +      InitializeEntity(self, target_objective_decrease_findtarget, INITPRIO_FINDTARGET);
 +}
 +
 +// destructible walls that can be used to trigger target_objective_decrease
 +void spawnfunc_func_assault_destructible() {
 +      if(!g_assault)
 +      {
 +              remove(self);
 +              return;
 +      }
 +      self.spawnflags = 3;
 +      self.classname = "func_assault_destructible";
-               self.team = COLOR_TEAM1;
++      if(assault_attacker_team == NUM_TEAM_1) {
++              self.team = NUM_TEAM_2;
 +      } else {
-               if(ent.team == COLOR_TEAM1)
-                       ent.team = COLOR_TEAM2;
++              self.team = NUM_TEAM_1;
 +      }
 +      spawnfunc_func_breakable();
 +}
 +
 +void assault_wall_think() {
 +      if(self.enemy.health < 0) {
 +              self.model = "";
 +              self.solid = SOLID_NOT;
 +      } else {
 +              self.model = self.mdl;
 +              self.solid = SOLID_BSP;
 +      }
 +
 +      self.nextthink = time + 0.2;
 +}
 +
 +void spawnfunc_func_assault_wall() {
 +      if(!g_assault)
 +      {
 +              remove(self);
 +              return;
 +      }
 +      self.classname = "func_assault_wall";
 +      self.mdl = self.model;
 +      setmodel(self, self.mdl);
 +      self.solid = SOLID_BSP;
 +      self.think = assault_wall_think;
 +      self.nextthink = time;
 +      InitializeEntity(self, assault_setenemytoobjective, INITPRIO_FINDTARGET);
 +}
 +
 +
 +void target_assault_roundend_reset() {
 +      //print("round end reset\n");
 +      self.cnt = self.cnt + 1; // up round counter
 +      self.winning = 0; // up round
 +}
 +
 +void target_assault_roundend_use() {
 +      self.winning = 1; // round has been won by attackers
 +}
 +
 +void spawnfunc_target_assault_roundend() {
 +      if(!g_assault)
 +      {
 +              remove(self);
 +              return;
 +      }
 +      self.winning = 0; // round not yet won by attackers
 +      self.classname = "target_assault_roundend";
 +      self.use = target_assault_roundend_use;
 +      self.cnt = 0; // first round
 +      self.reset = target_assault_roundend_reset;
 +}
 +
 +void assault_roundstart_use() {
 +
 +      activator = self;
 +      SUB_UseTargets();
 +
 +
 +#ifdef TTURRETS_ENABLED
 +      entity ent, oldself;
 +
 +      //(Re)spawn all turrets
 +      oldself = self;
 +      ent = find(world, classname, "turret_main");
 +      while(ent) {
 +              // Swap turret teams
-                       ent.team = COLOR_TEAM1;
++              if(ent.team == NUM_TEAM_1)
++                      ent.team = NUM_TEAM_2;
 +              else
-       assault_attacker_team = COLOR_TEAM1;
++                      ent.team = NUM_TEAM_1;
 +
 +              self = ent;
 +
 +              // Dubbles as teamchange
 +              turret_stdproc_respawn();
 +
 +              ent = find(ent, classname, "turret_main");
 +      }
 +      self = oldself;
 +#endif
 +
 +
 +}
 +
 +void spawnfunc_target_assault_roundstart() {
 +      if(!g_assault)
 +      {
 +              remove(self);
 +              return;
 +      }
-       if(assault_attacker_team == COLOR_TEAM1) {
-               assault_attacker_team = COLOR_TEAM2;
++      assault_attacker_team = NUM_TEAM_1;
 +      self.classname = "target_assault_roundstart";
 +      self.use = assault_roundstart_use;
 +      self.reset2 = assault_roundstart_use;
 +      InitializeEntity(self, assault_roundstart_use, INITPRIO_FINDTARGET);
 +}
 +
 +// trigger new round
 +// reset objectives, toggle spawnpoints, reset triggers, ...
 +void vehicles_clearrturn();
 +void vehicles_spawn();
 +void assault_new_round()
 +{
 +    entity oldself;
 +      //bprint("ASSAULT: new round\n");
 +
 +      oldself = self;
 +      // Eject players from vehicles
 +    FOR_EACH_PLAYER(self)
 +    {
 +        if(self.vehicle)
 +            vehicles_exit(VHEF_RELESE);
 +    }
 +
 +    self = findchainflags(vehicle_flags, VHF_ISVEHICLE);
 +    while(self)
 +    {
 +        vehicles_clearrturn();
 +        vehicles_spawn();
 +        self = self.chain;
 +    }
 +
 +    self = oldself;
 +
 +      // up round counter
 +      self.winning = self.winning + 1;
 +
 +      // swap attacker/defender roles
-               assault_attacker_team = COLOR_TEAM1;
++      if(assault_attacker_team == NUM_TEAM_1) {
++              assault_attacker_team = NUM_TEAM_2;
 +      } else {
-                       if(ent.team_saved == COLOR_TEAM1)
-                               ent.team_saved = COLOR_TEAM2;
-                       else if(ent.team_saved == COLOR_TEAM2)
-                               ent.team_saved = COLOR_TEAM1;
++              assault_attacker_team = NUM_TEAM_1;
 +      }
 +
 +
 +      entity ent;
 +      for(ent = world; (ent = nextent(ent)); )
 +      {
 +              if(clienttype(ent) == CLIENTTYPE_NOTACLIENT)
 +              {
++                      if(ent.team_saved == NUM_TEAM_1)
++                              ent.team_saved = NUM_TEAM_2;
++                      else if(ent.team_saved == NUM_TEAM_2)
++                              ent.team_saved = NUM_TEAM_1;
 +              }
 +      }
 +
 +      // reset the level with a countdown
 +      cvar_set("timelimit", ftos(ceil(time - game_starttime) / 60));
 +      ReadyRestart_force(); // sets game_starttime
 +}
index 45e5d35fba71d805eea9c3116af1f5b642b503bd,bfc362caff91a1e9f630248669fce9d41bba8d50..efb9f8c17a240cfdd5869f6a074a7cb15fd2383b
@@@ -75,7 -75,9 +75,8 @@@ float autocvar_g_arena_maxspawned
  float autocvar_g_arena_point_leadlimit;
  float autocvar_g_arena_point_limit;
  float autocvar_g_arena_roundbased;
+ float autocvar_g_arena_round_timelimit;
  float autocvar_g_arena_warmup;
 -float autocvar_g_assault;
  float autocvar_g_balance_armor_blockpercent;
  float autocvar_g_balance_armor_limit;
  float autocvar_g_balance_armor_regen;
@@@ -93,7 -95,6 +94,6 @@@ float autocvar_g_balance_rifle_primary_
  float autocvar_g_balance_rifle_primary_burstcost;
  float autocvar_g_balance_rifle_primary_damage;
  float autocvar_g_balance_rifle_primary_force;
- float autocvar_g_balance_rifle_primary_headshotaddeddamage;
  float autocvar_g_balance_rifle_primary_lifetime;
  float autocvar_g_balance_rifle_primary_refire;
  float autocvar_g_balance_rifle_primary_shots;
@@@ -108,7 -109,6 +108,6 @@@ float autocvar_g_balance_rifle_secondar
  float autocvar_g_balance_rifle_secondary_burstcost;
  float autocvar_g_balance_rifle_secondary_damage;
  float autocvar_g_balance_rifle_secondary_force;
- float autocvar_g_balance_rifle_secondary_headshotaddeddamage;
  float autocvar_g_balance_rifle_secondary_lifetime;
  float autocvar_g_balance_rifle_secondary_reload;
  float autocvar_g_balance_rifle_secondary_refire;
@@@ -179,16 -179,6 +178,6 @@@ float autocvar_g_balance_crylink_second
  float autocvar_g_balance_crylink_secondary_spreadtype;
  float autocvar_g_balance_crylink_reload_ammo;
  float autocvar_g_balance_crylink_reload_time;
- float autocvar_g_balance_curse_empathy_minhealth;
- float autocvar_g_balance_curse_empathy_takedamage;
- float autocvar_g_balance_curse_slow_atkrate;
- float autocvar_g_balance_curse_slow_highspeed;
- float autocvar_g_balance_curse_venom_hpmod;
- float autocvar_g_balance_curse_venom_limitmod;
- float autocvar_g_balance_curse_venom_rotrate;
- float autocvar_g_balance_curse_vulner_takedamage;
- float autocvar_g_balance_curse_weak_damage;
- float autocvar_g_balance_curse_weak_force;
  float autocvar_g_balance_damagepush_speedfactor;
  float autocvar_g_balance_electro_combo_comboradius;
  float autocvar_g_balance_electro_combo_damage;
@@@ -594,26 -584,6 +583,6 @@@ float autocvar_g_balance_rocketlauncher
  float autocvar_g_balance_rocketlauncher_speedstart;
  float autocvar_g_balance_rocketlauncher_reload_ammo;
  float autocvar_g_balance_rocketlauncher_reload_time;
- float autocvar_g_balance_rune_defense_combo_takedamage;
- float autocvar_g_balance_rune_defense_takedamage;
- float autocvar_g_balance_rune_regen_combo_hpmod;
- float autocvar_g_balance_rune_regen_combo_limitmod;
- float autocvar_g_balance_rune_regen_combo_regenrate;
- float autocvar_g_balance_rune_regen_combo_rotrate;
- float autocvar_g_balance_rune_regen_hpmod;
- float autocvar_g_balance_rune_regen_limitmod;
- float autocvar_g_balance_rune_regen_regenrate;
- float autocvar_g_balance_rune_speed_atkrate;
- float autocvar_g_balance_rune_speed_combo_atkrate;
- float autocvar_g_balance_rune_speed_combo_highspeed;
- float autocvar_g_balance_rune_speed_highspeed;
- float autocvar_g_balance_rune_strength_combo_damage;
- float autocvar_g_balance_rune_strength_combo_force;
- float autocvar_g_balance_rune_strength_damage;
- float autocvar_g_balance_rune_strength_force;
- float autocvar_g_balance_rune_vampire_absorb;
- float autocvar_g_balance_rune_vampire_combo_absorb;
- float autocvar_g_balance_rune_vampire_maxhealth;
  float autocvar_g_balance_seeker_type;
  float autocvar_g_balance_seeker_flac_ammo;
  float autocvar_g_balance_seeker_flac_animtime;
@@@ -703,7 -673,6 +672,6 @@@ float autocvar_g_balance_uzi_burst_spre
  float autocvar_g_balance_uzi_first;
  float autocvar_g_balance_uzi_first_ammo;
  float autocvar_g_balance_uzi_first_damage;
- float autocvar_g_balance_uzi_first_headshotaddeddamage;
  float autocvar_g_balance_uzi_first_force;
  float autocvar_g_balance_uzi_first_refire;
  float autocvar_g_balance_uzi_first_spread;
@@@ -714,7 -683,6 +682,6 @@@ float autocvar_g_balance_uzi_spread_max
  float autocvar_g_balance_uzi_spread_min;
  float autocvar_g_balance_uzi_sustained_ammo;
  float autocvar_g_balance_uzi_sustained_damage;
- float autocvar_g_balance_uzi_sustained_headshotaddeddamage;
  float autocvar_g_balance_uzi_sustained_force;
  float autocvar_g_balance_uzi_sustained_refire;
  float autocvar_g_balance_uzi_sustained_spread;
@@@ -742,6 -710,8 +709,8 @@@ float autocvar_g_ca_point_leadlimit
  float autocvar_g_ca_point_limit;
  float autocvar_g_ca_round_timelimit;
  float autocvar_g_ca_spectate_enemies;
+ float autocvar_g_ca_teams;
+ float autocvar_g_ca_teams_override;
  float autocvar_g_ca_warmup;
  float autocvar_g_campaign;
  #define autocvar_g_campaign_forceteam cvar("g_campaign_forceteam")
@@@ -760,6 -730,7 +729,7 @@@ float autocvar_g_chat_flood_spl_team
  float autocvar_g_chat_flood_spl_tell;
  float autocvar_g_chat_nospectators;
  float autocvar_g_chat_teamcolors;
+ float autocvar_g_chat_tellprivacy;
  float autocvar_g_ctf_allow_vehicle_carry;
  float autocvar_g_ctf_allow_vehicle_touch;
  float autocvar_g_ctf_throw;
@@@ -785,7 -756,6 +755,6 @@@ float autocvar_g_ctf_pass_request
  float autocvar_g_ctf_pass_turnrate;
  float autocvar_g_ctf_pass_timelimit;
  float autocvar_g_ctf_pass_velocity;
- float autocvar_g_ctf_captimerecord_always;
  float autocvar_g_ctf_dynamiclights;
  string autocvar_g_ctf_flag_blue_model;
  float autocvar_g_ctf_flag_blue_skin;
@@@ -795,7 -765,6 +764,6 @@@ float autocvar_g_ctf_flag_dropped_waypo
  float autocvar_g_ctf_flag_dropped_floatinwater;
  float autocvar_g_ctf_flag_glowtrails;
  float autocvar_g_ctf_flag_health;
- float autocvar_g_ctf_flag_pickup_verbosename;
  string autocvar_g_ctf_flag_red_model;
  float autocvar_g_ctf_flag_red_skin;
  float autocvar_g_ctf_flag_return_time;
@@@ -848,11 -817,15 +816,15 @@@ string autocvar_g_forced_team_pink
  string autocvar_g_forced_team_red;
  string autocvar_g_forced_team_yellow;
  float autocvar_g_freezetag_frozen_force;
+ float autocvar_g_freezetag_frozen_maxtime;
  float autocvar_g_freezetag_point_leadlimit;
  float autocvar_g_freezetag_point_limit;
  float autocvar_g_freezetag_revive_extra_size;
  float autocvar_g_freezetag_revive_speed;
  float autocvar_g_freezetag_revive_clearspeed;
+ float autocvar_g_freezetag_round_timelimit;
+ float autocvar_g_freezetag_teams;
+ float autocvar_g_freezetag_teams_override;
  float autocvar_g_freezetag_warmup;
  #define autocvar_g_friendlyfire cvar("g_friendlyfire")
  #define autocvar_g_friendlyfire_virtual cvar("g_friendlyfire_virtual")
@@@ -895,8 -868,8 +867,8 @@@ float autocvar_g_keyhunt_teams
  float autocvar_g_keyhunt_teams_override;
  float autocvar_g_lms_campcheck_damage;
  float autocvar_g_lms_campcheck_distance;
+ float autocvar_g_lms_extra_lives;
  float autocvar_g_lms_campcheck_interval;
- string autocvar_g_lms_campcheck_message;
  float autocvar_g_lms_join_anytime;
  float autocvar_g_lms_last_join;
  #define autocvar_g_lms_lives_override cvar("g_lms_lives_override")
@@@ -991,21 -964,6 +963,6 @@@ float autocvar_g_respawn_ghosts
  float autocvar_g_respawn_ghosts_maxtime;
  float autocvar_g_respawn_ghosts_speed;
  float autocvar_g_respawn_waves;
- float autocvar_g_runematch_allow_same;
- float autocvar_g_runematch_drop_runes_max;
- float autocvar_g_runematch_fixedspawns;
- float autocvar_g_runematch_frags_killed_runeholder;
- float autocvar_g_runematch_frags_killedby_runeholder;
- float autocvar_g_runematch_frags_norune;
- float autocvar_g_runematch_point_leadlimit;
- #define autocvar_g_runematch_point_limit cvar("g_runematch_point_limit")
- float autocvar_g_runematch_pointamt;
- float autocvar_g_runematch_pointrate;
- float autocvar_g_runematch_respawntime;
- float autocvar_g_runematch_rune_alpha;
- float autocvar_g_runematch_rune_color_strength;
- float autocvar_g_runematch_rune_effects;
- float autocvar_g_runematch_shuffletime;
  float autocvar_g_running_guns;
  float autocvar_g_shootfromcenter;
  float autocvar_g_shootfromclient;
@@@ -1017,7 -975,6 +974,6 @@@ float autocvar_g_spawn_useallspawns
  float autocvar_g_spawnpoints_auto_move_out_of_solid;
  #define autocvar_g_spawnshieldtime cvar("g_spawnshieldtime")
  float autocvar_g_spawnsound;
- float autocvar_g_start_delay;
  #define autocvar_g_start_weapon_laser cvar("g_start_weapon_laser")
  float autocvar_g_tdm_team_spawns;
  float autocvar_g_tdm_teams;
@@@ -1166,13 -1123,10 +1122,10 @@@ float autocvar_sv_eventlog_files_counte
  string autocvar_sv_eventlog_files_nameprefix;
  string autocvar_sv_eventlog_files_namesuffix;
  float autocvar_sv_eventlog_files_timestamps;
- float autocvar_sv_fraginfo;
- float autocvar_sv_fraginfo_handicap;
- float autocvar_sv_fraginfo_ping;
- float autocvar_sv_fraginfo_stats;
  float autocvar_sv_friction;
  float autocvar_sv_friction_on_land;
  float autocvar_sv_gameplayfix_q2airaccelerate;
+ float autocvar_sv_gentle;
  #define autocvar_sv_gravity cvar("sv_gravity")
  string autocvar_sv_intermission_cdtrack;
  string autocvar_sv_jumpspeedcap_max;
@@@ -1188,7 -1142,6 +1141,6 @@@ float autocvar_sv_maxairspeed
  float autocvar_sv_maxairstrafespeed;
  float autocvar_sv_maxspeed;
  string autocvar_sv_motd;
- float autocvar_sv_player_jumpanim_minfall;
  float autocvar_sv_precacheplayermodels;
  float autocvar_sv_precacheweapons;
  float autocvar_sv_q3acompat_machineshotgunswap;
@@@ -1256,7 -1209,6 +1208,6 @@@ float autocvar_welcome_message_time
  float autocvar_sv_gameplayfix_gravityunaffectedbyticrate;
  float autocvar_g_trueaim_minrange;
  float autocvar_g_debug_defaultsounds;
- float autocvar_g_loituma;
  float autocvar_g_grab_range;
  float autocvar_g_sandbox_info;
  float autocvar_g_sandbox_readonly;
@@@ -1277,3 -1229,7 +1228,7 @@@ float autocvar_physics_ode
  float autocvar_g_physical_items;
  float autocvar_g_physical_items_damageforcescale;
  float autocvar_g_physical_items_reset;
+ float autocvar_g_touchexplode_radius;
+ float autocvar_g_touchexplode_damage;
+ float autocvar_g_touchexplode_edgedamage;
+ float autocvar_g_touchexplode_force;
index ce7fb8194a0268b3394f4260d02397e55613518e,a3078c4e43588bc64bbbeef1c2a09e490a4af928..a54874786cf6df38f2f87cbf267ba88970d5fc79
@@@ -203,25 -203,6 +203,6 @@@ void havocbot_goalrating_enemyplayers(f
  // choose a role according to the situation
  void havocbot_role_dm();
  
- //DOM:
- //go to best items, or control points you don't own
- void havocbot_role_dom()
- {
-       if(self.deadflag != DEAD_NO)
-               return;
-       if (self.bot_strategytime < time)
-       {
-               self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
-               navigation_goalrating_start();
-               havocbot_goalrating_controlpoints(10000, self.origin, 15000);
-               havocbot_goalrating_items(8000, self.origin, 8000);
-               //havocbot_goalrating_enemyplayers(3000, self.origin, 2000);
-               //havocbot_goalrating_waypoints(1, self.origin, 1000);
-               navigation_goalrating_end();
-       }
- }
  //DM:
  //go to best items
  void havocbot_role_dm()
@@@ -284,25 -265,20 +265,18 @@@ void havocbot_chooserole_race(
        self.havocbot_role = havocbot_role_race;
  }
  
- void havocbot_chooserole_dom()
- {
-       self.havocbot_role = havocbot_role_dom;
- }
  void havocbot_chooserole()
  {
        dprint("choosing a role...\n");
        self.bot_strategytime = 0;
        if (MUTATOR_CALLHOOK(HavocBot_ChooseRule))
                return;
-       else if (g_domination)
-               havocbot_chooserole_dom();
        else if (g_keyhunt)
                havocbot_chooserole_kh();
        else if (g_race || g_cts)
                havocbot_chooserole_race();
        else if (g_onslaught)
                havocbot_chooserole_ons();
 -      else if (g_assault)
 -              havocbot_chooserole_ast();
        else // assume anything else is deathmatch
                havocbot_chooserole_dm();
  }
index 6c05b534d18cae4fcb64c40d8c756d74be5fce9e,2f9c0d8312fae7091b9570070db75e7b405a71c8..075280c264e2094c8ecd40785ad946c00736dec2
@@@ -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)
@@@ -293,7 -277,7 +277,7 @@@ entity SelectSpawnPoint (float anypoint
        else
        {
                float mindist;
-               if (arena_roundbased && !g_ca)
+               if (g_arena && arena_roundbased)
                        mindist = 800;
                else
                        mindist = 100;
@@@ -401,16 -385,34 +385,34 @@@ void PutObserverInServer (void
                WriteEntity(MSG_ONE, self);
        }
  
-       DropAllRunes(self);
+       if(g_lms)
+       {
+               // Only if the player cannot play at all
+               if(PlayerScore_Add(self, SP_LMS_RANK, 0) == 666)
+                       self.frags = FRAGS_SPECTATOR;
+               else
+                       self.frags = FRAGS_LMS_LOSER;
+       }
+       else 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;
        MUTATOR_CALLHOOK(MakePlayerObserver);
  
        minstagib_stop_countdown(self);
  
        Portal_ClearAll(self);
+       
        if(self.alivetime)
        {
-               PlayerStats_Event(self, PLAYERSTATS_ALIVETIME, time - self.alivetime);
+               if(!inWarmupStage)
+                       PlayerStats_Event(self, PLAYERSTATS_ALIVETIME, time - self.alivetime);
                self.alivetime = 0;
        }
  
        if not(g_ca)  // don't reset teams when moving a ca player to the spectators
                self.team = -1;  // move this as it is needed to log the player spectating in eventlog
  
-       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");
-                       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");
+       if(self.killcount != -666)
+       {
+               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_SPECTATE, self.netname);
  
                if(self.just_joined == FALSE) {
                        LogTeamchange(self.playerid, -1, 4);
        self.pauseregen_finished = 0;
        self.damageforcescale = 0;
        self.death_time = 0;
+       self.respawn_flags = 0;
        self.respawn_time = 0;
+       self.stat_respawn_time = 0;
        self.alpha = 0;
        self.scale = 0;
        self.fade_time = 0;
        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;
        self.punchvector = '0 0 0';
        self.oldvelocity = self.velocity;
        self.fire_endtime = -1;
-       if(g_arena)
-       {
-               if(self.version_mismatch)
-               {
-                       Spawnqueue_Unmark(self);
-                       Spawnqueue_Remove(self);
-               }
-               else
-               {
-                       Spawnqueue_Insert(self);
-               }
-       }
-       else if(g_lms)
-       {
-               // Only if the player cannot play at all
-               if(PlayerScore_Add(self, SP_LMS_RANK, 0) == 666)
-                       self.frags = FRAGS_SPECTATOR;
-               else
-                       self.frags = FRAGS_LMS_LOSER;
-       }
-       else if(g_ca)
-       {
-               if(self.caplayer)
-                       self.frags = FRAGS_LMS_LOSER;
-               else
-                       self.frags = FRAGS_SPECTATOR;
-       }
-       else
-               self.frags = FRAGS_SPECTATOR;
  }
  
  .float model_randomizer;
@@@ -554,7 -522,7 +522,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
@@@ -643,11 -599,7 +599,7 @@@ Called when a client spawns in the serv
  void PutClientInServer (void)
  {
        if(clienttype(self) == CLIENTTYPE_BOT)
-       {
                self.classname = "player";
-               if(g_ca)
-                       self.caplayer = 1;
-       }
        else if(clienttype(self) == CLIENTTYPE_REAL)
        {
                msg_entity = self;
                        self.classname = "observer";
        }
  
-       if((g_arena && !self.spawned) || (g_ca && !allowed_to_spawn))
-               self.classname = "observer";
+       MUTATOR_CALLHOOK(PutClientInServer);
  
        if(gameover)
                self.classname = "observer";
  
-       if(self.classname == "player" && (!g_ca || (g_ca && allowed_to_spawn))) {
+       if(self.classname == "player") {
                entity spot, oldself;
                float j;
  
                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.damageforcescale = 2;
                self.death_time = 0;
+               self.respawn_flags = 0;
                self.respawn_time = 0;
+               self.stat_respawn_time = 0;
                self.scale = 0;
                self.fade_time = 0;
                self.pain_frame = 0;
  
                self.metertime = 0;
  
-               self.runes = 0;
                self.deadflag = DEAD_NO;
  
                self.angles = spot.angles;
                self.lastteleporttime = time; // prevent insane speeds due to changing origin
          self.hud = HUD_NORMAL;
  
-               if(g_arena)
-               {
-                       Spawnqueue_Remove(self);
-                       Spawnqueue_Mark(self);
-               }
-               else if(g_ca)
-                       self.caplayer = 1;
                self.event_damage = PlayerDamage;
  
                self.bot_attack = TRUE;
  
                //stuffcmd(self, "chase_active 0");
                //stuffcmd(self, "set viewsize $tmpviewsize \n");
 -
 -              if(g_assault) {
 -                      if(self.team == assault_attacker_team)
 -                              Send_Notification(NOTIF_TEAM, self, MSG_CENTER, CENTER_ASSAULT_ATTACKING);
 -                      else
 -                              Send_Notification(NOTIF_TEAM, self, MSG_CENTER, CENTER_ASSAULT_DEFENDING);
 -              }
--
++              
                target_voicescript_clear(self);
  
                // reset fields the weapons may use
                self.weaponname = "";
                self.switchingweapon = 0;
  
-               if(!self.alivetime)
-                       self.alivetime = time;
+               if(!inWarmupStage)
+                       if(!self.alivetime)
+                               self.alivetime = time;
  
                antilag_clear(self);
  
@@@ -1062,14 -1013,13 +1006,13 @@@ void ClientKill_Now_TeamChange(
        }
        else if(self.killindicator_teamchange == -2)
        {
-               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
                SV_ChangeTeam(self.killindicator_teamchange - 1);
+       self.killindicator_teamchange = 0;
  }
  
  void ClientKill_Now()
@@@ -1131,7 -1081,7 +1074,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;
@@@ -1216,28 -1166,28 +1159,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);
                }
        }
  
  
  void ClientKill (void)
  {
-       if (gameover)
-               return;
+       if(gameover) return;
+       if(self.player_blocked) return;
+       if(self.freezetag_frozen) return;
  
-       if((g_arena || g_ca) && ((champion && champion.classname == "player" && player_count > 1) || player_count == 1)) // don't allow a kill in this case either
-       {
-               // do nothing
-       }
-     else if(self.freezetag_frozen)
-     {
-         // do nothing
-     }
-       else
-               ClientKill_TeamChange(0);
+       ClientKill_TeamChange(0);
  }
  
  void CTS_ClientKill (entity e) // silent version of ClientKill, used when player finishes a CTS run. Useful to prevent cheating by running back to the start line and starting out with more speed
@@@ -1279,7 -1221,7 +1214,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
@@@ -1328,7 -1270,6 +1263,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);
@@@ -1348,7 -1289,7 +1282,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";
  
        race_PreSpawnObserver();
  
-       //if(g_domination)
-       //      dom_player_join_team(self);
        // identify the right forced team
        if(autocvar_g_campaign)
        {
                {
                        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")
  
        JoinBestTeam(self, FALSE, FALSE); // if the team number is valid, keep it
  
-       if((autocvar_sv_spectate == 1 && !g_lms) || autocvar_g_campaign || self.team_forced < 0) {
+       if((autocvar_sv_spectate == 1) || autocvar_g_campaign || self.team_forced < 0) {
                self.classname = "observer";
        } else {
                if(teamplay)
  
        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?
        else
                stuffcmd(self, "set _teams_available 0\n");
  
-       if(g_arena || g_ca)
-       {
-               self.classname = "observer";
-               if(g_arena)
-                       Spawnqueue_Insert(self);
-       }
        attach_entcs();
  
        bot_relinkplayerlist();
        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_bugrigs || WEPSET_EQ_AW(g_weaponarena_weapons, WEP_TUBA))
-                       stuffcmd(self, "cl_cmd settemp chase_active 1\n");
-       }
-       if(g_lms)
-       {
-               if(PlayerScore_Add(self, SP_LMS_LIVES, LMS_NewPlayerLives()) <= 0)
+               if(!autocvar_g_campaign)
                {
-                       PlayerScore_Add(self, SP_LMS_RANK, 666);
-                       self.frags = FRAGS_SPECTATOR;
+                       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");
        }
  
        if(!sv_foginterval && world.fog != "")
        else if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca) // teamnagger is currently bad for ca
                send_CSQC_teamnagger();
  
-       if (g_domination)
-               set_dom_state(self);
        CheatInitClient();
  
-       if(!autocvar_g_campaign)
-               Send_CSQC_Centerprint_Generic(self, CPID_MOTD, getwelcomemessage(), autocvar_welcome_message_time, 0);
        CSQCMODEL_AUTOINIT();
  
        self.model_randomizer = random();
-     
-     if(clienttype(self) != CLIENTTYPE_REAL)
-         return;
-         
-     sv_notice_join();
-     
-     MUTATOR_CALLHOOK(ClientConnect);
+       if(clienttype(self) == CLIENTTYPE_REAL)
+               sv_notice_join();
+       MUTATOR_CALLHOOK(ClientConnect);
  }
  /*
  =============
@@@ -1623,10 -1541,9 +1534,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);
  
        bot_relinkplayerlist();
  
-       if(g_arena)
-       {
-               Spawnqueue_Unmark(self);
-               Spawnqueue_Remove(self);
-       }
        accuracy_free(self);
        ClientData_Detach();
        PlayerScore_Detach(self);
@@@ -1795,7 -1706,8 +1699,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
                        {
@@@ -1989,32 -1911,6 +1904,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;
        limita = limita * limit_mod;
        //limitf = limitf * limit_mod;
  
-       if(g_lms && g_ca)
+       if(g_ca)
                rot_mod = 0;
  
        if (!g_minstagib && !g_ca && (!g_lms || autocvar_g_lms_regenerate))
@@@ -2150,7 -2046,6 +2039,6 @@@ void SpectateCopy(entity spectatee) 
        self.dmg_inflictor = spectatee.dmg_inflictor;
        self.v_angle = spectatee.v_angle;
        self.angles = spectatee.v_angle;
-       self.stat_respawn_time = spectatee.stat_respawn_time;
        if(!self.BUTTON_USE)
                self.fixangle = TRUE;
        setorigin(self, spectatee.origin);
@@@ -2294,55 -2189,40 +2182,40 @@@ 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(self.caplayer)
+               return;
+       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;
+                               { campaign_bots_may_start = 1; }
  
-                       PutClientInServer();
-                       if(self.classname == "player")
-                               bprint ("^4", self.netname, "^4 is playing now\n");
-                       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
+                       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);
        }
  }
  
@@@ -2377,8 -2257,9 +2250,9 @@@ float nJoinAllowed(entity ignore) 
                return maxclients - totalClients;
  
        float currentlyPlaying = 0;
-       FOR_EACH_REALPLAYER(e)
-               currentlyPlaying += 1;
+       FOR_EACH_REALCLIENT(e)
+               if(e.classname == "player" || e.caplayer == 1)
+                       currentlyPlaying += 1;
  
        if(currentlyPlaying < autocvar_g_maxplayers)
                return min(maxclients - totalClients, autocvar_g_maxplayers - currentlyPlaying);
  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;
  }
  
@@@ -2522,8 -2411,6 +2404,6 @@@ void PlayerUseKey(
        MUTATOR_CALLHOOK(PlayerUseKey);
  }
  
- .float touchexplode_time;
  /*
  =============
  PlayerPreThink
@@@ -2539,14 -2426,10 +2419,10 @@@ void PlayerPreThink (void
        WarpZone_PlayerPhysics_FixVAngle();
  
        self.stat_game_starttime = game_starttime;
+       self.stat_round_starttime = round_starttime;
        self.stat_allow_oldnexbeam = autocvar_g_allow_oldnexbeam;
        self.stat_leadlimit = autocvar_leadlimit;
  
-       if(g_arena || (g_ca && !allowed_to_spawn))
-               self.stat_respawn_time = 0;
-       else
-               self.stat_respawn_time = self.respawn_time;
        if(frametime)
        {
                // physics frames: update anticheat stuff
                                        {
                                                // 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);
  
                if (self.deadflag != DEAD_NO)
                {
-                       float button_pressed, force_respawn;
                        if(self.personal && g_race_qualifying)
                        {
                                if(time > self.respawn_time)
                                {
                                        self.respawn_time = time + 1; // only retry once a second
+                                       self.stat_respawn_time = self.respawn_time;
                                        respawn();
                                        self.impulse = 141;
                                }
                        }
                        else
                        {
+                               float button_pressed;
                                if(frametime)
                                        player_anim();
                                button_pressed = (self.BUTTON_ATCK || self.BUTTON_JUMP || self.BUTTON_ATCK2 || self.BUTTON_HOOK || self.BUTTON_USE);
-                               force_respawn = (g_lms || g_ca || g_cts || autocvar_g_forced_respawn);
+                               
                                if (self.deadflag == DEAD_DYING)
                                {
-                                       if(force_respawn)
+                                       if(self.respawn_flags & RESPAWN_FORCE)
                                                self.deadflag = DEAD_RESPAWNING;
                                        else if(!button_pressed)
                                                self.deadflag = DEAD_DEAD;
                                                respawn();
                                        }
                                }
                                ShowRespawnCountdown();
+                               if(self.respawn_flags & RESPAWN_SILENT)
+                                       self.stat_respawn_time = 0;
+                               else
+                                       self.stat_respawn_time = self.respawn_time;
                        }
  
                        // if respawning, invert stat_respawn_time to indicate this, the client translates it
  
                        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)
-               {
-                       vector dist;
-                       // calculate player movement (in 2 dimensions only, so jumping on one spot doesn't count as movement)
-                       dist = self.prevorigin - self.origin;
-                       dist_z = 0;
-                       self.lms_traveled_distance += fabs(vlen(dist));
-                       if((autocvar_g_campaign && !campaign_bots_may_start) || (time < game_starttime))
-                       {
-                               self.lms_nextcheck = time + autocvar_g_lms_campcheck_interval*2;
-                               self.lms_traveled_distance = 0;
-                       }
-                       if(time > self.lms_nextcheck)
-                       {
-                               //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);
-                                       // 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');
-                               }
-                               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)
                        {
@@@ -2942,18 -2789,6 +2782,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 ce90ef457eb1fbd3db4c22e60cc7c2360fed502a,d705f5d5e9fb9674c7cae4f91400d0a2cbdb60cb..311d156304c9dbd0c99835d8ab928515e8ddc6aa
@@@ -46,10 -46,22 +46,22 @@@ void Mutator_Remove(mutatorfunc_t func
  MUTATOR_HOOKABLE(MakePlayerObserver);
        // called when a player becomes observer, after shared setup
  
+ MUTATOR_HOOKABLE(PutClientInServer);
+       entity self; // client wanting to spawn
  MUTATOR_HOOKABLE(PlayerSpawn);
        entity spawn_spot; // spot that was used, or world
        // called when a player spawns as player, after shared setup, before his weapon is chosen (so items may be changed in here)
  
+ MUTATOR_HOOKABLE(reset_map_global);
+       // called in reset_map
+ MUTATOR_HOOKABLE(reset_map_players);
+       // called in reset_map
+ MUTATOR_HOOKABLE(ForbidPlayerScore_Clear);
+       // returns 1 if clearing player score shall not be allowed
  MUTATOR_HOOKABLE(ClientDisconnect);
        // called when a player disconnects
  
@@@ -59,6 -71,7 +71,7 @@@ MUTATOR_HOOKABLE(PlayerDies)
                entity frag_inflictor;
                entity frag_attacker;
                entity frag_target; // same as self
+               float frag_deathtype;
  
  MUTATOR_HOOKABLE(GiveFragsForKill);
        // called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill
@@@ -142,7 -155,7 +155,7 @@@ MUTATOR_HOOKABLE(PlayerDamage_SplitHeal
                float damage_save;
                
  MUTATOR_HOOKABLE(PlayerDamage_Calculate);
-       // called to adjust damage and force values which are applied to the player, used for e.g. strength damage/force multiplier or runematch runes
+       // called to adjust damage and force values which are applied to the player, used for e.g. strength damage/force multiplier
        // i'm not sure if I should change this around slightly (Naming of the entities, and also how they're done in g_damage).
        // INPUT:
                entity frag_attacker;
@@@ -235,10 -248,6 +248,10 @@@ MUTATOR_HOOKABLE(HelpMePing)
        // INPUT
        entity self; // the player who pressed impulse 33
        
 +MUTATOR_HOOKABLE(VehicleSpawn);
 +      // called when a vehicle initializes
 +      // return TRUE to remove the vehicle
 +      
  MUTATOR_HOOKABLE(VehicleEnter);
        // called when a player enters a vehicle
        // allows mutators to set special settings in this event
index 7d75706d7a699deadfc36406586fa880cd10e8ca,9c139f0e97d5042acdc076b7c03409fb135b2034..dab42bd65d8c39287701a4c3cffb3daf808f9609
@@@ -1,10 -1,13 +1,14 @@@
 +MUTATOR_DECLARATION(gamemode_assault);
+ MUTATOR_DECLARATION(gamemode_arena);
+ MUTATOR_DECLARATION(gamemode_ca);
  MUTATOR_DECLARATION(gamemode_keyhunt);
  MUTATOR_DECLARATION(gamemode_freezetag);
  MUTATOR_DECLARATION(gamemode_keepaway);
  MUTATOR_DECLARATION(gamemode_ctf);
  MUTATOR_DECLARATION(gamemode_nexball);
  MUTATOR_DECLARATION(gamemode_onslaught);
+ MUTATOR_DECLARATION(gamemode_domination);
+ MUTATOR_DECLARATION(gamemode_lms);
  
  MUTATOR_DECLARATION(mutator_dodging);
  MUTATOR_DECLARATION(mutator_invincibleprojectiles);
@@@ -15,5 -18,6 +19,6 @@@ MUTATOR_DECLARATION(mutator_spawn_near_
  MUTATOR_DECLARATION(mutator_physical_items);
  MUTATOR_DECLARATION(mutator_vampire);
  MUTATOR_DECLARATION(mutator_superspec);
+ MUTATOR_DECLARATION(mutator_touchexplode);
  
  MUTATOR_DECLARATION(sandbox);
diff --combined qcsrc/server/progs.src
index 27124892343be9bd2886949d9338fabc72f3fc7a,28736e6cdb279f2ff0ee8762b8520f18cc7018ba..b3cc22ddaa7a785c9a44472025a74e1b0cde3cb3
@@@ -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_assault.qh
+ mutators/gamemode_arena.qh
+ mutators/gamemode_ca.qh
  mutators/gamemode_ctf.qh
+ mutators/gamemode_domination.qh
  mutators/gamemode_keyhunt.qh // TODO fix this
  mutators/gamemode_keepaway.qh
  mutators/gamemode_nexball.qh 
+ mutators/gamemode_lms.qh
  mutators/mutator_dodging.qh
  
  //// tZork Turrets ////
@@@ -79,6 -88,8 +89,8 @@@ antilag.q
  
  playerdemo.qh
  
+ round_handler.qh
  // singleplayer stuff
  item_key.qh
  secret.qh
@@@ -95,8 -106,7 +107,7 @@@ g_subs.q
  
  g_tetris.qc
  
- runematch.qc
- arena.qc
+ //runematch.qc
  
  g_violence.qc
  g_damage.qc
@@@ -142,7 -152,7 +153,7 @@@ t_plats.q
  antilag.qc
  
  //ctf.qc
- domination.qc
//domination.qc
  //mode_onslaught.qc
  //nexball.qc
  g_hook.qc
@@@ -167,7 -177,7 +178,7 @@@ command/getreplies.q
  command/cmd.qc
  command/sv_cmd.qc
  
 -assault.qc
 +//assault.qc
  
  ipban.qc
  
@@@ -205,16 -215,21 +216,22 @@@ anticheat.q
  cheats.qc
  playerstats.qc
  
+ round_handler.qc
  ../common/explosion_equation.qc
  
  mutators/base.qc
 +mutators/gamemode_assault.qc
+ mutators/gamemode_arena.qc
+ mutators/gamemode_ca.qc
  mutators/gamemode_ctf.qc
+ mutators/gamemode_domination.qc
  mutators/gamemode_freezetag.qc
  mutators/gamemode_keyhunt.qc
  mutators/gamemode_keepaway.qc
  mutators/gamemode_nexball.qc
  mutators/gamemode_onslaught.qc
+ mutators/gamemode_lms.qc
  mutators/mutator_invincibleproj.qc
  mutators/mutator_new_toys.qc
  mutators/mutator_nix.qc
@@@ -225,6 -240,7 +242,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
index 66ba48145338425295501e0a232fbe002d9307b1,3f39f455c56c6f70d0813564e229b9d8d83c87aa..d60f4563c1cfdbf937982c9046ed66cc2f264423
@@@ -44,37 -44,6 +44,6 @@@ void ScoreRules_generic(
        ScoreRules_basics_end();
  }
  
- // g_domination
- #define ST_DOM_TICKS 1
- #define SP_DOM_TICKS 4
- #define SP_DOM_TAKES 5
- void ScoreRules_dom()
- {
-       float sp_domticks, sp_score;
-       sp_score = sp_domticks = 0;
-       if(autocvar_g_domination_disable_frags)
-               sp_domticks = SFL_SORT_PRIO_PRIMARY;
-       else
-               sp_score = SFL_SORT_PRIO_PRIMARY;
-       CheckAllowedTeams(world);
-       ScoreRules_basics(((c4>=0) ? 4 : (c3>=0) ? 3 : 2), sp_score, sp_score, TRUE);
-       ScoreInfo_SetLabel_TeamScore  (ST_DOM_TICKS,    "ticks",     sp_domticks);
-       ScoreInfo_SetLabel_PlayerScore(SP_DOM_TICKS,    "ticks",     sp_domticks);
-       ScoreInfo_SetLabel_PlayerScore(SP_DOM_TAKES,    "takes",     0);
-       ScoreRules_basics_end();
- }
- // LMS stuff
- #define SP_LMS_LIVES 4
- #define SP_LMS_RANK 5
- void ScoreRules_lms()
- {
-       ScoreRules_basics(0, 0, 0, FALSE);
-       ScoreInfo_SetLabel_PlayerScore(SP_LMS_LIVES,    "lives",     SFL_SORT_PRIO_SECONDARY);
-       ScoreInfo_SetLabel_PlayerScore(SP_LMS_RANK,     "rank",      SFL_LOWER_IS_BETTER | SFL_RANK | SFL_SORT_PRIO_PRIMARY | SFL_ALLOW_HIDE);
-       ScoreRules_basics_end();
- }
  // Key hunt stuff
  #define ST_KH_CAPS 1
  #define SP_KH_CAPS 4
@@@ -99,9 -68,8 +68,8 @@@ void ScoreRules_kh(float teams
  // Race stuff
  #define ST_RACE_LAPS 1
  #define SP_RACE_LAPS 4
- #define SP_RACE_FASTEST 5
  #define SP_RACE_TIME 5
//#define SP_RACE_RANK 6
#define SP_RACE_FASTEST 6
  void ScoreRules_race()
  {
        ScoreRules_basics(race_teams, 0, 0, FALSE);
                ScoreInfo_SetLabel_TeamScore(  ST_RACE_LAPS,    "laps",      SFL_SORT_PRIO_PRIMARY);
                ScoreInfo_SetLabel_PlayerScore(SP_RACE_LAPS,    "laps",      SFL_SORT_PRIO_PRIMARY);
                ScoreInfo_SetLabel_PlayerScore(SP_RACE_TIME,    "time",      SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER | SFL_TIME);
-               //ScoreInfo_SetLabel_PlayerScore(SP_RACE_RANK,    "rank",      SFL_LOWER_IS_BETTER | SFL_RANK | SFL_ALLOW_HIDE);
+               ScoreInfo_SetLabel_PlayerScore(SP_RACE_FASTEST, "fastest",   SFL_LOWER_IS_BETTER | SFL_TIME);
        }
        else if(g_race_qualifying)
        {
        }
        else
        {
-               //ScoreInfo_SetLabel_TeamScore(  ST_RACE_LAPS,    "laps",      0);
                ScoreInfo_SetLabel_PlayerScore(SP_RACE_LAPS,    "laps",      SFL_SORT_PRIO_PRIMARY);
                ScoreInfo_SetLabel_PlayerScore(SP_RACE_TIME,    "time",      SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER | SFL_TIME);
+               ScoreInfo_SetLabel_PlayerScore(SP_RACE_FASTEST, "fastest",   SFL_LOWER_IS_BETTER | SFL_TIME);
        }
        ScoreRules_basics_end();
  }
  
 -// Assault stuff
 -#define ST_ASSAULT_OBJECTIVES 1
 -#define SP_ASSAULT_OBJECTIVES 4
 -void ScoreRules_assault()
 -{
 -      ScoreRules_basics(2, SFL_SORT_PRIO_SECONDARY, SFL_SORT_PRIO_SECONDARY, TRUE);
 -      ScoreInfo_SetLabel_TeamScore(  ST_ASSAULT_OBJECTIVES,    "objectives",      SFL_SORT_PRIO_PRIMARY);
 -      ScoreInfo_SetLabel_PlayerScore(SP_ASSAULT_OBJECTIVES,    "objectives",      SFL_SORT_PRIO_PRIMARY);
 -      ScoreRules_basics_end();
 -}
 -
  // Nexball stuff
  #define ST_NEXBALL_GOALS 1
  #define SP_NEXBALL_GOALS 4
diff --combined qcsrc/server/teamplay.qc
index f2aaf258bfffd3850382b4f2000b7d8c0ed09069,3d7970297fd6f010923d73b020bb4fa13220fa1d..16236dd16ba7d93fb52210553efe8d0ca89a5078
@@@ -13,47 -13,6 +13,6 @@@ void TeamchangeFrags(entity e
        PlayerScore_Clear(e);
  }
  
- vector TeamColor(float teem)
- {
-       switch(teem)
-       {
-               case COLOR_TEAM1:
-                       return '1 0.0625 0.0625';
-               case COLOR_TEAM2:
-                       return '0.0625 0.0625 1';
-               case COLOR_TEAM3:
-                       return '1 1 0.0625';
-               case COLOR_TEAM4:
-                       return '1 0.0625 1';
-               default:
-                       return '1 1 1';
-       }
- }
- string TeamName(float t)
- {
-       return strcat(Team_ColorName(t), " Team");
- }
- string ColoredTeamName(float t)
- {
-       return strcat(Team_ColorCode(t), Team_ColorName(t), " Team^7");
- }
- string TeamNoName(float t)
- {
-       // fixme: Search for team entities and get their .netname's!
-       if(t == 1)
-               return "Red Team";
-       if(t == 2)
-               return "Blue Team";
-       if(t == 3)
-               return "Yellow Team";
-       if(t == 4)
-               return "Pink Team";
-       return "Neutral Team";
- }
- void dom_init();
- void runematch_init();
  void tdm_init();
  void entcs_init();
  
@@@ -134,7 -93,7 +93,7 @@@ void InitGameplayMode(
                ActivateTeamplay();
                fraglimit_override = autocvar_g_domination_point_limit;
                leadlimit_override = autocvar_g_domination_point_leadlimit;
-               dom_init();
+               MUTATOR_ADD(gamemode_domination);
                have_team_spawns = -1; // request team spawns
        }
  
                have_team_spawns = -1; // request team spawns
        }
  
-       if(g_runematch)
-       {
-               // ActivateTeamplay();
-               fraglimit_override = autocvar_g_runematch_point_limit;
-               leadlimit_override = autocvar_g_runematch_point_leadlimit;
-               runematch_init();
-       }
        if(g_lms)
        {
                fraglimit_override = autocvar_g_lms_lives_override;
                leadlimit_override = 0; // not supported by LMS
                if(fraglimit_override == 0)
                        fraglimit_override = -1;
-               lms_lowest_lives = 9999;
-               lms_next_place = 0;
-               ScoreRules_lms();
+               MUTATOR_ADD(gamemode_lms);
        }
  
        if(g_arena)
        {
                fraglimit_override = autocvar_g_arena_point_limit;
                leadlimit_override = autocvar_g_arena_point_leadlimit;
-               maxspawned = autocvar_g_arena_maxspawned;
-               if(maxspawned < 2)
-                       maxspawned = 2;
-               arena_roundbased = autocvar_g_arena_roundbased;
+               MUTATOR_ADD(gamemode_arena);
        }
  
        if(g_ca)
                ActivateTeamplay();
                fraglimit_override = autocvar_g_ca_point_limit;
                leadlimit_override = autocvar_g_ca_point_leadlimit;
-               precache_sound("ctf/red_capture.wav");
-               precache_sound("ctf/blue_capture.wav");
+               MUTATOR_ADD(gamemode_ca);
        }
        if(g_keyhunt)
        {
                ActivateTeamplay();
        if(g_assault)
        {
                ActivateTeamplay();
 -              ScoreRules_assault();
 +              MUTATOR_ADD(gamemode_assault);
                have_team_spawns = -1; // request team spawns
        }
  
@@@ -417,13 -363,13 +363,13 @@@ void SetPlayerTeam(entity pl, float t, 
        float _color;
  
        if(t == 4)
-               _color = COLOR_TEAM4 - 1;
+               _color = NUM_TEAM_4 - 1;
        else if(t == 3)
-               _color = COLOR_TEAM3 - 1;
+               _color = NUM_TEAM_3 - 1;
        else if(t == 2)
-               _color = COLOR_TEAM2 - 1;
+               _color = NUM_TEAM_2 - 1;
        else
-               _color = COLOR_TEAM1 - 1;
+               _color = NUM_TEAM_1 - 1;
  
        SetPlayerColors(pl,_color);
  
                LogTeamchange(pl.playerid, pl.team, 3);  // log manual team join
  
                if(!noprint)
-               bprint(pl.netname, "^7 has changed from ", TeamNoName(s), " to ", TeamNoName(t), "\n");
+               bprint(pl.netname, "^7 has changed from ", Team_NumberToColoredFullName(s), "^7 to ", Team_NumberToColoredFullName(t), "\n");
        }
  
  }
@@@ -453,10 -399,10 +399,10 @@@ void CheckAllowedTeams (entity for_whom
                head = findchain(classname, "onslaught_generator");
                while (head)
                {
-                       if (head.team == COLOR_TEAM1) c1 = 0;
-                       if (head.team == COLOR_TEAM2) c2 = 0;
-                       if (head.team == COLOR_TEAM3) c3 = 0;
-                       if (head.team == COLOR_TEAM4) c4 = 0;
+                       if (head.team == NUM_TEAM_1) c1 = 0;
+                       if (head.team == NUM_TEAM_2) c2 = 0;
+                       if (head.team == NUM_TEAM_3) c3 = 0;
+                       if (head.team == NUM_TEAM_4) c4 = 0;
                        head = head.chain;
                }
        }
                {
                        if(!(g_domination && head.netname == ""))
                        {
-                               if(head.team == COLOR_TEAM1)
+                               if(head.team == NUM_TEAM_1)
                                        c1 = 0;
-                               else if(head.team == COLOR_TEAM2)
+                               else if(head.team == NUM_TEAM_2)
                                        c2 = 0;
-                               else if(head.team == COLOR_TEAM3)
+                               else if(head.team == NUM_TEAM_3)
                                        c3 = 0;
-                               else if(head.team == COLOR_TEAM4)
+                               else if(head.team == NUM_TEAM_4)
                                        c4 = 0;
                        }
                        head = find(head, classname, teament_name);
        }
  
        // if player has a forced team, ONLY allow that one
-       if(self.team_forced == COLOR_TEAM1 && c1 >= 0)
+       if(self.team_forced == NUM_TEAM_1 && c1 >= 0)
                c2 = c3 = c4 = -1;
-       else if(self.team_forced == COLOR_TEAM2 && c2 >= 0)
+       else if(self.team_forced == NUM_TEAM_2 && c2 >= 0)
                c1 = c3 = c4 = -1;
-       else if(self.team_forced == COLOR_TEAM3 && c3 >= 0)
+       else if(self.team_forced == NUM_TEAM_3 && c3 >= 0)
                c1 = c2 = c4 = -1;
-       else if(self.team_forced == COLOR_TEAM4 && c4 >= 0)
+       else if(self.team_forced == NUM_TEAM_4 && c4 >= 0)
                c1 = c2 = c3 = -1;
  }
  
@@@ -577,7 -523,7 +523,7 @@@ void GetTeamCounts(entity ignore
                                bvalue = value;
                        else
                                bvalue = 0;
-                       if(t == COLOR_TEAM1)
+                       if(t == NUM_TEAM_1)
                        {
                                if(c1 >= 0)
                                {
                                        cb1 = cb1 + bvalue;
                                }
                        }
-                       if(t == COLOR_TEAM2)
+                       if(t == NUM_TEAM_2)
                        {
                                if(c2 >= 0)
                                {
                                        cb2 = cb2 + bvalue;
                                }
                        }
-                       if(t == COLOR_TEAM3)
+                       if(t == NUM_TEAM_3)
                        {
                                if(c3 >= 0)
                                {
                                        cb3 = cb3 + bvalue;
                                }
                        }
-                       if(t == COLOR_TEAM4)
+                       if(t == NUM_TEAM_4)
                        {
                                if(c4 >= 0)
                                {
@@@ -770,13 -716,13 +716,13 @@@ float JoinBestTeam(entity pl, float onl
        // if he's not on a valid team, then let other code put him on the smallest team
        if(!forcebestteam)
        {
-               if(     c1 >= 0 && pl.team == COLOR_TEAM1)
+               if(     c1 >= 0 && pl.team == NUM_TEAM_1)
                        selectedteam = pl.team;
-               else if(c2 >= 0 && pl.team == COLOR_TEAM2)
+               else if(c2 >= 0 && pl.team == NUM_TEAM_2)
                        selectedteam = pl.team;
-               else if(c3 >= 0 && pl.team == COLOR_TEAM3)
+               else if(c3 >= 0 && pl.team == NUM_TEAM_3)
                        selectedteam = pl.team;
-               else if(c4 >= 0 && pl.team == COLOR_TEAM4)
+               else if(c4 >= 0 && pl.team == NUM_TEAM_4)
                        selectedteam = pl.team;
                else
                        selectedteam = -1;
                TeamchangeFrags(self);
                if(smallest == 1)
                {
-                       SetPlayerColors(pl, COLOR_TEAM1 - 1);
+                       SetPlayerColors(pl, NUM_TEAM_1 - 1);
                }
                else if(smallest == 2)
                {
-                       SetPlayerColors(pl, COLOR_TEAM2 - 1);
+                       SetPlayerColors(pl, NUM_TEAM_2 - 1);
                }
                else if(smallest == 3)
                {
-                       SetPlayerColors(pl, COLOR_TEAM3 - 1);
+                       SetPlayerColors(pl, NUM_TEAM_3 - 1);
                }
                else if(smallest == 4)
                {
-                       SetPlayerColors(pl, COLOR_TEAM4 - 1);
+                       SetPlayerColors(pl, NUM_TEAM_4 - 1);
                }
                else
                {
@@@ -845,21 -791,21 +791,21 @@@ void SV_ChangeTeam(float _color
        scolor = self.clientcolors & 0x0F;
        dcolor = _color & 0x0F;
  
-       if(scolor == COLOR_TEAM1 - 1)
+       if(scolor == NUM_TEAM_1 - 1)
                steam = 1;
-       else if(scolor == COLOR_TEAM2 - 1)
+       else if(scolor == NUM_TEAM_2 - 1)
                steam = 2;
-       else if(scolor == COLOR_TEAM3 - 1)
+       else if(scolor == NUM_TEAM_3 - 1)
                steam = 3;
-       else // if(scolor == COLOR_TEAM4 - 1)
+       else // if(scolor == NUM_TEAM_4 - 1)
                steam = 4;
-       if(dcolor == COLOR_TEAM1 - 1)
+       if(dcolor == NUM_TEAM_1 - 1)
                dteam = 1;
-       else if(dcolor == COLOR_TEAM2 - 1)
+       else if(dcolor == NUM_TEAM_2 - 1)
                dteam = 2;
-       else if(dcolor == COLOR_TEAM3 - 1)
+       else if(dcolor == NUM_TEAM_3 - 1)
                dteam = 3;
-       else // if(dcolor == COLOR_TEAM4 - 1)
+       else // if(dcolor == NUM_TEAM_4 - 1)
                dteam = 4;
  
        CheckAllowedTeams(self);
@@@ -948,13 -894,13 +894,13 @@@ void ShufflePlayerOutOfTeam (float sour
        }
  
        if(source_team == 1)
-               steam = COLOR_TEAM1;
+               steam = NUM_TEAM_1;
        else if(source_team == 2)
-               steam = COLOR_TEAM2;
+               steam = NUM_TEAM_2;
        else if(source_team == 3)
-               steam = COLOR_TEAM3;
+               steam = NUM_TEAM_3;
        else // if(source_team == 4)
-               steam = COLOR_TEAM4;
+               steam = NUM_TEAM_4;
  
        lowest_bot = world;
        lowest_bot_score = 999999999;
  
        if(selected.deadflag == DEAD_NO)
                Damage(selected, selected, selected, 100000, DEATH_AUTOTEAMCHANGE, selected.origin, '0 0 0');
-       centerprint(selected, strcat("You have been moved into a different team to improve team balance\nYou are now on: ", ColoredTeamName(selected.team)));
+       centerprint(selected, strcat("You have been moved into a different team to improve team balance\nYou are now on: ", Team_ColoredFullName(selected.team)));
  }
  
  // code from here on is just to support maps that don't have team entities
@@@ -1073,12 -1019,12 +1019,12 @@@ void tdm_spawnteams(
                numteams = autocvar_g_tdm_teams;
        numteams = bound(2, numteams, 4);
  
-       tdm_spawnteam("Red", COLOR_TEAM1-1);
-       tdm_spawnteam("Blue", COLOR_TEAM2-1);
+       tdm_spawnteam("Red", NUM_TEAM_1-1);
+       tdm_spawnteam("Blue", NUM_TEAM_2-1);
        if(numteams >= 3)
-               tdm_spawnteam("Yellow", COLOR_TEAM3-1);
+               tdm_spawnteam("Yellow", NUM_TEAM_3-1);
        if(numteams >= 4)
-               tdm_spawnteam("Pink", COLOR_TEAM4-1);
+               tdm_spawnteam("Pink", NUM_TEAM_4-1);
  }
  
  void tdm_delayedinit()
index 9627340faad9437de829f316697111eeaf1ede44,a79fcc62a4e2df25044e7d4a55e7647ecf4273f4..1b1ae3f647628626c24440d0b020ac8654909be1
@@@ -544,7 -544,7 +544,7 @@@ void vehicles_touch(
          if(vehicles_crushable(other))
          {
              if(vlen(self.velocity) != 0)
-                 Damage(other, self, self.owner, autocvar_g_vehicles_crush_dmg, DEATH_VHCRUSH, '0 0 0', normalize(other.origin - self.origin) * autocvar_g_vehicles_crush_force);
+                 Damage(other, self, self.owner, autocvar_g_vehicles_crush_dmg, DEATH_VH_CRUSH, '0 0 0', normalize(other.origin - self.origin) * autocvar_g_vehicles_crush_force);
  
              return; // Dont do selfdamage when hitting "soft targets".
          }
@@@ -1033,7 -1033,7 +1033,7 @@@ void vehicles_showwp(
      }
  
      if(teamplay && self.team)
-           rgb = TeamColor(self.team);
+           rgb = Team_ColorRGB(self.team);
      else
            rgb = '1 1 1';
      WaypointSprite_Spawn("vehicle", 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, TRUE, RADARICON_POWERUP, rgb);
@@@ -1268,14 -1268,14 +1268,14 @@@ float vehicle_initialize(string  net_na
      self.vehicle_exit        = exitfunc;
      self.vehicle_enter       = enterproc;
      self.PlayerPhysplug      = physproc;
-     self.event_damage        = vehicles_damage;
+     self.event_damage        = func_null;
      self.touch               = vehicles_touch;
      self.think               = vehicles_spawn;
      self.nextthink           = time;
      self.vehicle_respawntime = _respawntime;
      self.vehicle_spawn       = spawnproc;
      self.effects             = EF_NODRAW;
 -    if(g_assault || !autocvar_g_vehicles_delayspawn)
 +    if(!autocvar_g_vehicles_delayspawn)
          self.nextthink = time + 0.5;
      else
          self.nextthink = time + _respawntime + (random() * autocvar_g_vehicles_delayspawn_jitter);
      self.pos1 = self.origin;
      self.pos2 = self.angles;
      self.tur_head.team = self.team;
 +      
 +      if(MUTATOR_CALLHOOK(VehicleSpawn))
 +              return FALSE;
  
      return TRUE;
  }