]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge remote-tracking branch 'origin/master' into samual/notification_rewrite
authorSamual Lenks <samual@xonotic.org>
Tue, 1 Jan 2013 19:29:35 +0000 (14:29 -0500)
committerSamual Lenks <samual@xonotic.org>
Tue, 1 Jan 2013 19:29:35 +0000 (14:29 -0500)
21 files changed:
1  2 
commands.cfg
qcsrc/client/Main.qc
qcsrc/client/View.qc
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/hud.qc
qcsrc/client/main.qh
qcsrc/client/miscfunctions.qc
qcsrc/common/util.qh
qcsrc/menu/progs.src
qcsrc/server/autocvars.qh
qcsrc/server/bot/bot.qc
qcsrc/server/cl_client.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/gamemode_ctf.qc
qcsrc/server/mutators/gamemode_nexball.qc
qcsrc/server/w_hagar.qc
qcsrc/server/w_seeker.qc

diff --combined commands.cfg
index 33e8e42cfc0781b866263350767f22d83cc6814a,44fa671bd7f88e4ace9f1c4be2cf0e3929ad1542..0aece8a628129a88a898cef037fc4c75034f6224
@@@ -52,11 -52,10 +52,11 @@@ alias who                  "qc_cmd_svcm
  
  // generic commands (across all programs)
  alias addtolist            "qc_cmd_svmenu addtolist            ${* ?}" // Add a string to a cvar
 -alias qc_curl              "qc_cmd_svmenu curl                 ${* ?}" // curl requests
  alias dumpcommands         "qc_cmd_svmenu dumpcommands         ${* ?}" // Dump all commands on the program to *_cmd_dump.txt
 +alias dumpnotifs           "qc_cmd_svmenu dumpnotifs           ${* ?}" // Dump all notifications into notifications_dump.txt
  alias maplist              "qc_cmd_svmenu maplist              ${* ?}" // Automatic control of maplist
 -alias nextframe            "qc_cmd_svmenu nextframe            ${* ?}" // do something next frame
 +alias nextframe            "qc_cmd_svmenu nextframe            ${* ?}" // Execute the given command next frame of this VM
 +alias qc_curl              "qc_cmd_svmenu qc_curl              ${* ?}" // Queries a URL
  alias removefromlist       "qc_cmd_svmenu removefromlist       ${* ?}" // Remove a string from a cvar
  alias rpn                  "qc_cmd_svmenu rpn                  ${* ?}" // RPN calculator
  //alias settemp            "qc_cmd_svmenu settemp              ${* ?}" // Temporarily set a value to a cvar which is restored later
@@@ -289,7 -288,7 +289,7 @@@ set sv_vote_command_restriction_movetop
  // =================================
  set sv_vote_call 1 "Allow users to call a vote for the commands in sv_vote_commands"
  set sv_vote_change 1 "Allow voters to change their mind after already voting"
- set sv_vote_commands "restart fraglimit chmap gotomap nextmap endmatch reducematchtime extendmatchtime allready kick cointoss movetoauto" "these commands can be voted"
+ set sv_vote_commands "restart fraglimit chmap gotomap nextmap endmatch reducematchtime extendmatchtime allready kick cointoss movetoauto shuffleteams" "these commands can be voted"
  set sv_vote_only_commands ""
  set sv_vote_master_commands "movetored movetoblue movetoyellow movetopink" "Extra commands which vote masters can execute by themselves, along with the normal sv_vote_commands." // maybe add kickban here (but then sv_vote_master 0)
  set sv_vote_master 1  "Allows the use of the vote master system"
@@@ -303,6 -302,7 +303,7 @@@ set sv_vote_wait 120       "a player can not 
  set sv_vote_stop 15   "a player can not call a vote again for this many seconds when he stopped this vote (e.g. to correct it)"
  set sv_vote_majority_factor 0.5       "What percentage of the PLAYERS constitute a majority? (Must be at least 0.5, recommended: 0.5)"
  set sv_vote_majority_factor_of_voted 0.5 "What percentage of the VOTERS constitute a majority too? (Must be at least 0.5, recommended: 0.5)"
+ set sv_vote_gamestart 0 "Allow voting during map change"
  // when disabled, don't allow game type changes "note: set these two equal to JUST support simple majorities"
  set sv_vote_override_mostrecent 0
  
diff --combined qcsrc/client/Main.qc
index 4eac3af0952a4c2fc580fc4abe6c5659445ab856,066f32ef6e44f394d2dc2775baf4ae9c648d0482..9abcea202bdb3840597d6bb75847e7ad994e0023
@@@ -120,7 -120,7 +120,7 @@@ void CSQC_Init(void
        draw_endBoldFont();
        menu_visible = FALSE;
        menu_show = menu_show_error;
-       menu_action = menu_sub_null;
+       menu_action = func_null;
  
        for(i = 0; i < 255; ++i)
                if(getplayerkeyvalue(i, "viewentity") == "")
        teams = Sort_Spawn();
        players = Sort_Spawn();
  
 -      GetTeam(COLOR_SPECTATOR, true); // add specs first
 +      GetTeam(FL_SPECTATOR, true); // add specs first
  
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
 -
 +      CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
 +      CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
 +      
        WaypointSprite_Load();
  
        // precaches
        turrets_precache();
      Announcer_Precache();
        Tuba_Precache();
+       CSQCPlayer_Precache();
        
        if(autocvar_cl_reticle)
        {
@@@ -261,16 -260,16 +262,16 @@@ float SetTeam(entity o, float Team
                switch(Team)
                {
                        case -1:
 -                      case COLOR_TEAM1:
 -                      case COLOR_TEAM2:
 -                      case COLOR_TEAM3:
 -                      case COLOR_TEAM4:
 +                      case FL_TEAM_1:
 +                      case FL_TEAM_2:
 +                      case FL_TEAM_3:
 +                      case FL_TEAM_4:
                                break;
                        default:
                                if(GetTeam(Team, false) == world)
                                {
                                        print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
 -                                      Team = COLOR_SPECTATOR;
 +                                      Team = FL_SPECTATOR;
                                }
                                break;
                }
                                if(GetTeam(Team, false) == world)
                                {
                                        print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
 -                                      Team = COLOR_SPECTATOR;
 +                                      Team = FL_SPECTATOR;
                                }
                                break;
                }
@@@ -400,7 -399,7 +401,7 @@@ float CSQC_InputEvent(float bInputType
        if (MapVote_InputEvent(bInputType, nPrimary, nSecondary))
                return true;
  
-       if(menu_visible)
+       if(menu_visible && menu_action)
                if(menu_action(bInputType, nPrimary, nSecondary))
                        return TRUE;
  
@@@ -794,6 -793,18 +795,18 @@@ void Ent_Remove(
        if(self.entremove)
                self.entremove();
  
+       if(self.skeletonindex)
+       {
+               skel_delete(self.skeletonindex);
+               self.skeletonindex = 0;
+       }
+       if(self.snd_looping > 0)
+       {
+               sound(self, self.snd_looping, "misc/null.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+               self.snd_looping = 0;
+       }
        self.enttype = 0;
        self.classname = "";
        self.draw = menu_sub_null;
@@@ -1211,10 -1222,6 +1224,10 @@@ float CSQC_Parse_TempEntity(
                        cl_notice_read();
                        bHandled = true;
                        break;
 +              case TE_CSQC_NOTIFICATION:
 +                      Read_Notification();
 +                      bHandled = true;
 +                      break;
                default:
                        // No special logic for this temporary entity; return 0 so the engine can handle it
                        bHandled = false;
diff --combined qcsrc/client/View.qc
index 4771a8ea99c9ecb192c834599a025999650db725,940f810573f3283f007b310855df39813e939c8f..dccee35de1559ccf42e6773ee2be22b0f564c98a
@@@ -242,7 -242,7 +242,7 @@@ float EnemyHitCheck(
        if(teamplay)
                if(t == myteam)
                        return SHOTTYPE_HITTEAM;
 -      if(t == COLOR_SPECTATOR)
 +      if(t == FL_SPECTATOR)
                return SHOTTYPE_HITWORLD;
        return SHOTTYPE_HITENEMY;
  }
@@@ -782,7 -782,6 +782,6 @@@ void CSQC_UpdateView(float w, float h
  
  
        // improved polyblend
-       vector rgb;
        if(autocvar_hud_contents)
        {
                float contentalpha_temp, incontent, liquidalpha, contentfadetime;
index e7988cb5ad1d165920dd654f336bab94b9b430ee,ccc5dc35475dcda19612e5d228bad1c508059d94..c4a5b39a6b27c77d0b8829d0658f513195f760b7
@@@ -218,7 -218,7 +218,7 @@@ void CSQCPlayer_ForceModel_Apply(float 
                entity tm;
  
                for(tm = teams.sort_next; tm; tm = tm.sort_next)
 -                      if(tm.team != COLOR_SPECTATOR)
 +                      if(tm.team != FL_SPECTATOR)
                                ++teams_count;
  
                if(autocvar_cl_forcemyplayercolors)
@@@ -443,6 -443,7 +443,7 @@@ void CSQCModel_Effects_PostUpdate(void
        if(self.csqcmodel_teleported)
                Projectile_ResetTrail(self.origin);
  }
+ .float snd_looping;
  void CSQCModel_Effects_Apply(void)
  {
        float eff = self.csqcmodel_effects;
        if(self.csqcmodel_effects & CSQCMODEL_EF_RESPAWNGHOST)
                self.renderflags |= RF_ADDITIVE;
                // also special in CSQCPlayer_GlowMod_Apply
+       if(self.csqcmodel_modelflags & MF_ROCKET)
+       {
+               if(!self.snd_looping)
+               {
+                       sound(self, CH_TRIGGER_SINGLE, "misc/jetpack_fly.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+                       self.snd_looping = CH_TRIGGER_SINGLE;
+               }
+       }
+       else
+       {
+               if(self.snd_looping)
+               {
+                       sound(self, self.snd_looping, "misc/null.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+                       self.snd_looping = 0;
+               }
+       }
+ }
+ void CSQCPlayer_Precache()
+ {
+       precache_sound("misc/jetpack_fly.wav");
  }
  
  // FEATURE: auto glowmod
diff --combined qcsrc/client/hud.qc
index 77292f85f1307640fc70d3cb1524cd77166cebae,35a0a0448026ea2b06d7ed5b6ad81533fccd3dca..74a726d68850272f30b658ff350d01db447cdd64
@@@ -244,30 -244,6 +244,30 @@@ float race_CheckName(string net_name) 
        return 0;
  }
  
 +float GetPlayerColorForce(float i)
 +{
 +      if(!teamplay)
 +              return 0;
 +      else
 +              return stof(getplayerkeyvalue(i, "colors")) & 15;
 +}
 +
 +float GetPlayerColor(float i)
 +{
 +      if not(playerslots[i].gotscores) // unconnected
 +              return FL_SPECTATOR;
 +      else if(stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR)
 +              return FL_SPECTATOR;
 +      else
 +              return GetPlayerColorForce(i);
 +}
 +
 +string GetPlayerName(float i)
 +{
 +      return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
 +}
 +
 +
  /*
  ==================
  HUD panels
@@@ -463,15 -439,15 +463,15 @@@ void HUD_Weapons(void
        WEPSET_COPY_AS(weapons_stat);
        float i, f, a, j, factor;
        float screen_ar, center_x, center_y;
-       float weapon_count, weapon_id, weapon_alpha;
+       float weapon_count, weapon_id;
        float row, column, rows, columns;
        float aspect = autocvar_hud_panel_weapons_aspect;
  
        float show_accuracy = false, panel_weapon_accuracy;
  
        float timeout = autocvar_hud_panel_weapons_timeout;
-       float timein_effect_length = (autocvar_hud_panel_weapons_timeout_effect ? 0.375 : 0);
-       float timeout_effect_length = (autocvar_hud_panel_weapons_timeout_effect ? 0.75 : 0);
+       float timein_effect_length = autocvar_hud_panel_weapons_timeout_speed_in; //? 0.375 : 0);
+       float timeout_effect_length = autocvar_hud_panel_weapons_timeout_speed_out; //? 0.75 : 0);
  
        float ammo_type, ammo_full;
        float barsize_x = 0, barsize_y = 0, baroffset_x = 0, baroffset_y = 0;
        {
                if((!autocvar_hud_panel_weapons) || (spectatee_status == -1))
                        return;
-               else if(timeout && time >= weapontime + timeout + timeout_effect_length)
+               else if(timeout && time >= weapontime + timeout + timeout_effect_length && ((autocvar_hud_panel_weapons_timeout_effect != 1) && !(autocvar_hud_panel_weapons_timeout_fadebgmin + autocvar_hud_panel_weapons_timeout_fadefgmin)))
                {
                        weaponprevtime = time;
                        return;
  
        draw_beginBoldFont();
  
-       // calculate fading effect to weapon images for when the panel is idle
-       if(autocvar_hud_panel_weapons_fade)
-       {
-               weapon_alpha = 3.2 - 2 * (time - weapontime);
-               weapon_alpha = bound(0.7, weapon_alpha, 1) * panel_fg_alpha;
-       }
-       else
-               weapon_alpha = panel_fg_alpha;
        // figure out weapon order (how the weapons are sorted) // TODO make this configurable
        if(weaponorder_bypriority != autocvar_cl_weaponpriority || !weaponorder[0])
        {
        {
                if (timeout && time >= weapontime + timeout) // apply timeout effect if needed
                {
-                       f = (time - (weapontime + timeout)) / timeout_effect_length;
-                       if (autocvar_hud_panel_weapons_timeout_effect == 1 || autocvar_hud_panel_weapons_timeout_effect == 3)
+                       f = bound(0, (time - (weapontime + timeout)) / timeout_effect_length, 1);
+                       // fade the panel alpha
+                       if(autocvar_hud_panel_weapons_timeout_effect == 1)
+                       {
+                               panel_bg_alpha *= (autocvar_hud_panel_weapons_timeout_fadebgmin * f + (1 - f));
+                               panel_fg_alpha *= (autocvar_hud_panel_weapons_timeout_fadefgmin * f + (1 - f));
+                       }
+                       else if(autocvar_hud_panel_weapons_timeout_effect == 3)
                        {
                                panel_bg_alpha *= (1 - f);
                                panel_fg_alpha *= (1 - f);
                        }
+                       // move the panel off the screen
                        if (autocvar_hud_panel_weapons_timeout_effect == 2 || autocvar_hud_panel_weapons_timeout_effect == 3)
                        {
                                f *= f; // for a cooler movement
                }
                else if (timeout && time < weaponprevtime + timein_effect_length) // apply timein effect if needed
                {
-                       f = (time - weaponprevtime) / timein_effect_length;
-                       if (autocvar_hud_panel_weapons_timeout_effect == 1 || autocvar_hud_panel_weapons_timeout_effect == 3)
+                       f = bound(0, (time - weaponprevtime) / timein_effect_length, 1);
+                       // fade the panel alpha
+                       if(autocvar_hud_panel_weapons_timeout_effect == 1)
+                       {
+                               panel_bg_alpha *= (autocvar_hud_panel_weapons_timeout_fadebgmin * (1 - f) + f);
+                               panel_fg_alpha *= (autocvar_hud_panel_weapons_timeout_fadefgmin * (1 - f) + f);
+                       }
+                       else if(autocvar_hud_panel_weapons_timeout_effect == 3)
                        {
                                panel_bg_alpha *= (f);
                                panel_fg_alpha *= (f);
                        }
+                       // move the panel back on screen
                        if (autocvar_hud_panel_weapons_timeout_effect == 2 || autocvar_hud_panel_weapons_timeout_effect == 3)
                        {
                                f *= f; // for a cooler movement
  
                // draw background behind currently selected weapon
                if(self.weapon == switchweapon)
-                       drawpic_aspect_skin(weapon_pos, "weapon_current_bg", weapon_size, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
+                       drawpic_aspect_skin(weapon_pos, "weapon_current_bg", weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
  
                // draw the weapon accuracy
                if(show_accuracy)
                if(WEPSET_CONTAINS_AW(weapons_stat, self.weapon))
                {
                        // draw the weapon image
-                       drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
+                       drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
  
                        // draw weapon label string
                        switch(autocvar_hud_panel_weapons_label)
@@@ -1630,10 -1615,31 +1639,10 @@@ string Weapon_KillMessage(float deathty
        return w_deathtypestring;
  }
  
 -#define KN_MAX_ENTRIES 10
 -float kn_index;
 -float killnotify_times[KN_MAX_ENTRIES];
 -float killnotify_deathtype[KN_MAX_ENTRIES];
 -float killnotify_actiontype[KN_MAX_ENTRIES]; // 0 = "Y [used by] X", 1 = "X [did action to] Y"
 -string killnotify_attackers[KN_MAX_ENTRIES];
 -string killnotify_victims[KN_MAX_ENTRIES];
 -void HUD_KillNotify_Push(string attacker, string victim, float actiontype, float wpn)
 -{
 -      --kn_index;
 -      if (kn_index == -1)
 -              kn_index = KN_MAX_ENTRIES-1;
 -      killnotify_times[kn_index] = time;
 -      killnotify_deathtype[kn_index] = wpn;
 -      killnotify_actiontype[kn_index] = actiontype;
 -      if(killnotify_attackers[kn_index])
 -              strunzone(killnotify_attackers[kn_index]);
 -      killnotify_attackers[kn_index] = strzone(attacker);
 -      if(killnotify_victims[kn_index])
 -              strunzone(killnotify_victims[kn_index]);
 -      killnotify_victims[kn_index] = strzone(victim);
 -}
  
  void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s1 = attacker, s2 = victim
  {
 +      /*
        float w;
        float alsoprint, gentle;
        alsoprint = (autocvar_hud_panel_notify_print || !panel_enabled); // print message to console if: notify panel disabled, or cvar to do so enabled
                        if(alsoprint)
                                print(sprintf(_("%s^7 has dropped the ball!\n"), s1));
                }
 -      }
 +      }*/
  }
  
  void HUD_KillCenterprint(string s1, string s2, float type, float msg)
                                centerprint_hud(_("^1Don't go against team mates!"));
                        else
                                centerprint_hud(_("^1Don't shoot your team mates!"));
 -              } else if (type == DEATH_QUIET) {
 -                      // do nothing
                } else { // generic message
                        if(gentle)
                                centerprint_hud(_("^1You need to be more careful!"));
        }
  }
  
 -void HUD_Notify (void)
 +void HUD_Notify(void)
  {
        if(!autocvar__hud_configure)
        {
        float fadetime;
        fadetime = autocvar_hud_panel_notify_fadetime;
  
 -      string s;
 -
 -      vector pos_attacker, pos_victim;
 -      vector weap_pos;
 +      vector pos_attacker, pos_victim, pos_icon;
        float width_attacker;
 -      string attacker, victim;
 +      string attacker, victim, icon;
  
        float i, j, w, type, step, limit;
        if(autocvar_hud_panel_notify_flip) //order items from the top down
                                a = entries - 1 - i;
                        attacker = textShortenToWidth(sprintf(_("Player %d"), a+1), 0.48 * mySize_x - height, fontsize, stringwidth_colors);
                        victim = textShortenToWidth(sprintf(_("Player %d"), a+2), 0.48 * mySize_x - height, fontsize, stringwidth_colors);
 -                      s = strcat("weapon", get_weaponinfo(WEP_FIRST + mod(floor(a*2.4), WEP_LAST)).netname);
 +                      icon = strcat("weapon", get_weaponinfo(WEP_FIRST + mod(floor(a*2.4), WEP_LAST)).netname);
                        a = bound(0, (when - a) / 4, 1);
                        goto hud_config_notifyprint;
                }
 -
 -              if (j == KN_MAX_ENTRIES)
 -                      j = 0;
 -
 -              if(killnotify_times[j] + when > time)
 -                      a = 1;
 -              else if(fadetime)
 -              {
 -                      a = bound(0, (killnotify_times[j] + when + fadetime - time) / fadetime, 1);
 -                      if(!a)
 -                      {
 -                              break;
 -                      }
 -              }
                else
                {
 -                      break;
 -              }
 -
 -              s = "";
 -
 -              type = killnotify_deathtype[j];
 -              w = DEATH_WEAPONOF(type);
 +                      if (j == KN_MAX_ENTRIES)
 +                              j = 0;
  
 -              // TODO: maybe print in team colors?
 -              //
 -              // Y [used by] X
 -              if(killnotify_actiontype[j] == 0) 
 -              {
 -                      if(type == DEATH_GENERIC)
 -                      {
 -                              s = "notify_death";
 -                      }
 -                      else if(type == DEATH_NOAMMO)
 -                      {
 -                              s = "notify_outofammo";
 -                      }
 -                      else if(type == DEATH_KILL)
 -                      {
 -                              s = "notify_selfkill";
 -                      }
 -                      else if(type == DEATH_CAMP)
 -                      {
 -                              s = "notify_camping";
 -                      }
 -                      else if(type == KILL_TEAM_RED)
 -                      {
 -                              s = "notify_teamkill_red";
 -                      }
 -                      else if(type == KILL_TEAM_BLUE)
 -                      {
 -                              s = "notify_teamkill_blue";
 -                      }
 -                      else if(type == DEATH_DROWN)
 -                      {
 -                              s = "notify_water";
 -                      }
 -                      else if(type == DEATH_SLIME)
 -                      {
 -                              s = "notify_slime";
 -                      }
 -                      else if(type == DEATH_LAVA)
 -                      {
 -                              s = "notify_lava";
 -                      }
 -                      else if(type == DEATH_FALL)
 -                      {
 -                              s = "notify_fall";
 -                      }
 -                      else if(type == DEATH_SHOOTING_STAR)
 -                      {
 -                              s = "notify_shootingstar";
 -                      }
 -                      else if(type == DEATH_HURTTRIGGER || type == DEATH_CUSTOM)
 -                      {
 -                              s = "notify_death";
 -                      }
 -                      else if(type == INFO_GOTFLAG)
 -                      {
 -                              if(killnotify_victims[j] == "^1RED^7 flag")
 -                              {
 -                                      s = "notify_red_taken";
 -                              }
 -                              else
 -                              {
 -                                      s = "notify_blue_taken";
 -                              }
 -                      }
 -                      else if(type == INFO_RETURNFLAG)
 -                      {
 -                              if(killnotify_victims[j] == "^1RED^7 flag")
 -                              {
 -                                      s = "notify_red_returned";
 -                              }
 -                              else
 -                              {
 -                                      s = "notify_blue_returned";
 -                              }
 -                      }
 -                      else if(type == INFO_LOSTFLAG)
 -                      {
 -                              if(killnotify_victims[j] == "^1RED^7 flag")
 -                              {
 -                                      s = "notify_red_lost";
 -                              }
 -                              else
 -                              {
 -                                      s = "notify_blue_lost";
 -                              }
 -                      }
 -                      else if(type == INFO_CAPTUREFLAG)
 +                      if(killnotify_times[j] + when > time)
 +                              a = 1;
 +                      else if(fadetime)
                        {
 -                              if(killnotify_victims[j] == "^1RED^7 flag")
 -                              {
 -                                      s = "notify_red_captured";
 -                              }
 -                              else
 +                              a = bound(0, (killnotify_times[j] + when + fadetime - time) / fadetime, 1);
 +                              if(!a)
                                {
 -                                      s = "notify_blue_captured";
 +                                      break;
                                }
                        }
 -                      else if(type == KA_DROPBALL)
 -                      {
 -                              s = "notify_balldropped";
 -                      }
 -                      else if(type == KA_PICKUPBALL)
 +                      else
                        {
 -                              s = "notify_ballpickedup";
 +                              break;
                        }
                        
 -                      attacker = textShortenToWidth(killnotify_attackers[j], 0.48 * mySize_x - height, fontsize, stringwidth_colors);
 -                      pos_attacker = pos + eX * (0.52 * mySize_x + height) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
 -                      weap_pos = pos + eX * 0.5 * mySize_x - eX * height + eY * i * height;
 -
 -                      if(s != "")
 -                      {
 -                              drawpic_aspect_skin(weap_pos, s, '2 1 0' * height, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
 -                              drawcolorcodedstring(pos_attacker, attacker, fontsize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
 -                      }
 +                      attacker = killnotify_attackers[j];
 +                      victim = killnotify_victims[j];
 +                      icon = killnotify_icon[j];
                }
 -              // X [did action to] Y
 -              else
 +
 +              //type = killnotify_deathtype[j];
 +              //w = DEATH_WEAPONOF(type);
 +
 +              if(icon != "")
                {
 -                      if(type & HITTYPE_SECONDARY && w == WEP_LASER)
 -                      {
 -                              s = "notify_melee_laser";
 -                      }
 -                      else if(type & HITTYPE_SECONDARY && w == WEP_SHOTGUN)
 -                      {
 -                              s = "notify_melee_shotgun";
 -                      }
 -                      else if(type & HITTYPE_HEADSHOT && (w == WEP_RIFLE || w == WEP_MINSTANEX)) // all headshot weapons go here
 -                      {
 -                              s = "notify_headshot";
 -                      }
 -                      else if(WEP_VALID(w))
 -                      {
 -                              self = get_weaponinfo(w);
 -                              s = strcat("weapon", self.netname);
 -                      }
 -                      else if(type == KILL_TEAM_RED)
 -                      {
 -                              s = "notify_teamkill_red";
 -                      }
 -                      else if(type == KILL_TEAM_BLUE)
 -                      {
 -                              s = "notify_teamkill_red";
 -                      }
 -                      else if(type == DEATH_TELEFRAG)
 -                      {
 -                              s = "notify_telefrag";
 -                      }
 -                      else if(type == DEATH_DROWN)
 -                      {
 -                              s = "notify_water";
 -                      }
 -                      else if(type == DEATH_SLIME)
 -                      {
 -                              s = "notify_slime";
 -                      }
 -                      else if(type == DEATH_LAVA)
 -                      {
 -                              s = "notify_lava";
 -                      }
 -                      else if(type == DEATH_FALL)
 -                      {
 -                              s = "notify_fall";
 -                      }
 -                      else if(type == DEATH_SHOOTING_STAR)
 -                      {
 -                              s = "notify_shootingstar";
 -                      }
 -                      else if(type == DEATH_HURTTRIGGER || type == DEATH_CUSTOM) // DEATH_CUSTOM is also void, right?
 -                      {
 -                              s = "notify_void";
 -                      }
 -                      else if(type == RACE_SERVER_RECORD)
 -                      {
 -                              s = "race_newrecordserver";
 -                      }
 -                      else if(type == RACE_NEW_RANK)
 -                      {
 -                              s = "race_newrankyellow";
 -                      }
 -                      else if(type == RACE_NEW_TIME)
 +                      if((attacker != "") && (victim == ""))
                        {
 -                              s = "race_newtime";
 +                              // Y [used by] X
 +                              attacker = textShortenToWidth(attacker, 0.73 * mySize_x - height, fontsize, stringwidth_colors);
 +                              pos_attacker = pos + eX * (0.27 * mySize_x + height) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
 +                              pos_icon = pos + eX * 0.25 * mySize_x - eX * height + eY * i * height;
 +
 +                              drawpic_aspect_skin(pos_icon, icon, '2 1 0' * height, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
 +                              drawcolorcodedstring(pos_attacker, attacker, fontsize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
                        }
 -                      else if(type == RACE_FAIL)
 +                      else if((attacker != "") && (victim != ""))
                        {
 -                              s = "race_newfail";
 -                      }
 -
 -                      attacker = textShortenToWidth(killnotify_attackers[j], 0.48 * mySize_x - height, fontsize, stringwidth_colors);
 -                      victim = textShortenToWidth(killnotify_victims[j], 0.48 * mySize_x - height, fontsize, stringwidth_colors);
 +                              // X [did action to] Y
 +                              attacker = textShortenToWidth(attacker, 0.48 * mySize_x - height, fontsize, stringwidth_colors);
 +                              victim = textShortenToWidth(victim, 0.48 * mySize_x - height, fontsize, stringwidth_colors);
  :hud_config_notifyprint
 -                      width_attacker = stringwidth(attacker, TRUE, fontsize);
 -                      pos_attacker = pos + eX * (0.48 * mySize_x - height - width_attacker) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
 -                      pos_victim = pos + eX * (0.52 * mySize_x + height) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
 -                      weap_pos = pos + eX * 0.5 * mySize_x - eX * height + eY * i * height;
 +                              width_attacker = stringwidth(attacker, TRUE, fontsize);
 +                              pos_attacker = pos + eX * (0.48 * mySize_x - height - width_attacker) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
 +                              pos_victim = pos + eX * (0.52 * mySize_x + height) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
 +                              pos_icon = pos + eX * 0.5 * mySize_x - eX * height + eY * i * height;
  
 -                      if(s != "")
 -                      {
 -                              drawpic_aspect_skin(weap_pos, s, '2 1 0' * height, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
 +                              drawpic_aspect_skin(pos_icon, icon, '2 1 0' * height, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
                                drawcolorcodedstring(pos_attacker, attacker, fontsize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
                                drawcolorcodedstring(pos_victim, victim, fontsize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
                        }
@@@ -2481,8 -2664,8 +2490,8 @@@ void HUD_Radar(void
        for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
        {
                color2 = GetPlayerColor(tm.sv_entnum);
 -              //if(color == COLOR_SPECTATOR || color == color2)
 -                      draw_teamradar_player(tm.origin, tm.angles, GetTeamRGB(color2));
 +              //if(color == FL_SPECTATOR || color == color2)
 +                      draw_teamradar_player(tm.origin, tm.angles, Team_ColorRGB(color2));
        }
        draw_teamradar_player(view_origin, view_angles, '1 1 1');
  
@@@ -2521,7 -2704,7 +2530,7 @@@ void HUD_Score_Rankings(vector pos, vec
                        for(i=0; i<team_count; ++i) {
                                if (i == floor((entries - 2) / players_per_team) || (entries == 1 && i == 0))
                                        HUD_Panel_DrawHighlight(pos + eX * score_size * i, eX * score_size + eY * fontsize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 -                              drawstring_aspect(pos + eX * score_size * i, ftos(175 - 23*i), eX * score_size + eY * fontsize_y, GetTeamRGB(ColorByTeam(i)) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
 +                              drawstring_aspect(pos + eX * score_size * i, ftos(175 - 23*i), eX * score_size + eY * fontsize_y, Team_ColorRGB(ColorByTeam(i)) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
                        }
                        first_pl = 1;
                        pos_y += fontsize_y;
                        }
  
                        if (team_count)
 -                              score_color = GetTeamRGB(ColorByTeam(floor((i - first_pl) / players_per_team))) * 0.8;
 +                              score_color = Team_ColorRGB(ColorByTeam(floor((i - first_pl) / players_per_team))) * 0.8;
                        s = textShortenToWidth(s, name_size, fontsize, stringwidth_colors);
                        drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, TRUE, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
                        drawstring(pos + eX * (name_size + spacing_size), ftos(score), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
                // show team scores in the first line
                float score_size = mySize_x / team_count;
                for(tm = teams.sort_next; tm; tm = tm.sort_next) {
 -                      if(tm.team == COLOR_SPECTATOR)
 +                      if(tm.team == FL_SPECTATOR)
                                continue;
                        if (tm.team == myteam)
                                drawfill(pos + eX * score_size * i, eX * score_size + eY * fontsize_y, '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 -                      drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores[ts_primary])), eX * score_size + eY * fontsize_y, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
 +                      drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores[ts_primary])), eX * score_size + eY * fontsize_y, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
                        ++i;
                }
                first_pl = 1;
        do
        for (pl = players.sort_next; pl && i<entries; pl = pl.sort_next)
        {
 -              if ((team_count && pl.team != tm.team) || pl.team == COLOR_SPECTATOR)
 +              if ((team_count && pl.team != tm.team) || pl.team == FL_SPECTATOR)
                        continue;
  
                if (i == entries-1 && !me_printed && pl != me)
                if (autocvar_hud_panel_score_rankings == 1 && spectatee_status != -1)
                {
                        for (pl = me.sort_next; pl; pl = pl.sort_next)
 -                              if (pl.team != COLOR_SPECTATOR)
 +                              if (pl.team != FL_SPECTATOR)
                                        break;
  
                        if (pl)
                        drawfill(pos, eX * mySize_x + eY * fontsize_y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                }
                if (team_count)
 -                      score_color = GetTeamRGB(pl.team) * 0.8;
 +                      score_color = Team_ColorRGB(pl.team) * 0.8;
                s = textShortenToWidth(GetPlayerName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
                drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, TRUE, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
                drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores[ps_primary])), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
                pos_y += fontsize_y;
                ++i;
        }
 -      while (i<entries && team_count && (tm = tm.sort_next) && (tm.team != COLOR_SPECTATOR || (tm = tm.sort_next)));
 +      while (i<entries && team_count && (tm = tm.sort_next) && (tm.team != FL_SPECTATOR || (tm = tm.sort_next)));
  }
  
  void HUD_Score(void)
                vector score_pos, score_size; //for scores other than myteam
                if (spectatee_status == -1 || autocvar_hud_panel_score_rankings)
                {
 -                      for(tm = teams.sort_next; tm, tm.team != COLOR_SPECTATOR; tm = tm.sort_next)
 +                      for(tm = teams.sort_next; tm, tm.team != FL_SPECTATOR; tm = tm.sort_next)
                                ++scores_count;
                        if (autocvar_hud_panel_score_rankings)
                        {
                draw_beginBoldFont();
                row = column = 0;
                for(tm = teams.sort_next; tm; tm = tm.sort_next) {
 -                      if(tm.team == COLOR_SPECTATOR)
 +                      if(tm.team == FL_SPECTATOR)
                                continue;
                        score = tm.(teamscores[ts_primary]);
                        if(autocvar__hud_configure)
                                score_pos = pos + eX * column * (score_size_x + offset_x) + eY * row * (score_size_y + offset_y);
                                if (max_fragcount == score)
                                        HUD_Panel_DrawHighlight(score_pos, score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 -                              drawstring_aspect(score_pos, ftos(score), score_size, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
 +                              drawstring_aspect(score_pos, ftos(score), score_size, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
                                ++row;
                                if(row >= rows)
                                {
                        else if(tm.team == myteam) {
                                if (max_fragcount == score)
                                        HUD_Panel_DrawHighlight(pos, eX * 0.75 * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 -                              drawstring_aspect(pos, ftos(score), eX * 0.75 * mySize_x + eY * mySize_y, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
 +                              drawstring_aspect(pos, ftos(score), eX * 0.75 * mySize_x + eY * mySize_y, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
                        } else {
                                if (max_fragcount == score)
                                        HUD_Panel_DrawHighlight(pos + eX * 0.75 * mySize_x + eY * (1/3) * rows * mySize_y, score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 -                              drawstring_aspect(pos + eX * 0.75 * mySize_x + eY * (1/3) * rows * mySize_y, ftos(score), score_size, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
 +                              drawstring_aspect(pos + eX * 0.75 * mySize_x + eY * (1/3) * rows * mySize_y, ftos(score), score_size, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
                                ++rows;
                        }
                }
@@@ -3213,7 -3396,7 +3222,7 @@@ void HUD_Mod_CTF(vector pos, vector myS
                case 2: red_icon = "flag_red_lost"; break;
                case 3: red_icon = "flag_red_carrying"; red_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break;
                default:
 -                      if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM2))
 +                      if((stat_items & IT_CTF_SHIELDED) && (myteam == FL_TEAM_2))
                                red_icon = "flag_red_shielded";
                        else
                                red_icon = string_null;
                default:
                        if(redflag == 3)
                                red_icon_prevstatus = "flag_red_carrying"; // make it more visible
 -                      else if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM2))
 +                      else if((stat_items & IT_CTF_SHIELDED) && (myteam == FL_TEAM_2))
                                red_icon_prevstatus = "flag_red_shielded";
                        else
                                red_icon_prevstatus = string_null;
                case 2: blue_icon = "flag_blue_lost"; break;
                case 3: blue_icon = "flag_blue_carrying"; blue_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break;
                default:
 -                      if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM1))
 +                      if((stat_items & IT_CTF_SHIELDED) && (myteam == FL_TEAM_1))
                                blue_icon = "flag_blue_shielded";
                        else
                                blue_icon = string_null;
                default:
                        if(blueflag == 3)
                                blue_icon_prevstatus = "flag_blue_carrying"; // make it more visible
 -                      else if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM1))
 +                      else if((stat_items & IT_CTF_SHIELDED) && (myteam == FL_TEAM_1))
                                blue_icon_prevstatus = "flag_blue_shielded";
                        else
                                blue_icon_prevstatus = string_null;
        }
  
        if(mySize_x > mySize_y) {
 -              if (myteam == COLOR_TEAM1) { // always draw own flag on left
 +              if (myteam == FL_TEAM_1) { // always draw own flag on left
                        redflag_pos = pos;
                        blueflag_pos = pos + eX * 0.5 * mySize_x;
                } else {
                }
                flag_size = eX * 0.5 * mySize_x + eY * mySize_y;
        } else {
 -              if (myteam == COLOR_TEAM1) { // always draw own flag on left
 +              if (myteam == FL_TEAM_1) { // always draw own flag on left
                        redflag_pos = pos;
                        blueflag_pos = pos + eY * 0.5 * mySize_y;
                } else {
@@@ -3385,16 -3568,16 +3394,16 @@@ void HUD_Mod_KH(vector pos, vector mySi
                {
                        switch(keyteam)
                        {
 -                              case COLOR_TEAM1:
 +                              case FL_TEAM_1:
                                        drawpic_aspect_skin(pa, "kh_redarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% theAlpha key
                                        break;
 -                              case COLOR_TEAM2:
 +                              case FL_TEAM_2:
                                        drawpic_aspect_skin(pa, "kh_bluearrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% theAlpha key
                                        break;
 -                              case COLOR_TEAM3:
 +                              case FL_TEAM_3:
                                        drawpic_aspect_skin(pa, "kh_yellowarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% theAlpha key
                                        break;
 -                              case COLOR_TEAM4:
 +                              case FL_TEAM_4:
                                        drawpic_aspect_skin(pa, "kh_pinkarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% theAlpha key
                                        break;
                                default:
@@@ -3741,7 -3924,7 +3750,7 @@@ void HUD_Mod_Dom(vector myPos, vector m
        entity tm;
        float teams_count = 0;
        for(tm = teams.sort_next; tm; tm = tm.sort_next)
 -              if(tm.team != COLOR_SPECTATOR)
 +              if(tm.team != FL_SPECTATOR)
                        ++teams_count;
  
        float layout = autocvar_hud_panel_modicons_dom_layout;
@@@ -4200,7 -4383,7 +4209,7 @@@ void HUD_InfoMessages(void
                        {
                                for(; tm.sort_next; tm = tm.sort_next)
                                {
 -                                      if(!tm.team_size || tm.team == COLOR_SPECTATOR)
 +                                      if(!tm.team_size || tm.team == FL_SPECTATOR)
                                                continue;
                                        if(!ts_min) ts_min = tm.team_size;
                                        else ts_min = min(ts_min, tm.team_size);
                                        s = strcat(blinkcolor, _("Teamnumbers are unbalanced!"));
                                        tm = GetTeam(myteam, false);
                                        if (tm)
 -                                      if (tm.team != COLOR_SPECTATOR)
 +                                      if (tm.team != FL_SPECTATOR)
                                        if (tm.team_size == ts_max)
                                                s = strcat(s, sprintf(_(" Press ^3%s%s to adjust"), getcommandkey("team menu", "menu_showteamselect"), blinkcolor));
                                        drawInfoMessage(s)
diff --combined qcsrc/client/main.qh
index 474e919f42ee1b5f170d89551fb4585f34c6b806,28536c256b017f5f7a0397e86728c90fe0d4682f..8369a5ff20bc9ce399d0eef7c1a35d1063b4d8a9
@@@ -1,5 -1,3 +1,3 @@@
- const string string_null;
  // --------------------------------------------------------------------------
  // MENU Functionality
  
@@@ -40,6 -38,16 +38,6 @@@ float gametype
  //.float ctf_state;
  //.float health;
  
 -// Constants
 -const float COLOR_TEAM_RED = 64;
 -const float COLOR_TEAM_BLUE = 208;
 -
 -const float COLOR_TEAM1       = 4;  // red
 -const float COLOR_TEAM2       = 13; // blue
 -const float COLOR_TEAM3       = 12; // yellow
 -const float COLOR_TEAM4       = 9; // pink
 -const float COLOR_SPECTATOR = 1337;
 -
  #define FONT_DEFAULT 0
  #define FONT_USER 8
  
index f7de619d0eae0c41e0146d40176578dc00f1109e,6cceb42bacda13964394e996318c8f37f0e8fb3f..0cdfb0f8e380f8ca8fa4ba9c1446e69595078cc8
@@@ -1,5 -1,3 +1,3 @@@
- var float(string text, float handleColors, vector fontSize) stringwidth;
  entity players;
  entity teams;
  
@@@ -110,7 -108,7 +108,7 @@@ entity GetTeam(float Team, float add
  {
        float num;
        entity tm;
 -      num = (Team == COLOR_SPECTATOR) ? 16 : Team;
 +      num = (Team == FL_SPECTATOR) ? 16 : Team;
        if(teamslots[num])
                return teamslots[num];
        if not(add)
@@@ -166,6 -164,20 +164,6 @@@ string ColorTranslateRGB(string s
                return s;
  }
  
 -string Team_ColorCode(float teamid)
 -{
 -    if (teamid == COLOR_TEAM1)
 -        return "^1";
 -    else if (teamid == COLOR_TEAM2)
 -        return "^4";
 -    else if (teamid == COLOR_TEAM3)
 -        return "^3";
 -    else if (teamid == COLOR_TEAM4)
 -        return "^6";
 -    else
 -        return "^7";
 -}
 -
  // decolorizes and team colors the player name when needed
  string playername(string thename, float teamid)
  {
diff --combined qcsrc/common/util.qh
index 9a3821ed16b4e4f2d6ff43f687c852afa06bb913,10e680e562615a818f62f7297294681158ed03aa..4ac13b925cd431ebac060edd2cdf1bd37785cdfb
@@@ -1,9 -1,6 +1,9 @@@
  // a dummy macro that prevents the "hanging ;" warning
  #define ENDS_WITH_CURLY_BRACE
  
 +// return the actual code name of a var as a string
 +#define VAR_TO_TEXT(var) #var
 +
  #ifdef HAVE_YO_DAWG_CPP
  // TODO make ascii art pic of xzibit
  // YO DAWG!
@@@ -40,11 -37,6 +40,11 @@@ void ACCUMULATE_call(string func
        ACCUMULATE_call(#func)
  #endif
  
 +// used for simplifying ACCUMULATE_FUNCTIONs
 +#define SET_FIRST_OR_LAST(input,first,count) if(!input) { input = (first + count); }
 +#define SET_FIELD_COUNT(field,first,count) if(!field) { field = (first + count); ++count; }
 +#define CHECK_MAX_COUNT(name,max,count,type) if(count == max) { error(strcat("Maximum ", type, " hit: ", VAR_TO_TEXT(name), ": ", ftos(count), ".\n")); }
 +
  // this returns a tempstring containing a copy of s with additional \n newlines added, it also replaces \n in the text with a real newline
  // NOTE: s IS allowed to be a tempstring
  string wordwrap(string s, float l);
@@@ -232,8 -224,13 +232,13 @@@ void WriteInt24_t(float dest, float val
  #endif
  
  // the NULL function
+ #ifdef GMQCC
+ #define func_null nil
+ #define string_null nil
+ #else
  var void func_null(void);
  var string string_null;
+ #endif
  float float2range11(float f);
  float float2range01(float f);
  
@@@ -367,9 -364,3 +372,9 @@@ float cubic_speedfunc_is_sane(float sta
  typedef entity(entity cur, entity near, entity pass) findNextEntityNearFunction_t;
  typedef float(entity a, entity b, entity pass) isConnectedFunction_t;
  void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass);
 +
 +// expand multiple arguments into one argument
 +#define XPD5(a,b,c,d,e) a, b, c, d, e
 +#define XPD4(a,b,c,d) a, b, c, d
 +#define XPD3(a,b,c) a, b, c
 +#define XPD2(a,b) a, b
diff --combined qcsrc/menu/progs.src
index 37bc4bea81e08e7325afb0789cee53558dd11886,e45a4813a6d257bc512e10dbae643c0db61500fa..efaff9d46092367fe70c32326ac70d28ff0bbc25
@@@ -1,7 -1,9 +1,9 @@@
  ../../menu.dat
  
+ sys-pre.qh
  ../dpdefs/menudefs.qc
  ../dpdefs/keycodes.qc
+ sys-post.qh
  
  config.qh
  ../common/util-pre.qh
@@@ -11,8 -13,6 +13,8 @@@
  
  oo/base.h
  
 +../common/teams.qh
 +../common/notifications.qc
  ../common/constants.qh
  ../common/mapinfo.qh
  ../common/campaign_common.qh
index 9d52dd79941e614edbe3d33f2d8389223b4d080a,433261d45a94b464e25e1e5d4b2b3d6a53aefecd..64ce307000104472d82148af6fc67d685f299fe3
@@@ -761,7 -761,6 +761,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;
@@@ -797,6 -796,7 +797,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;
@@@ -868,7 -868,6 +868,6 @@@ string autocvar_g_hitplots_individuals
  float autocvar_g_jetpack_acceleration_side;
  float autocvar_g_jetpack_acceleration_up;
  float autocvar_g_jetpack_antigravity;
- float autocvar_g_jetpack_attenuation;
  float autocvar_g_jetpack_fuel;
  float autocvar_g_jetpack_maxspeed_side;
  float autocvar_g_jetpack_maxspeed_up;
@@@ -1175,7 -1174,6 +1174,7 @@@ 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;
@@@ -1230,6 -1228,7 +1229,7 @@@ float autocvar_sv_vote_singlecount
  float autocvar_sv_vote_stop;
  float autocvar_sv_vote_timeout;
  float autocvar_sv_vote_wait;
+ float autocvar_sv_vote_gamestart;
  float autocvar_sv_warsowbunny_accel;
  float autocvar_sv_warsowbunny_airforwardaccel;
  float autocvar_sv_warsowbunny_backtosideratio;
diff --combined qcsrc/server/bot/bot.qc
index bdcfe864e4e43666a60901933d549893f513a543,bd23e890356c3ca1b4e7fc1e295d60ff1df93b61..3781077ebc01d7efda4abe15c2c1106d6a7873bc
@@@ -45,7 -45,7 +45,7 @@@ void bot_think(
  
        if (autocvar_g_campaign && !campaign_bots_may_start)
        {
-               self.nextthink = time + 0.5;
+               self.bot_nextthink = time + 0.5;
                return;
        }
  
@@@ -85,7 -85,7 +85,7 @@@
        {
                // block the bot during the countdown to game start
                self.movement = '0 0 0';
-               self.nextthink = game_starttime;
+               self.bot_nextthink = game_starttime;
                return;
        }
  
@@@ -393,19 -393,19 +393,19 @@@ void bot_clientconnect(
        self.bot_nextthink = time - random();
        self.lag_func = bot_lagfunc;
        self.isbot = TRUE;
-       self.createdtime = self.nextthink;
+       self.createdtime = self.bot_nextthink;
  
        if(!self.bot_config_loaded) // This is needed so team overrider doesn't break between matches
                bot_setnameandstuff();
  
        if(self.bot_forced_team==1)
 -              self.team = COLOR_TEAM1;
 +              self.team = FL_TEAM_1;
        else if(self.bot_forced_team==2)
 -              self.team = COLOR_TEAM2;
 +              self.team = FL_TEAM_2;
        else if(self.bot_forced_team==3)
 -              self.team = COLOR_TEAM3;
 +              self.team = FL_TEAM_3;
        else if(self.bot_forced_team==4)
 -              self.team = COLOR_TEAM4;
 +              self.team = FL_TEAM_4;
        else
                JoinBestTeam(self, FALSE, TRUE);
  
@@@ -426,13 -426,13 +426,13 @@@ void bot_removefromlargestteam(
        bestcount = 0;
        while (head)
        {
 -              if(head.team == COLOR_TEAM1)
 +              if(head.team == FL_TEAM_1)
                        thiscount = c1;
 -              else if(head.team == COLOR_TEAM2)
 +              else if(head.team == FL_TEAM_2)
                        thiscount = c2;
 -              else if(head.team == COLOR_TEAM3)
 +              else if(head.team == FL_TEAM_3)
                        thiscount = c3;
 -              else if(head.team == COLOR_TEAM4)
 +              else if(head.team == FL_TEAM_4)
                        thiscount = c4;
                else
                        thiscount = 0;
index 775374baeacb2d5bcd55166ee4be9821a35623f1,4f5671df082117db61307d639106d9756dbe4976..81d218271460b17f1a5951c93f71e0d525dd3c27
@@@ -554,7 -554,7 +554,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));
@@@ -1241,10 -1241,10 +1241,10 @@@ void ClientKill_TeamChange (float targe
                }
                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_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, strcat("^7Changing to ", Team_ColoredFullName(targetteam), "^7 in %d seconds"), 1, self.killindicator.cnt);
                }
        }
  
@@@ -1286,7 -1286,7 +1286,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
@@@ -1335,6 -1335,7 +1335,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);
@@@ -1362,16 -1363,6 +1362,16 @@@ void ClientConnect (void
        self.flags = FL_CLIENT;
        self.version_nagtime = time + 10 + random() * 10;
  
 +      if(self.netaddress == "local")
 +      {
 +              print("^3server is local!\n");
 +
 +              if(server_is_local)
 +                      print("Multiple local clients???");
 +              else
 +                      server_is_local = TRUE;
 +      }
 +
        if(player_count<0)
        {
                dprint("BUG player count is lower than zero, this cannot happen!\n");
                {
                        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 = FL_TEAM_1; break;
 +                              case 2: self.team_forced = FL_TEAM_2; break;
 +                              case 3: self.team_forced = FL_TEAM_3; break;
 +                              case 4: self.team_forced = FL_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 = FL_TEAM_1;
        else if(PlayerInIDList(self, autocvar_g_forced_team_blue))
 -              self.team_forced = COLOR_TEAM2;
 +              self.team_forced = FL_TEAM_2;
        else if(PlayerInIDList(self, autocvar_g_forced_team_yellow))
 -              self.team_forced = COLOR_TEAM3;
 +              self.team_forced = FL_TEAM_3;
        else if(PlayerInIDList(self, autocvar_g_forced_team_pink))
 -              self.team_forced = COLOR_TEAM4;
 +              self.team_forced = FL_TEAM_4;
        else if(autocvar_g_forced_team_otherwise == "red")
 -              self.team_forced = COLOR_TEAM1;
 +              self.team_forced = FL_TEAM_1;
        else if(autocvar_g_forced_team_otherwise == "blue")
 -              self.team_forced = COLOR_TEAM2;
 +              self.team_forced = FL_TEAM_2;
        else if(autocvar_g_forced_team_otherwise == "yellow")
 -              self.team_forced = COLOR_TEAM3;
 +              self.team_forced = FL_TEAM_3;
        else if(autocvar_g_forced_team_otherwise == "pink")
 -              self.team_forced = COLOR_TEAM4;
 +              self.team_forced = FL_TEAM_4;
        else if(autocvar_g_forced_team_otherwise == "spectate")
                self.team_forced = -1;
        else if(autocvar_g_forced_team_otherwise == "spectator")
        bprint("^4", self.netname, "^4 connected");
  
        if(self.classname != "observer" && (g_domination || g_ctf))
 -              bprint(" and joined the ", ColoredTeamName(self.team));
 +              bprint(" and joined the ", Team_ColoredFullName(self.team));
  
        bprint("\n");
  
        if(!sv_foginterval && world.fog != "")
                stuffcmd(self, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
  
-       SoundEntity_Attach(self);
        if(autocvar_g_hitplots || strstrofs(strcat(" ", autocvar_g_hitplots_individuals, " "), strcat(" ", self.netaddress, " "), 0) >= 0)
        {
                self.hitplotfh = fopen(strcat("hits-", matchid, "-", self.netaddress, "-", ftos(self.playerid), ".plot"), FILE_WRITE);
@@@ -1644,8 -1633,6 +1642,6 @@@ void ClientDisconnect (void
        bprint ("^4",self.netname);
        bprint ("^4 disconnected\n");
  
-       SoundEntity_Detach(self);
        DropAllRunes(self);
        MUTATOR_CALLHOOK(ClientDisconnect);
  
@@@ -1791,15 -1778,9 +1787,9 @@@ void player_powerups (void
        olditems = self.items;
  
        if((self.items & IT_USING_JETPACK) && !self.deadflag)
-       {
-               SoundEntity_StartSound(self, CH_TRIGGER_SINGLE, "misc/jetpack_fly.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
                self.modelflags |= MF_ROCKET;
-       }
        else
-       {
-               SoundEntity_StopSound(self, CH_TRIGGER_SINGLE);
                self.modelflags &~= MF_ROCKET;
-       }
  
        self.effects &~= (EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
  
index dd22d4b13018c149440c1786c9351e6c6b34a7ae,0710ddfa8474874cca23787d9ed6221e44660ebd..e44ec091085bcb4487d46769ea35b71f228313e1
@@@ -830,8 -830,6 +830,6 @@@ void GameCommand_animbench(float reques
                case CMD_REQUEST_COMMAND:
                {
                        entity tmp_entity;
-                       float i;
-                       vector v;
  
                        if(argc >= 4)
                        {
@@@ -974,6 -972,7 +972,6 @@@ void GameCommand_moveplayer(float reque
                        string targets = strreplace(",", " ", argv(1));
                        string original_targets = strreplace(" ", ", ", targets);
                        string destination = argv(2);
 -                      string notify = argv(3);
                        
                        string successful, t;
                        successful = string_null;
                                                        if(teamplay)
                                                        {
                                                                // set up
 -                                                              float team_color;
 +                                                              float team_id;
                                                                float save = client.team_forced;
                                                                client.team_forced = 0;
  
                                                                // find the team to move the player to
 -                                                              team_color = ColourToNumber(destination);
 -                                                              if(team_color == client.team) // already on the destination team
 +                                                              team_id = Team_ColorToTeam(destination);
 +                                                              if(team_id == client.team) // already on the destination team
                                                                {
                                                                        // keep the forcing undone
 -                                                                      print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") is already on the ", ColoredTeamName(client.team), (targets ? ", skipping to next player.\n" : ".\n"));
 +                                                                      print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") is already on the ", Team_ColoredFullName(client.team), (targets ? "^7, skipping to next player.\n" : "^7.\n"));
                                                                        continue;
                                                                } 
 -                                                              else if(team_color == 0)  // auto team
 +                                                              else if(team_id == 0)  // auto team
                                                                {
 -                                                                      team_color = NumberToTeamNumber(FindSmallestTeam(client, FALSE));
 +                                                                      team_id = Team_NumberToTeam(FindSmallestTeam(client, FALSE));
                                                                }
                                                                else
                                                                {
                                                                client.team_forced = save;
                                                                
                                                                // Check to see if the destination team is even available
 -                                                              switch(team_color
 +                                                              switch(team_id
                                                                {
 -                                                                      case COLOR_TEAM1: if(c1 == -1) { print("Sorry, can't move player to red team if it doesn't exist.\n"); return; } break;
 -                                                                      case COLOR_TEAM2: if(c2 == -1) { print("Sorry, can't move player to blue team if it doesn't exist.\n"); return; } break;
 -                                                                      case COLOR_TEAM3: if(c3 == -1) { print("Sorry, can't move player to yellow team if it doesn't exist.\n"); return; } break;
 -                                                                      case COLOR_TEAM4: if(c4 == -1) { print("Sorry, can't move player to pink team if it doesn't exist.\n"); return; } break;
 +                                                                      case FL_TEAM_1: if(c1 == -1) { print("Sorry, can't move player to red team if it doesn't exist.\n"); return; } break;
 +                                                                      case FL_TEAM_2: if(c2 == -1) { print("Sorry, can't move player to blue team if it doesn't exist.\n"); return; } break;
 +                                                                      case FL_TEAM_3: if(c3 == -1) { print("Sorry, can't move player to yellow team if it doesn't exist.\n"); return; } break;
 +                                                                      case FL_TEAM_4: if(c4 == -1) { print("Sorry, can't move player to pink team if it doesn't exist.\n"); return; } break;
                                                                        
                                                                        default: print("Sorry, can't move player here if team ", destination, " doesn't exist.\n"); return;
                                                                }
                                                                
                                                                // If so, lets continue and finally move the player
                                                                client.team_forced = 0;
 -                                                              MoveToTeam(client, team_color, 6, stof(notify));
 +                                                              MoveToTeam(client, team_id, 6);
                                                                successful = strcat(successful, (successful ? ", " : ""), client.netname);
 -                                                              print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") has been moved to the ", ColoredTeamName(team_color), ".\n");
 +                                                              print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") has been moved to the ", Team_ColoredFullName(team_id), "^7.\n");
                                                                continue;
                                                        }
                                                        else
                        print("Incorrect parameters for ^2moveplayer^7\n");
                case CMD_REQUEST_USAGE:
                {
 -                      print("\nUsage:^3 sv_cmd moveplayer clients destination [notify]\n");
 +                      print("\nUsage:^3 sv_cmd moveplayer clients destination\n");
                        print("  'clients' is a list (separated by commas) of player entity ID's or nicknames\n");
                        print("  'destination' is what to send the player to, be it team or spectating\n");
                        print("  Full list of destinations here: \"spec, spectator, red, blue, yellow, pink, auto.\"\n");
 -                      print("  'notify' is whether or not to send messages notifying of the move. Detail below.\n");
 -                      print("    0 (00) automove centerprint, admin message; 1 (01) automove centerprint, no admin message\n");
 -                      print("    2 (10) no centerprint, admin message; 3 (11) no centerprint, no admin message\n");
                        print("Examples: sv_cmd moveplayer 1,3,5 red 3\n");
                        print("          sv_cmd moveplayer 2 spec \n");
                        print("See also: ^2allspec, shuffleteams^7\n");
@@@ -1352,7 -1354,7 +1350,7 @@@ void GameCommand_shuffleteams(float req
                                        x = (t_players / t_teams);
                                        x = ((i == 1) ? ceil(x) : floor(x));
                                        
 -                                      team_color = NumberToTeamNumber(i);
 +                                      team_color = Team_NumberToTeam(i);
                                        
                                        // sort through the random list of players made earlier 
                                        for(z = 1; z <= maxclients; ++z)
                                                                self = edict_num(shuffleteams_players[z]);
  
                                                        if(self.team != team_color) 
 -                                                              MoveToTeam(self, team_color, 6, 0);
 +                                                              MoveToTeam(self, team_color, 6);
  
                                                        shuffleteams_players[z] = 0;
                                                        shuffleteams_teams[i] = shuffleteams_teams[i] + 1;
diff --combined qcsrc/server/defs.qh
index 0c38a2124e2982fc08b3f038051c67b92d2b0fe0,f777254138e0c0dc4facdb4259567ac397d11cba..60191b5bf38f00935be98358e1b09bffd944abc1
@@@ -39,6 -39,7 +39,6 @@@ float g_pickup_respawntimejitter_poweru
  float g_jetpack;
  
  float sv_clones;
 -float sv_gentle;
  float sv_foginterval;
  
  entity        activator;
@@@ -57,8 -58,6 +57,8 @@@ float team1_score, team2_score, team3_s
  
  float maxclients;
  
 +float server_is_local; // innocent until proven guilty by ClientConnect() in cl_client.qc
 +
  // Fields
  
  .void(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) event_damage;
@@@ -625,7 -624,7 +625,7 @@@ string deathmessage
  #define ACTIVE_BUSY   2
  #define ACTIVE_TOGGLE 3
  .float active;
- .float (float act_state) setactive;
+ .void (float act_state) setactive;
  .entity realowner;
  
  .float nex_charge;
diff --combined qcsrc/server/g_damage.qc
index d7fb5e7b052ab604763a3b0b2c40a64eb61ea016,a3eeefb73033ce71cfa2532ce575378af314904e..3807e7ed9dbe97ee17a9172d4313f79fd046a4cc
@@@ -227,7 -227,7 +227,7 @@@ void GiveFrags (entity attacker, entit
                UpdateFrags(attacker, f);
  }
  
 -string Obituary_ExtraFragInfo(entity player) // Extra fragmessage information
 +/*string Obituary_ExtraFragInfo(entity player) // Extra fragmessage information
  {
        string health_output = string_null;
        string ping_output = string_null;
        }
        
        return output;
 -}
 +}*/
  
  string AppendItemcodes(string s, entity player)
  {
@@@ -297,7 -297,7 +297,7 @@@ void LogDeath(string mode, float deatht
        s = strcat(":kill:", mode);
        s = strcat(s, ":", ftos(killer.playerid));
        s = strcat(s, ":", ftos(killed.playerid));
 -      s = strcat(s, ":type=", ftos(deathtype));
 +      s = strcat(s, ":type=", Deathtype_Name(deathtype));
        s = strcat(s, ":items=");
        s = AppendItemcodes(s, killer);
        if(killed != killer)
        GameLogEcho(s);
  }
  
 -void Send_KillNotification (string s1, string s2, string s3, float msg, float type)
 +void Obituary_SpecialDeath(entity notif_target, float murder, float deathtype, string s1, string s2, float f1, float f2, float f3)
  {
 -      WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
 -      WriteByte(MSG_BROADCAST, TE_CSQC_KILLNOTIFY);
 -      WriteString(MSG_BROADCAST, s1);
 -      WriteString(MSG_BROADCAST, s2);
 -      WriteString(MSG_BROADCAST, s3);
 -      WriteShort(MSG_BROADCAST, msg);
 -      WriteByte(MSG_BROADCAST, type);
 +      float handled, hits;
 +      if(DEATH_ISSPECIAL(deathtype))
 +      {
 +              #define DEATHTYPE(name,msg_death,msg_death_by,position) \
 +                      { if(deathtype == max(0, name)) \
 +                      { \
 +                              #if msg_death != NO_MSG \
 +                                      if not(murder) \
 +                                      { \
 +                                              Send_Notification(notif_target, MSG_ONE, MSG_DEATH, msg_death, s1, s2, f1, f2, f3); \
 +                                              Send_Notification_ToAll(notif_target, TRUE, MSG_INFO, INFO_##msg_death, s1, s2, f1, f2, f3); \
 +                                              ++handled; \
 +                                      } \
 +                              #endif \
 +                              #if msg_death_by != NO_MSG \
 +                                      if(murder) \
 +                                      { \
 +                                              Send_Notification(notif_target, MSG_ONE, MSG_DEATH, msg_death_by, s1, s2, f1, f2, f3); \
 +                                              Send_Notification_ToAll(notif_target, TRUE, MSG_INFO, INFO_##msg_death_by, s1, s2, f1, f2, f3); \
 +                                              ++handled; \
 +                                      } \
 +                              #endif \
 +                              ++hits; \
 +                      } }
 +
 +              DEATHTYPES
 +              #undef DEATHTYPE
 +              
 +              if not(hits)
 +              {
 +                      backtrace("Obituary_SpecialDeath(): Unhandled deathtype- Please notify Samual!\n");
 +              }
 +              if not(handled)
 +              {
 +                      dprint(sprintf("Obituary_SpecialDeath(): ^1Deathtype ^7(%s-%d)^1 has no notification!\n", Deathtype_Name(deathtype), deathtype));
 +                      return;
 +              }
 +      }
  }
  
 -// Function is used to send a generic centerprint whose content CSQC gets to decide (gentle version or not in the below cases)
 -void Send_CSQC_KillCenterprint(entity e, string s1, string s2, float msg, float type)
 +float w_deathtype;
 +float Obituary_WeaponDeath(float murder, float deathtype, string s1, string s2)
  {
 -      if (clienttype(e) == CLIENTTYPE_REAL)
 +      float death_weapon = DEATH_WEAPONOF(deathtype);
 +
 +      if(death_weapon)
        {
 -              msg_entity = e;
 -              WRITESPECTATABLE_MSG_ONE({
 -                      WriteByte(MSG_ONE, SVC_TEMPENTITY);
 -                      WriteByte(MSG_ONE, TE_CSQC_KILLCENTERPRINT);
 -                      WriteString(MSG_ONE, s1);
 -                      WriteString(MSG_ONE, s2);
 -                      WriteShort(MSG_ONE, msg);
 -                      WriteByte(MSG_ONE, type);
 -              });
 +              w_deathtype = deathtype;
 +              float death_message = weapon_action(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
 +              w_deathtype = FALSE;
 +
 +              if(death_message) { Send_Notification(world, MSG_BROADCAST, MSG_WEAPON, death_message, s1, s2, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG); }
 +              else { dprint(sprintf("Obituary_WeaponDeath(): ^1Deathtype ^7(%s-%d)^1 has no notification for weapon %d!\n", Deathtype_Name(deathtype), deathtype, death_weapon)); }
 +
 +              return TRUE;
        }
 +      return FALSE;
  }
  
 -void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
 +.float FRAG_VERBOSE;
 +void Obituary(entity attacker, entity inflictor, entity targ, float deathtype)
  {
 +      // Sanity check
 +      if not(targ.classname == STR_PLAYER) { backtrace("Obituary called on non-player?!\n"); return; }
 +
 +      // Declarations
        string  s, a, msg;
-       float w, type;
+       float type;
  
 -      if (targ.classname == "player")
 -      {
 -              s = targ.netname;
 -              a = attacker.netname;
 +      string s1 = NO_STR_ARG, s2 = NO_STR_ARG;
 +      float f1 = NO_FL_ARG, f2 = NO_FL_ARG, f3 = NO_FL_ARG;
 +      float notif_firstblood;
  
 -              if (targ == attacker) // suicides
 -              {
 -                      if (deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
 -                              msg = ColoredTeamName(targ.team); // TODO: check if needed?
 -                      else
 -                              msg = "";
 -            if(!g_cts) // no "killed your own dumb self" message in CTS
 -                Send_CSQC_KillCenterprint(targ, msg, "", deathtype, MSG_SUICIDE);
 +      //dprint(sprintf("Obituary(): Deathtype = %s (%d), Attacker = %s, Inflictor = %s, Target = %s...\n", Deathtype_Name(deathtype), deathtype, attacker.netname, inflictor.netname, targ.netname));
  
 -                      if(deathtype != DEATH_TEAMCHANGE && deathtype != DEATH_QUIET)
 +      // =======
 +      // SUICIDE
 +      // =======
 +      if(targ == attacker)
 +      {
 +              if(DEATH_ISSPECIAL(deathtype))
 +              {
 +                      if(deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
                        {
 -                              LogDeath("suicide", deathtype, targ, targ);
 -                              GiveFrags(attacker, targ, -1, deathtype);
 +                              s1 = targ.netname;
 +                              f1 = targ.team;
                        }
 -
 -                      if (targ.killcount > 2)
 -                              msg = ftos(targ.killcount);
                        else
 -                              msg = "";
 -                      if(teamplay && deathtype == DEATH_MIRRORDAMAGE)
                        {
 -                              if(attacker.team == COLOR_TEAM1)
 -                                      deathtype = KILL_TEAM_RED;
 -                              else
 -                                      deathtype = KILL_TEAM_BLUE;
 +                              switch(deathtype)
 +                              {
 +                                      case DEATH_MIRRORDAMAGE:
 +                                      {
 +                                              s1 = targ.netname;
 +                                              f1 = targ.killcount;
 +                                              break;
 +                                      }
 +                                      
 +                                      default:
 +                                      {
 +                                              s1 = targ.netname;
 +                                              f1 = targ.killcount;
 +                                              s2 = NO_STR_ARG;
 +                                              f2 = f3 = NO_FL_ARG;
 +                                              break;
 +                                      }
 +                              }
 +                              LogDeath("suicide", deathtype, targ, targ);
 +                              GiveFrags(attacker, targ, -1, deathtype);
                        }
 -
 -                      Send_KillNotification(s, msg, "", deathtype, MSG_SUICIDE);
 +                      
 +                      Obituary_SpecialDeath(targ, FALSE, deathtype, s1, s2, f1, f2, NO_FL_ARG);
                }
 -              else if (attacker.classname == "player")
 +              else if not(Obituary_WeaponDeath(FALSE, deathtype, targ.netname, NO_STR_ARG))
                {
 -                      if(!IsDifferentTeam(attacker, targ))
 -                      {
 -                              if(attacker.team == COLOR_TEAM1)
 -                                      type = KILL_TEAM_RED;
 -                              else
 -                                      type = KILL_TEAM_BLUE;
 +                      backtrace("SUICIDE: what the hell happened here?\n");
 +              }
 +      }
  
 -                              GiveFrags(attacker, targ, -1, deathtype);
 +      // ======
 +      // MURDER
 +      // ======
 +      else if(attacker.classname == "player")
 +      {
 +              s1 = attacker.netname;
 +              s2 = targ.netname;
  
 -                              Send_CSQC_KillCenterprint(attacker, s, "", type, MSG_KILL);
 +              // TODO: ADD REAL CHECK HERE!
 +              attacker.FRAG_VERBOSE = TRUE;
 +              targ.FRAG_VERBOSE = TRUE;
 +              
 +              if(!IsDifferentTeam(attacker, targ))
 +              {
 +                      LogDeath("tk", deathtype, attacker, targ);
 +                      GiveFrags(attacker, targ, -1, deathtype);
  
 -                              if (targ.killcount > 2)
 -                                      msg = ftos(targ.killcount);
 -                              else
 -                                      msg = "";
 +                      attacker.killcount = 0;
 +                      
 +                      Send_Notification(attacker, MSG_ONE, MSG_DEATH, DEATH_TEAMKILL_FRAG, s2, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
 +                      Send_Notification(targ, MSG_ONE, MSG_DEATH, DEATH_TEAMKILL_FRAGGED, s1, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
 +                      Send_Notification(world, MSG_BROADCAST, MSG_INFO, APP_TEAM_NUM_4(targ.team, INFO_DEATH_TEAMKILL_), s2, s1, targ.killcount, NO_FL_ARG, NO_FL_ARG);
  
 -                              if (attacker.killcount > 2) {
 -                                      msg = ftos(attacker.killcount);
 -                                      type = KILL_TEAM_SPREE;
 -                              }
 -                              Send_KillNotification(a, s, msg, type, MSG_KILL);
 +                      // In this case, the death message will ALWAYS be "foo was betrayed by bar"
 +                      // No need for specific death/weapon messages...
 +              }
 +              else
 +              {
 +                      LogDeath("frag", deathtype, attacker, targ);
 +                      GiveFrags(attacker, targ, 1, deathtype);
  
 -                              attacker.killcount = 0;
 +                      attacker.taunt_soundtime = time + 1;
 +                      attacker.killcount = attacker.killcount + 1;
 +                      
 +                      #define ADD_ACHIEVEMENT_CASE(numa,numb) \
 +                              case numa: \
 +                              { \
 +                                      AnnounceTo(attacker, strcat(#numb, "kills")); \
 +                                      PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##numa, 1); \
 +                                      break; \
 +                              }
 +                      switch(attacker.killcount)
 +                      {
 +                              ADD_ACHIEVEMENT_CASE(3, 03)
 +                              ADD_ACHIEVEMENT_CASE(5, 05)
 +                              ADD_ACHIEVEMENT_CASE(10, 10)
 +                              ADD_ACHIEVEMENT_CASE(15, 15)
 +                              ADD_ACHIEVEMENT_CASE(20, 20)
 +                              ADD_ACHIEVEMENT_CASE(25, 25)
 +                              ADD_ACHIEVEMENT_CASE(30, 30)
 +                              default: break;
 +                      }
 +                      #undef ADD_ACHIEVEMENT_CASE
  
 -                              LogDeath("tk", deathtype, attacker, targ);
 +                      if(!checkrules_firstblood)
 +                      {
 +                              checkrules_firstblood = TRUE;
 +                              notif_firstblood = TRUE; // modify the current messages so that they too show firstblood information
 +                              PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
 +                              PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
                        }
 -                      else
 +
 +                      if(notif_firstblood) // first blood, no kill sprees yet
                        {
 -                              if (!checkrules_firstblood)
 +                              if(targ.istypefrag)
                                {
 -                                      checkrules_firstblood = TRUE;
 -                                      Send_KillNotification(a, "", "", KILL_FIRST_BLOOD, MSG_KILL);
 -                                      // TODO: make these print a newline if they dont
 -                                      Send_CSQC_KillCenterprint(attacker, "", "", KILL_FIRST_BLOOD, MSG_KILL);
 -                                      Send_CSQC_KillCenterprint(targ, "", "", KILL_FIRST_VICTIM, MSG_KILL);
 -                                      PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
 -                                      PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
 -                              }
 -
 -                              if(targ.istypefrag) {
 -                                      Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_TYPEFRAG, MSG_KILL);
 -                                      Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_TYPEFRAGGED, MSG_KILL);
 -                              } else {
 -                                      Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_FRAG, MSG_KILL);
 -                                      Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_FRAGGED, MSG_KILL);
 +                                      Send_Notification(attacker, MSG_ONE, MSG_DEATH, (attacker.FRAG_VERBOSE ? DEATH_MURDER_TYPEFRAG_FIRST_VERBOSE : DEATH_MURDER_TYPEFRAG_FIRST),
 +                                              s2, s1, (attacker.FRAG_VERBOSE ? ((clienttype(targ) == CLIENTTYPE_BOT) ? BOT_PING : targ.ping) : NO_FL_ARG), NO_FL_ARG, NO_FL_ARG);
 +                                              
 +                                      Send_Notification(targ, MSG_ONE, MSG_DEATH, (targ.FRAG_VERBOSE ? DEATH_MURDER_TYPEFRAGGED_FIRST_VERBOSE : DEATH_MURDER_TYPEFRAGGED_FIRST),
 +                                              s1, NO_STR_ARG, (targ.FRAG_VERBOSE ? attacker.health : NO_FL_ARG), (targ.FRAG_VERBOSE ? attacker.armorvalue : NO_FL_ARG), (targ.FRAG_VERBOSE ? ((clienttype(attacker) == CLIENTTYPE_BOT) ? BOT_PING : attacker.ping) : NO_FL_ARG));
                                }
 -
 -                              attacker.taunt_soundtime = time + 1;
 -
 -                              if (deathtype == DEATH_HURTTRIGGER && inflictor.message2 != "")
 -                                      msg = inflictor.message2;
 -                              else if (deathtype == DEATH_CUSTOM)
 -                                      msg = deathmessage;
                                else
 -                                      msg = "";
 -
 -                              if(strstrofs(msg, "%", 0) < 0)
 -                                      msg = strcat("%s ", msg, " by %s");
 -
 -                              Send_KillNotification(a, s, msg, deathtype, MSG_KILL);
 -
 -                              GiveFrags(attacker, targ, 1, deathtype);
 -
 -                              if (targ.killcount > 2) {
 -                                      Send_KillNotification(s, ftos(targ.killcount), a, KILL_END_SPREE, MSG_SPREE);
 -                              }
 -
 -                              attacker.killcount = attacker.killcount + 1;
 -
 -                              if (attacker.killcount == 3)
 -                              {
 -                                      Send_KillNotification(a, "", "", KILL_SPREE_3, MSG_SPREE);
 -                                      AnnounceTo(attacker, "03kills");
 -                                      PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3, 1);
 -                              }
 -                              else if (attacker.killcount == 5)
 -                              {
 -                                      Send_KillNotification(a, "", "", KILL_SPREE_5, MSG_SPREE);
 -                                      AnnounceTo(attacker, "05kills");
 -                                      PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5, 1);
 -                              }
 -                              else if (attacker.killcount == 10)
 -                              {
 -                                      Send_KillNotification(a, "", "", KILL_SPREE_10, MSG_SPREE);
 -                                      AnnounceTo(attacker, "10kills");
 -                                      PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10, 1);
 -                              }
 -                              else if (attacker.killcount == 15)
 -                              {
 -                                      Send_KillNotification(a, "", "", KILL_SPREE_15, MSG_SPREE);
 -                                      AnnounceTo(attacker, "15kills");
 -                                      PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15, 1);
 -                              }
 -                              else if (attacker.killcount == 20)
                                {
 -                                      Send_KillNotification(a, "", "", KILL_SPREE_20, MSG_SPREE);
 -                                      AnnounceTo(attacker, "20kills");
 -                                      PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20, 1);
 +                                      Send_Notification(attacker, MSG_ONE, MSG_DEATH, (attacker.FRAG_VERBOSE ? DEATH_MURDER_FRAG_FIRST_VERBOSE : DEATH_MURDER_FRAG_FIRST),
 +                                              s2, s1, (attacker.FRAG_VERBOSE ? ((clienttype(targ) == CLIENTTYPE_BOT) ? BOT_PING : targ.ping) : NO_FL_ARG), NO_FL_ARG, NO_FL_ARG);
 +                                              
 +                                      Send_Notification(targ, MSG_ONE, MSG_DEATH, (targ.FRAG_VERBOSE ? DEATH_MURDER_FRAGGED_FIRST_VERBOSE : DEATH_MURDER_FRAGGED_FIRST),
 +                                              s1, NO_STR_ARG, (targ.FRAG_VERBOSE ? attacker.health : NO_FL_ARG), (targ.FRAG_VERBOSE ? attacker.armorvalue : NO_FL_ARG), (targ.FRAG_VERBOSE ? ((clienttype(attacker) == CLIENTTYPE_BOT) ? BOT_PING : attacker.ping) : NO_FL_ARG));
                                }
 -                              else if (attacker.killcount == 25)
 +                      }
 +                      else // normal frags, kill sprees listed
 +                      {
 +                              if(targ.istypefrag)
                                {
 -                                      Send_KillNotification(a, "", "", KILL_SPREE_25, MSG_SPREE);
 -                                      AnnounceTo(attacker, "25kills");
 -                                      PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25, 1);
 +                                      Send_Notification(attacker, MSG_ONE, MSG_DEATH, (attacker.FRAG_VERBOSE ? DEATH_MURDER_TYPEFRAG_VERBOSE : DEATH_MURDER_TYPEFRAG),
 +                                              s2, NO_STR_ARG, attacker.killcount, (attacker.FRAG_VERBOSE ? ((clienttype(targ) == CLIENTTYPE_BOT) ? BOT_PING : targ.ping) : NO_FL_ARG), NO_FL_ARG);
 +                                              
 +                                      Send_Notification(targ, MSG_ONE, MSG_DEATH, (targ.FRAG_VERBOSE ? DEATH_MURDER_TYPEFRAGGED_VERBOSE : DEATH_MURDER_TYPEFRAGGED),
 +                                              s1, NO_STR_ARG, (targ.FRAG_VERBOSE ? attacker.health : NO_FL_ARG), (targ.FRAG_VERBOSE ? attacker.armorvalue : NO_FL_ARG), (targ.FRAG_VERBOSE ? ((clienttype(attacker) == CLIENTTYPE_BOT) ? BOT_PING : attacker.ping) : NO_FL_ARG));
                                }
 -                              else if (attacker.killcount == 30)
 +                              else
                                {
 -                                      Send_KillNotification(a, "", "", KILL_SPREE_30, MSG_SPREE);
 -                                      AnnounceTo(attacker, "30kills");
 -                                      PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30, 1);
 -                              }
 -                              else if (attacker.killcount > 2) {
 -                                      Send_KillNotification(a, ftos(attacker.killcount), "", KILL_SPREE, MSG_SPREE);
 +                                      Send_Notification(attacker, MSG_ONE, MSG_DEATH, (attacker.FRAG_VERBOSE ? DEATH_MURDER_FRAG_VERBOSE : DEATH_MURDER_FRAG),
 +                                              s2, NO_STR_ARG, attacker.killcount, (attacker.FRAG_VERBOSE ? ((clienttype(targ) == CLIENTTYPE_BOT) ? BOT_PING : targ.ping) : NO_FL_ARG), NO_FL_ARG);
 +                                              
 +                                      Send_Notification(targ, MSG_ONE, MSG_DEATH, (targ.FRAG_VERBOSE ? DEATH_MURDER_FRAGGED_VERBOSE : DEATH_MURDER_FRAGGED),
 +                                              s1, NO_STR_ARG, (targ.FRAG_VERBOSE ? attacker.health : NO_FL_ARG), (targ.FRAG_VERBOSE ? attacker.armorvalue : NO_FL_ARG), (targ.FRAG_VERBOSE ? ((clienttype(attacker) == CLIENTTYPE_BOT) ? BOT_PING : attacker.ping) : NO_FL_ARG));
                                }
 -                              LogDeath("frag", deathtype, attacker, targ);
                        }
 +                      
 +                      if not(Obituary_WeaponDeath(TRUE, deathtype, targ.netname, attacker.netname))
 +                              Obituary_SpecialDeath(targ, TRUE, deathtype, s2, s1, targ.killcount, NO_FL_ARG, NO_FL_ARG);
                }
 -              else
 +      }
 +
 +      // =============
 +      // ACCIDENT/TRAP
 +      // =============
 +      else
 +      {
 +              switch(deathtype)
                {
 -                      Send_CSQC_KillCenterprint(targ, "", "", deathtype, MSG_KILL_ACTION);
 -                      if (deathtype == DEATH_HURTTRIGGER && inflictor.message != "")
 -                              msg = inflictor.message;
 -                      else if (deathtype == DEATH_CUSTOM)
 -                              msg = deathmessage;
 -                      else
 -                              msg = "";
 -                      if(strstrofs(msg, "%", 0) < 0)
 -                              msg = strcat("%s ", msg);
 -
 -                      GiveFrags(targ, targ, -1, deathtype);
 -                      if(PlayerScore_Add(targ, SP_SCORE, 0) == -5) {
 -                              AnnounceTo(targ, "botlike");
 -                              PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
 +                      // For now, we're just forcing HURTTRIGGER to behave as "DEATH_VOID" and giving it no special options...
 +                      // Later on you will only be able to make custom messages using DEATH_CUSTOM,
 +                      // and there will be a REAL DEATH_VOID implementation which mappers will use.
 +                      /*case DEATH_HURTTRIGGER:
 +                      {
 +                              s1 = targ.netname;
 +                              s2 = inflictor.message;
 +                              if(strstrofs(s2, "%", 0) < 0) { s2 = strcat("%s ", s2); }
 +                              break;
 +                      }*/
 +
 +                      case DEATH_CUSTOM:
 +                      {
 +                              s1 = targ.netname;
 +                              s2 = deathmessage;
 +                              f1 = targ.killcount;
 +                              if(strstrofs(s2, "%", 0) < 0) { s2 = strcat("%s ", s2); }
 +                              f2 = f3 = NO_FL_ARG;
 +                              break;
                        }
 -                      Send_KillNotification(s, msg, "", deathtype, MSG_KILL_ACTION);
 +                      
 +                      default:
 +                      {
 +                              s1 = targ.netname;
 +                              f1 = targ.killcount;
 +                              s2 = NO_STR_ARG;
 +                              f2 = f3 = NO_FL_ARG;
 +                              break;
 +                      }
 +              }
  
 -                      if (targ.killcount > 2)
 -                              Send_KillNotification(s, ftos(targ.killcount), "", 0, MSG_KILL_ACTION_SPREE);
 +              LogDeath("accident", deathtype, targ, targ);
 +              GiveFrags(targ, targ, -1, deathtype);
  
 -                      LogDeath("accident", deathtype, targ, targ);
 +              if(PlayerScore_Add(targ, SP_SCORE, 0) == -5)
 +              {
 +                      AnnounceTo(targ, "botlike");
 +                      PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
                }
  
 -              targ.death_origin = targ.origin;
 -              if(targ != attacker)
 -                      targ.killer_origin = attacker.origin;
 -
 -              // FIXME: this should go in PutClientInServer
 -              if (targ.killcount)
 -                      targ.killcount = 0;
 +              Obituary_SpecialDeath(targ, FALSE, deathtype, s1, s2, f1, f2, f3);
        }
 +
 +      // Set final information for the death
 +      targ.death_origin = targ.origin;
 +      if(targ != attacker) { targ.killer_origin = attacker.origin; }
 +      if(targ.killcount) { targ.killcount = 0; }
  }
  
  // these are updated by each Damage call for use in button triggering and such
@@@ -633,7 -571,7 +633,7 @@@ void Damage (entity targ, entity inflic
                        }
        }
  
 -      if(deathtype == DEATH_KILL || deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE || deathtype == DEATH_QUIET)
 +      if(deathtype == DEATH_KILL || deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
        {
                // These are ALWAYS lethal
                // No damage modification here
diff --combined qcsrc/server/g_world.qc
index 36885d95acb6029fcc0200462e87a2535e419052,8698b1753884f7e06e23ea4dd0890f41ee0af179..1862ba8cb92a214e7ff656638d8d5c864865226e
@@@ -553,8 -553,6 +553,8 @@@ void spawnfunc___init_dedicated_server(
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
 +      CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
 +      CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
  
        MapInfo_Enumerate();
        MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
@@@ -601,8 -599,6 +601,8 @@@ void spawnfunc_worldspawn (void
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
 +      CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
 +      CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
  
        ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
  
@@@ -1617,6 -1613,8 +1617,8 @@@ void NextLevel(
        if(autocvar_g_campaign)
                CampaignPreIntermission();
  
+       MUTATOR_CALLHOOK(MatchEnd);
        localcmd("\nsv_hook_gameend\n");
  }
  
@@@ -1763,10 -1761,10 +1765,10 @@@ float WinningCondition_Onslaught(
        {
                if (head.health > 0)
                {
 -                      if (head.team == COLOR_TEAM1) t1 = 1;
 -                      if (head.team == COLOR_TEAM2) t2 = 1;
 -                      if (head.team == COLOR_TEAM3) t3 = 1;
 -                      if (head.team == COLOR_TEAM4) t4 = 1;
 +                      if (head.team == FL_TEAM_1) t1 = 1;
 +                      if (head.team == FL_TEAM_2) t2 = 1;
 +                      if (head.team == FL_TEAM_3) t3 = 1;
 +                      if (head.team == FL_TEAM_4) t4 = 1;
                }
                head = find(head, classname, "onslaught_generator");
        }
        {
                // game over, only one team remains (or none)
                ClearWinners();
 -              if (t1) SetWinners(team, COLOR_TEAM1);
 -              if (t2) SetWinners(team, COLOR_TEAM2);
 -              if (t3) SetWinners(team, COLOR_TEAM3);
 -              if (t4) SetWinners(team, COLOR_TEAM4);
 +              if (t1) SetWinners(team, FL_TEAM_1);
 +              if (t2) SetWinners(team, FL_TEAM_2);
 +              if (t3) SetWinners(team, FL_TEAM_3);
 +              if (t4) SetWinners(team, FL_TEAM_4);
                dprint("Have a winner, ending game.\n");
                return WINNING_YES;
        }
@@@ -1815,13 -1813,13 +1817,13 @@@ float WinningCondition_Assault(
  
        status = WINNING_NO;
        // as the timelimit has not yet passed just assume the defending team will win
 -      if(assault_attacker_team == COLOR_TEAM1)
 +      if(assault_attacker_team == FL_TEAM_1)
        {
 -              SetWinners(team, COLOR_TEAM2);
 +              SetWinners(team, FL_TEAM_2);
        }
        else
        {
 -              SetWinners(team, COLOR_TEAM1);
 +              SetWinners(team, FL_TEAM_1);
        }
  
        entity ent;
@@@ -1947,10 -1945,10 +1949,10 @@@ float WinningCondition_Scores(float lim
  
        if(teamplay)
        {
 -              team1_score = TeamScore_GetCompareValue(COLOR_TEAM1);
 -              team2_score = TeamScore_GetCompareValue(COLOR_TEAM2);
 -              team3_score = TeamScore_GetCompareValue(COLOR_TEAM3);
 -              team4_score = TeamScore_GetCompareValue(COLOR_TEAM4);
 +              team1_score = TeamScore_GetCompareValue(FL_TEAM_1);
 +              team2_score = TeamScore_GetCompareValue(FL_TEAM_2);
 +              team3_score = TeamScore_GetCompareValue(FL_TEAM_3);
 +              team4_score = TeamScore_GetCompareValue(FL_TEAM_4);
        }
  
        ClearWinners();
@@@ -2066,25 -2064,25 +2068,25 @@@ float WinningCondition_RanOutOfSpawns(
  
        FOR_EACH_PLAYER(head) if(head.deadflag == DEAD_NO)
        {
 -              if(head.team == COLOR_TEAM1)
 +              if(head.team == FL_TEAM_1)
                        team1_score = 1;
 -              else if(head.team == COLOR_TEAM2)
 +              else if(head.team == FL_TEAM_2)
                        team2_score = 1;
 -              else if(head.team == COLOR_TEAM3)
 +              else if(head.team == FL_TEAM_3)
                        team3_score = 1;
 -              else if(head.team == COLOR_TEAM4)
 +              else if(head.team == FL_TEAM_4)
                        team4_score = 1;
        }
  
        for(head = world; (head = find(head, classname, "info_player_deathmatch")) != world; )
        {
 -              if(head.team == COLOR_TEAM1)
 +              if(head.team == FL_TEAM_1)
                        team1_score = 1;
 -              else if(head.team == COLOR_TEAM2)
 +              else if(head.team == FL_TEAM_2)
                        team2_score = 1;
 -              else if(head.team == COLOR_TEAM3)
 +              else if(head.team == FL_TEAM_3)
                        team3_score = 1;
 -              else if(head.team == COLOR_TEAM4)
 +              else if(head.team == FL_TEAM_4)
                        team4_score = 1;
        }
  
        {
                float t, i;
                if(team1_score)
 -                      t = COLOR_TEAM1;
 +                      t = FL_TEAM_1;
                else if(team2_score)
 -                      t = COLOR_TEAM2;
 +                      t = FL_TEAM_2;
                else if(team3_score)
 -                      t = COLOR_TEAM3;
 +                      t = FL_TEAM_3;
                else // if(team4_score)
 -                      t = COLOR_TEAM4;
 +                      t = FL_TEAM_4;
                CheckAllowedTeams(world);
                for(i = 0; i < MAX_TEAMSCORE; ++i)
                {
 -                      if(t != COLOR_TEAM1) if(c1 >= 0) TeamScore_AddToTeam(COLOR_TEAM1, i, -1000);
 -                      if(t != COLOR_TEAM2) if(c2 >= 0) TeamScore_AddToTeam(COLOR_TEAM2, i, -1000);
 -                      if(t != COLOR_TEAM3) if(c3 >= 0) TeamScore_AddToTeam(COLOR_TEAM3, i, -1000);
 -                      if(t != COLOR_TEAM4) if(c4 >= 0) TeamScore_AddToTeam(COLOR_TEAM4, i, -1000);
 +                      if(t != FL_TEAM_1) if(c1 >= 0) TeamScore_AddToTeam(FL_TEAM_1, i, -1000);
 +                      if(t != FL_TEAM_2) if(c2 >= 0) TeamScore_AddToTeam(FL_TEAM_2, i, -1000);
 +                      if(t != FL_TEAM_3) if(c3 >= 0) TeamScore_AddToTeam(FL_TEAM_3, i, -1000);
 +                      if(t != FL_TEAM_4) if(c4 >= 0) TeamScore_AddToTeam(FL_TEAM_4, i, -1000);
                }
  
                AddWinners(team, t);
index 89e35d3242d175eb3e4d4ebd800ddc52cc97e708,ffbc74448e518f0cf47d38645dade5d2de906327..e0f899486a450d3a17125dc57e65c4d03d5ebd73
@@@ -32,6 -32,7 +32,6 @@@ void WarpZone_crosshair_trace(entity pl
  void() spawnfunc_info_player_deathmatch; // needed for the other spawnpoints
  void() spawnpoint_use;
  string GetMapname();
 -string ColoredTeamName(float t);
  
  string admin_name(void)
  {
@@@ -610,6 -611,85 +610,6 @@@ void backtrace(string msg
      cvar_set("prvm_backtraceforwarnings", ftos(war));
  }
  
 -string Team_ColorCode(float teamid)
 -{
 -    if (teamid == COLOR_TEAM1)
 -        return "^1";
 -    else if (teamid == COLOR_TEAM2)
 -        return "^4";
 -    else if (teamid == COLOR_TEAM3)
 -        return "^3";
 -    else if (teamid == COLOR_TEAM4)
 -        return "^6";
 -    else
 -        return "^7";
 -}
 -
 -string Team_ColorName(float t)
 -{
 -    // fixme: Search for team entities and get their .netname's!
 -    if (t == COLOR_TEAM1)
 -        return "Red";
 -    if (t == COLOR_TEAM2)
 -        return "Blue";
 -    if (t == COLOR_TEAM3)
 -        return "Yellow";
 -    if (t == COLOR_TEAM4)
 -        return "Pink";
 -    return "Neutral";
 -}
 -
 -string Team_ColorNameLowerCase(float t)
 -{
 -    // fixme: Search for team entities and get their .netname's!
 -    if (t == COLOR_TEAM1)
 -        return "red";
 -    if (t == COLOR_TEAM2)
 -        return "blue";
 -    if (t == COLOR_TEAM3)
 -        return "yellow";
 -    if (t == COLOR_TEAM4)
 -        return "pink";
 -    return "neutral";
 -}
 -
 -float ColourToNumber(string team_colour)
 -{
 -      if (team_colour == "red")
 -              return COLOR_TEAM1;
 -
 -      if (team_colour == "blue")
 -              return COLOR_TEAM2;
 -
 -      if (team_colour == "yellow")
 -              return COLOR_TEAM3;
 -
 -      if (team_colour == "pink")
 -              return COLOR_TEAM4;
 -
 -      if (team_colour == "auto")
 -              return 0;
 -
 -      return -1;
 -}
 -
 -float NumberToTeamNumber(float number)
 -{
 -      if (number == 1)
 -              return COLOR_TEAM1;
 -
 -      if (number == 2)
 -              return COLOR_TEAM2;
 -
 -      if (number == 3)
 -              return COLOR_TEAM3;
 -
 -      if (number == 4)
 -              return COLOR_TEAM4;
 -
 -      return -1;
 -}
 -
  // decolorizes and team colors the player name when needed
  string playername(entity p)
  {
@@@ -1091,6 -1171,7 +1091,6 @@@ void readlevelcvars(void
  #endif
  
        sv_clones = cvar("sv_clones");
 -      sv_gentle = cvar("sv_gentle");
        sv_foginterval = cvar("sv_foginterval");
        g_cloaked = cvar("g_cloaked");
      if(g_cts)
@@@ -1518,9 -1599,6 +1518,6 @@@ void precache(
      precache_sound ("player/lava.wav");
      precache_sound ("player/slime.wav");
  
-     if (g_jetpack)
-         precache_sound ("misc/jetpack_fly.wav");
      precache_model ("models/sprites/0.spr32");
      precache_model ("models/sprites/1.spr32");
      precache_model ("models/sprites/2.spr32");
  #endif
  }
  
 -// sorry, but using \ in macros breaks line numbers
 -#define WRITESPECTATABLE_MSG_ONE_VARNAME(varname,statement) entity varname; varname = msg_entity; FOR_EACH_REALCLIENT(msg_entity) if(msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) statement msg_entity = varname
 -#define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
 -#define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
 -
 -
 -void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, float countdown_num)
 -{
 -      if ((clienttype(e) == CLIENTTYPE_REAL) && (e.flags & FL_CLIENT))
 -      {
 -              msg_entity = e;
 -              WRITESPECTATABLE_MSG_ONE({
 -                      WriteByte(MSG_ONE, SVC_TEMPENTITY);
 -                      WriteByte(MSG_ONE, TE_CSQC_CENTERPRINT_GENERIC);
 -                      WriteByte(MSG_ONE, id);
 -                      WriteString(MSG_ONE, s);
 -                      if (id != 0 && s != "")
 -                      {
 -                              WriteByte(MSG_ONE, duration);
 -                              WriteByte(MSG_ONE, countdown_num);
 -                      }
 -              });
 -      }
 -}
 -void Send_CSQC_Centerprint_Generic_Expire(entity e, float id)
 -{
 -      Send_CSQC_Centerprint_Generic(e, id, "", 1, 0);
 -}
  // WARNING: this kills the trace globals
  #define EXACTTRIGGER_TOUCH if(WarpZoneLib_ExactTrigger_Touch()) return
  #define EXACTTRIGGER_INIT  WarpZoneLib_ExactTrigger_Init()
@@@ -1715,7 -1821,7 +1712,7 @@@ void InitializeEntitiesRun(
              self = e_old;
          }
          //dprint("Delayed initialization: ", self.classname, "\n");
-         if(func != func_null)
+         if(func)
              func();
          else
          {
@@@ -1741,7 -1847,7 +1738,7 @@@ void SetCustomizer(entity e, float(void
  {
      e.customizeentityforclient = customizer;
      e.uncustomizeentityforclient = uncustomizer;
-     e.uncustomizeentityforclient_set = (uncustomizer != func_null);
+     e.uncustomizeentityforclient_set = !!uncustomizer;
  }
  
  .float nottargeted;
@@@ -2419,43 -2525,6 +2416,6 @@@ vector gettaginfo_relative(entity e, fl
      return gettaginfo(gettaginfo_relative_ent, tag);
  }
  
- void SoundEntity_StartSound(entity pl, float chan, string samp, float vol, float attn)
- {
-     float p;
-     p = pow(2, chan);
-     if (pl.soundentity.cnt & p)
-         return;
-     soundtoat(MSG_ALL, pl.soundentity, gettaginfo(pl.soundentity, 0), chan, samp, vol, attn);
-     pl.soundentity.cnt |= p;
- }
- void SoundEntity_StopSound(entity pl, float chan)
- {
-     float p;
-     p = pow(2, chan);
-     if (pl.soundentity.cnt & p)
-     {
-         stopsoundto(MSG_ALL, pl.soundentity, chan);
-         pl.soundentity.cnt &~= p;
-     }
- }
- void SoundEntity_Attach(entity pl)
- {
-     pl.soundentity = spawn();
-     pl.soundentity.classname = "soundentity";
-     pl.soundentity.owner = pl;
-     setattachment(pl.soundentity, pl, "");
-     setmodel(pl.soundentity, "null");
- }
- void SoundEntity_Detach(entity pl)
- {
-     float i;
-     for (i = 0; i <= 7; ++i)
-         SoundEntity_StopSound(pl, i);
- }
  .float scale2;
  
  float modeleffect_SendEntity(entity to, float sf)
@@@ -2706,8 -2775,3 +2666,8 @@@ float isPushable(entity e
                return TRUE;
        return FALSE;
  }
 +
 +void dedicated_print(string input) // print(), but only print if the server is not local
 +{
 +      if not(server_is_local) { print(input); }
 +}
index e3be6096d592f0950dce340d8d684b094c77b51c,908d81cf3fe0a9d96b13a1c529a8db568f5008a9..e8fa4639b888ef90c53ba6ca5b4a3061e1a7e69e
@@@ -20,39 -20,36 +20,39 @@@ void ctf_EventLog(string mode, float fl
                GameLogEcho(strcat(":ctf:", mode, ":", ftos(flagteam), ((actor != world) ? (strcat(":", ftos(actor.playerid))) : "")));
  }
  
 -string ctf_CaptureRecord(entity flag, entity player)
 +void ctf_CaptureRecord(entity flag, entity player)
  {
 -      float cap_time, cap_record, success;
 -      string cap_message = string_null, refername;
 -      
 -      if((autocvar_g_ctf_captimerecord_always) || (player_count - currentbots)) 
 -      {
 -              cap_record = ctf_captimerecord;
 -              cap_time = (time - flag.ctf_pickuptime);
 -
 -              refername = db_get(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"));
 -              refername = ((refername == player.netname) ? "their" : strcat(refername, "^7's"));
 -
 -              if(!ctf_captimerecord) 
 -                      { cap_message = strcat(" in ", ftos_decimals(cap_time, 2), " seconds"); success = TRUE; }
 -              else if(cap_time < cap_record) 
 -                      { cap_message = strcat(" in ", ftos_decimals(cap_time, 2), " seconds, breaking ", refername, " previous record of ", ftos_decimals(cap_record, 2), " seconds"); success = TRUE; }
 -              else
 -                      { cap_message = strcat(" in ", ftos_decimals(cap_time, 2), " seconds, failing to break ", refername, " record of ", ftos_decimals(cap_record, 2), " seconds"); success = FALSE; }
 +      entity tmp_entity;
 +      float notification, success;
 +      float cap_record = ctf_captimerecord;
 +      float cap_time = (time - flag.ctf_pickuptime);
 +      float f1, f2 = NO_FL_ARG;
 +      string s1, s2 = NO_STR_ARG;
 +      string refername = db_get(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"));
 +      
 +      // figure shit out
 +      if(!ctf_captimerecord) 
 +              { notification = APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_TIME_); s1 = player.netname; f1 = (cap_time * 100); success = TRUE; }
 +      else if(cap_time < cap_record) 
 +              { notification = APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_BROKEN_); s1 = player.netname; s2 = refername; f1 = (cap_time * 100); f2 = (cap_record * 100); success = TRUE; }
 +      else
 +              { notification = APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_UNBROKEN_); s1 = player.netname; s2 = refername; f1 = (cap_time * 100); f2 = (cap_record * 100); success = FALSE; }
  
 -              if(success) 
 -              {
 -                      ctf_captimerecord = cap_time;
 -                      db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/time"), ftos(cap_time));
 -                      db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"), player.netname);
 -                      write_recordmarker(player, (time - cap_time), cap_time); 
 -              } 
 +      // notify about shit
 +      FOR_EACH_REALCLIENT(tmp_entity)
 +      {
 +              if not(tmp_entity.CAPTURE_VERBOSE) { notification = APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_); s2 = NO_STR_ARG; f1 = f2 = NO_FL_ARG; }
 +              Send_Notification(tmp_entity, MSG_ONE, MSG_INFO, notification, s1, s2, f1, f2, NO_FL_ARG);
        }
 -      
 -      return cap_message;
 +
 +      // write that shit in the database
 +      if(success) 
 +      {
 +              ctf_captimerecord = cap_time;
 +              db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/time"), ftos(cap_time));
 +              db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"), player.netname);
 +              write_recordmarker(player, (time - cap_time), cap_time); 
 +      } 
  }
  
  void ctf_FlagcarrierWaypoints(entity player)
@@@ -169,9 -166,9 +169,9 @@@ void ctf_CaptureShield_Update(entity pl
        if((wanted_status == player.ctf_captureshielded) && (updated_status != wanted_status)) // 0: shield only, 1: unshield only
        {
                if(updated_status) // TODO csqc notifier for this // Samual: How?
 -                      Send_CSQC_Centerprint_Generic(player, CPID_CTF_CAPTURESHIELD, "^3You are now ^4shielded^3 from the flag\n^3for ^1too many unsuccessful attempts^3 to capture.\n\n^3Make some defensive scores before trying again.", 5, 0);
 +                      Send_Notification(player, MSG_ONE, MSG_CENTER, CENTER_CTF_CAPTURESHIELD_SHIELDED, NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
                else
 -                      Send_CSQC_Centerprint_Generic(player, CPID_CTF_CAPTURESHIELD, "^3You are now free.\n\n^3Feel free to ^1try to capture^3 the flag again\n^3if you think you will succeed.", 5, 0);
 +                      Send_Notification(player, MSG_ONE, MSG_CENTER, CENTER_CTF_CAPTURESHIELD_FREE, NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
                        
                player.ctf_captureshielded = updated_status;
        }
@@@ -194,7 -191,7 +194,7 @@@ void ctf_CaptureShield_Touch(
        vector othermid = (other.absmin + other.absmax) * 0.5;
  
        Damage(other, self, self, 0, DEATH_HURTTRIGGER, mymid, normalize(othermid - mymid) * ctf_captureshield_force);
 -      Send_CSQC_Centerprint_Generic(other, CPID_CTF_CAPTURESHIELD, "^3You are ^4shielded^3 from the flag\n^3for ^1too many unsuccessful attempts^3 to capture.\n\n^3Get some defensive scores before trying again.", 5, 0);
 +      Send_Notification(other, MSG_ONE, MSG_CENTER, CENTER_CTF_CAPTURESHIELD_SHIELDED, NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
  }
  
  void ctf_CaptureShield_Spawn(entity flag)
@@@ -237,7 -234,7 +237,7 @@@ void ctf_Handle_Drop(entity flag, entit
        flag.ctf_status = FLAG_DROPPED;
        
        // messages and sounds
 -      Send_KillNotification(player.netname, flag.netname, "", INFO_LOSTFLAG, MSG_INFO);
 +      Send_Notification(world, MSG_BROADCAST, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_LOST_), player.netname, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
        sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTN_NONE);
        ctf_EventLog("dropped", player.team, player);
  
@@@ -290,11 -287,11 +290,11 @@@ void ctf_Handle_Retrieve(entity flag, e
        FOR_EACH_REALPLAYER(tmp_player)
        {
                if(tmp_player == sender)
 -                      centerprint(tmp_player, strcat("You passed the ", flag.netname, " to ", player.netname));
 +                      Send_Notification(tmp_player, MSG_ONE, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PASS_SENT_), player.netname, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
                else if(tmp_player == player)
 -                      centerprint(tmp_player, strcat("You received the ", flag.netname, " from ", sender.netname));
 +                      Send_Notification(tmp_player, MSG_ONE, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PASS_RECEIVED_), sender.netname, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
                else if(!IsDifferentTeam(tmp_player, sender))
 -                      centerprint(tmp_player, strcat(sender.netname, " passed the ", flag.netname, " to ", player.netname));
 +                      Send_Notification(tmp_player, MSG_ONE, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PASS_OTHER_), sender.netname, player.netname, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
        }
        
        // create new waypoint
@@@ -407,7 -404,7 +407,7 @@@ void ctf_Handle_Capture(entity flag, en
        if not(player) { return; } // without someone to give the reward to, we can't possibly cap
        
        // messages and sounds
 -      Send_KillNotification(player.netname, enemy_flag.netname, ctf_CaptureRecord(enemy_flag, player), INFO_CAPTUREFLAG, MSG_INFO);
 +      ctf_CaptureRecord(enemy_flag, player);
        sound(player, CH_TRIGGER, flag.snd_flag_capture, VOL_BASE, ATTN_NONE);
        
        switch(capturetype)
  void ctf_Handle_Return(entity flag, entity player)
  {
        // messages and sounds
 -      //centerprint(player, strcat("You returned the ", flag.netname));
 -      Send_KillNotification(player.netname, flag.netname, "", INFO_RETURNFLAG, MSG_INFO);
 +      Send_Notification(player, MSG_ONE, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_RETURN_), NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
 +      Send_Notification(world, MSG_BROADCAST, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_RETURN_), player.netname, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
        sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTN_NONE);
        ctf_EventLog("return", flag.team, player);
  
@@@ -474,6 -471,7 +474,6 @@@ void ctf_Handle_Pickup(entity flag, ent
  {
        // declarations
        entity tmp_player; // temporary entity which the FOR_EACH_PLAYER loop uses to scan players
 -      string verbosename; // holds the name of the player OR no name at all for printing in the centerprints
        float pickup_dropped_score; // used to calculate dropped pickup score
        
        // attach the flag to the player
        }
  
        // messages and sounds
 -      Send_KillNotification (player.netname, flag.netname, "", INFO_GOTFLAG, MSG_INFO);
 +      Send_Notification(world, MSG_BROADCAST, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_PICKUP_), player.netname, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
        sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTN_NONE);
 -      verbosename = ((autocvar_g_ctf_flag_pickup_verbosename) ? strcat(Team_ColorCode(player.team), "(^7", player.netname, Team_ColorCode(player.team), ") ") : "");
 -      
 +
        FOR_EACH_REALPLAYER(tmp_player)
        {
                if(tmp_player == player)
                {
 -                      centerprint(tmp_player, strcat("You got the ", flag.netname, "!"));
 -                      //if(ctf_stalemate) { centerprint(tmp_player, "Stalemate! Enemies can see you on radar!"); }
 +                      Send_Notification(tmp_player, MSG_ONE, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PICKUP_), NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
 +                      if(ctf_stalemate) { Send_Notification(player, MSG_ONE, MSG_CENTER, CENTER_CTF_STALEMATE_CARRIER, NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG); }
                }
 -              //else if(!IsDifferentTeam(tmp_player, player))
 -              //      centerprint(tmp_player, strcat("Your ", Team_ColorCode(player.team), "team mate ", verbosename, "^7got the flag! Protect them!"));
 -              else if(!IsDifferentTeam(tmp_player, flag))
 -                      centerprint(tmp_player, strcat("The ", Team_ColorCode(player.team), "enemy ", verbosename, "^7got your flag! Retrieve it!"));
 +              else if(!IsDifferentTeam(tmp_player, player) && tmp_player != player)
 +                      Send_Notification(tmp_player, MSG_ONE, MSG_CENTER, (tmp_player.PICKUP_TEAM_VERBOSE ? CENTER_CTF_PICKUP_TEAM_VERBOSE : CENTER_CTF_PICKUP_TEAM), Team_ColorCode(player.team), (tmp_player.PICKUP_TEAM_VERBOSE ? player.netname : NO_STR_ARG), NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
 +              else if(IsDifferentTeam(tmp_player, player))
 +                      Send_Notification(tmp_player, MSG_ONE, MSG_CENTER, (tmp_player.PICKUP_ENEMY_VERBOSE ? CENTER_CTF_PICKUP_ENEMY_VERBOSE : CENTER_CTF_PICKUP_ENEMY), Team_ColorCode(player.team), (tmp_player.PICKUP_ENEMY_VERBOSE ? player.netname : NO_STR_ARG), NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
        }
        
        // scoring
@@@ -569,14 -568,14 +569,14 @@@ void ctf_CheckFlagReturn(entity flag, f
                {
                        switch(returntype)
                        {
 -                              case RETURN_DROPPED: bprint("The ", flag.netname, " was dropped in the base and returned itself\n"); break;
 -                              case RETURN_DAMAGE: bprint("The ", flag.netname, " was destroyed and returned to base\n"); break;
 -                              case RETURN_SPEEDRUN: bprint("The ", flag.netname, " became impatient after ", ftos_decimals(ctf_captimerecord, 2), " seconds and returned itself\n"); break;
 -                              case RETURN_NEEDKILL: bprint("The ", flag.netname, " fell somewhere it couldn't be reached and returned to base\n"); break;
 +                              case RETURN_DROPPED: Send_Notification(world, MSG_BROADCAST, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_DROPPED_), NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG); break;
 +                              case RETURN_DAMAGE: Send_Notification(world, MSG_BROADCAST, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_DAMAGED_), NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG); break;
 +                              case RETURN_SPEEDRUN: Send_Notification(world, MSG_BROADCAST, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_SPEEDRUN_), NO_STR_ARG, NO_STR_ARG, ctf_captimerecord, NO_FL_ARG, NO_FL_ARG); break;
 +                              case RETURN_NEEDKILL: Send_Notification(world, MSG_BROADCAST, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_NEEDKILL_), NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG); break;
                                
                                default:
                                case RETURN_TIMEOUT:
 -                                      { bprint("The ", flag.netname, " has returned to base\n"); break; }
 +                                      { Send_Notification(world, MSG_BROADCAST, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_TIMEOUT_), NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG); break; }
                        }
                        sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTN_NONE);
                        ctf_EventLog("returned", flag.team, world);
@@@ -605,8 -604,8 +605,8 @@@ void ctf_CheckStalemate(void
                        
                        switch(tmp_entity.team)
                        {
 -                              case COLOR_TEAM1: ++stale_red_flags; break;
 -                              case COLOR_TEAM2: ++stale_blue_flags; break;
 +                              case FL_TEAM_1: ++stale_red_flags; break;
 +                              case FL_TEAM_2: ++stale_blue_flags; break;
                        }
                }
        }
                {
                        FOR_EACH_REALPLAYER(tmp_entity)
                                if(tmp_entity.flagcarried)
 -                                      centerprint(tmp_entity, "Stalemate! Enemies can now see you on radar!");
 +                                      Send_Notification(tmp_entity, MSG_ONE, MSG_CENTER, CENTER_CTF_STALEMATE_CARRIER, NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
                                else
 -                                      centerprint(tmp_entity, "Stalemate! Flag carriers can now be seen by enemies on radar!");
 +                                      Send_Notification(tmp_entity, MSG_ONE, MSG_CENTER, CENTER_CTF_STALEMATE_OTHER, NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
                        
                        wpforenemy_announced = TRUE;
                }
@@@ -932,7 -931,7 +932,7 @@@ void ctf_DelayedFlagSetup(void) // call
        self.bot_basewaypoint = self.nearestwaypoint;
  
        // waypointsprites
 -      WaypointSprite_SpawnFixed(((self.team == COLOR_TEAM1) ? "redbase" : "bluebase"), self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG, colormapPaletteColor(self.team - 1, FALSE));
 +      WaypointSprite_SpawnFixed(((self.team == FL_TEAM_1) ? "redbase" : "bluebase"), self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG, colormapPaletteColor(self.team - 1, FALSE));
        WaypointSprite_UpdateTeamRadar(self.wps_flagbase, RADARICON_FLAG, colormapPaletteColor(self.team - 1, FALSE));
  
        // captureshield setup
@@@ -949,10 -948,10 +949,10 @@@ void ctf_FlagSetup(float teamnumber, en
        flag.ctf_worldflagnext = ctf_worldflaglist; // link flag into ctf_worldflaglist
        ctf_worldflaglist = flag;
  
 -      setattachment(flag, world, ""); 
 +      setattachment(flag, world, "");
  
 -      flag.netname = ((teamnumber) ? "^1RED^7 flag" : "^4BLUE^7 flag");
 -      flag.team = ((teamnumber) ? COLOR_TEAM1 : COLOR_TEAM2); // COLOR_TEAM1: color 4 team (red) - COLOR_TEAM2: color 13 team (blue)
 +      flag.netname = ((teamnumber) ? "^1REPLACETHIS^7" : "^4REPLACETHIS^7"); // ((teamnumber) ? "^1RED^7 flag" : "^4BLUE^7 flag");
 +      flag.team = ((teamnumber) ? FL_TEAM_1 : FL_TEAM_2); // FL_TEAM_1: color 4 team (red) - FL_TEAM_2: color 13 team (blue)
        flag.items = ((teamnumber) ? IT_KEY2 : IT_KEY1); // IT_KEY2: gold key (redish enough) - IT_KEY1: silver key (bluish enough)
        flag.classname = "item_flag_team";
        flag.target = "###item###"; // wut?
@@@ -1843,13 -1842,13 +1843,13 @@@ MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey
                                                { 
                                                        if(clienttype(head) == CLIENTTYPE_BOT)
                                                        {
 -                                                              centerprint(player, strcat("Requesting ", head.netname, " to pass you the ", head.flagcarried.netname)); 
 +                                                              Send_Notification(player, MSG_ONE, MSG_CENTER, CENTER_CTF_PASS_REQUESTING, head.netname, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
                                                                ctf_Handle_Throw(head, player, DROP_PASS);
                                                        }
                                                        else
                                                        {
 -                                                              centerprint(head, strcat(player.netname, " requests you to pass the ", head.flagcarried.netname)); 
 -                                                              centerprint(player, strcat("Requesting ", head.netname, " to pass you the ", head.flagcarried.netname)); 
 +                                                              Send_Notification(head, MSG_ONE, MSG_CENTER, CENTER_CTF_PASS_REQUESTED, player.netname, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
 +                                                              Send_Notification(player, MSG_ONE, MSG_CENTER, CENTER_CTF_PASS_REQUESTING, head.netname, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
                                                        }
                                                        player.throw_antispam = time + autocvar_g_ctf_pass_wait; 
                                                        return TRUE; 
                                }
                                else
                                {
 -                                      centerprint(player, strcat("Too many flag throws, throwing disabled for ", ftos(rint((player.throw_prevtime + autocvar_g_ctf_throw_punish_delay) - time)), " seconds."));
 +                                      Send_Notification(player, MSG_ONE, MSG_CENTER, CENTER_CTF_FLAG_THROW_PUNISH, NO_STR_ARG, NO_STR_ARG, rint((player.throw_prevtime + autocvar_g_ctf_throw_punish_delay) - time), NO_FL_ARG, NO_FL_ARG);
                                        return FALSE;
                                }
                        }
@@@ -1961,8 -1960,8 +1961,8 @@@ MUTATOR_HOOKFUNCTION(ctf_AbortSpeedrun
  {
        if(self.flagcarried)
        {
 -              bprint("The ", self.flagcarried.netname, " was returned to base by its carrier\n");
 -              ctf_RespawnFlag(self);
 +              Send_Notification(world, MSG_BROADCAST, MSG_INFO, APP_TEAM_ENT_2(self.flagcarried, INFO_CTF_FLAGRETURN_ABORTRUN_), NO_STR_ARG, NO_STR_ARG, NO_FL_ARG, NO_FL_ARG, NO_FL_ARG);
 +              ctf_RespawnFlag(self.flagcarried);
                return TRUE;
        }
        
@@@ -1986,7 -1985,7 +1986,7 @@@ MUTATOR_HOOKFUNCTION(ctf_MatchEnd
                                flag.solid = SOLID_NOT;
                                flag.nextthink = FALSE; // stop thinking
                                
-                               print("stopping the ", flag.netname, " from moving.\n");
+                               //dprint("stopping the ", flag.netname, " from moving.\n");
                                break;
                        }
                        
@@@ -2009,14 -2008,6 +2009,14 @@@ MUTATOR_HOOKFUNCTION(ctf_BotRoles
        return TRUE;
  }
  
 +MUTATOR_HOOKFUNCTION(ctf_GetCvars)
 +{
 +      GetCvars_handleFloat(get_cvars_s, get_cvars_f, CAPTURE_VERBOSE, "notification_ctf_capture_verbose");
 +      GetCvars_handleFloat(get_cvars_s, get_cvars_f, PICKUP_TEAM_VERBOSE, "notification_ctf_pickup_team_verbose");
 +      GetCvars_handleFloat(get_cvars_s, get_cvars_f, PICKUP_ENEMY_VERBOSE, "notification_ctf_pickup_enemy_verbose");
 +      return TRUE;
 +}
 +
  
  // ==========
  // Spawnfuncs
@@@ -2029,7 -2020,7 +2029,7 @@@ void spawnfunc_info_player_team1(
  {
        if(g_assault) { remove(self); return; }
        
 -      self.team = COLOR_TEAM1; // red
 +      self.team = FL_TEAM_1; // red
        spawnfunc_info_player_deathmatch();
  }
  
@@@ -2041,7 -2032,7 +2041,7 @@@ void spawnfunc_info_player_team2(
  {
        if(g_assault) { remove(self); return; }
        
 -      self.team = COLOR_TEAM2; // blue
 +      self.team = FL_TEAM_2; // blue
        spawnfunc_info_player_deathmatch();
  }
  
@@@ -2052,7 -2043,7 +2052,7 @@@ void spawnfunc_info_player_team3(
  {
        if(g_assault) { remove(self); return; }
        
 -      self.team = COLOR_TEAM3; // yellow
 +      self.team = FL_TEAM_3; // yellow
        spawnfunc_info_player_deathmatch();
  }
  
@@@ -2064,7 -2055,7 +2064,7 @@@ void spawnfunc_info_player_team4(
  {
        if(g_assault) { remove(self); return; }
        
 -      self.team = COLOR_TEAM4; // purple
 +      self.team = FL_TEAM_4; // purple
        spawnfunc_info_player_deathmatch();
  }
  
@@@ -2166,8 -2157,8 +2166,8 @@@ void ctf_DelayedInit() // Do this chec
        if(find(world, classname, "ctf_team") == world)
        {
                print("No ""ctf_team"" entities found on this map, creating them anyway.\n");
 -              ctf_SpawnTeam("Red", COLOR_TEAM1 - 1);
 -              ctf_SpawnTeam("Blue", COLOR_TEAM2 - 1);
 +              ctf_SpawnTeam("Red", FL_TEAM_1 - 1);
 +              ctf_SpawnTeam("Blue", FL_TEAM_2 - 1);
        }
        
        ctf_ScoreRules();
@@@ -2201,7 -2192,6 +2201,7 @@@ MUTATOR_DEFINITION(gamemode_ctf
        MUTATOR_HOOK(VehicleExit, ctf_VehicleExit, CBC_ORDER_ANY);
        MUTATOR_HOOK(AbortSpeedrun, ctf_AbortSpeedrun, CBC_ORDER_ANY);
        MUTATOR_HOOK(HavocBot_ChooseRule, ctf_BotRoles, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(GetCvars, ctf_GetCvars, CBC_ORDER_ANY);
        
        MUTATOR_ONADD
        {
index c115dca36c07474e75e439178c2118c16864d080,5f27b60a55f882e851cc99fe5bc876fec16e5601..6fcb8647bbe97114d2fa6cc46f303095193f2c4f
@@@ -49,7 -49,7 +49,7 @@@ void nexball_setstatus(void
        {
                if(self.ballcarried.teamtime && (self.ballcarried.teamtime < time))
                {
 -                      bprint("The ", ColoredTeamName(self.team), " held the ball for too long.\n");
 +                      bprint("The ", Team_ColoredFullName(self.team), " held the ball for too long.\n");
                        oldself = self;
                        self = self.ballcarried;
                        DropBall(self, self.owner.origin, '0 0 0');
@@@ -204,8 -204,7 +204,8 @@@ void ResetBall(void
        if(self.cnt < 2)        // step 1
        {
                if(time == self.teamtime)
 -                      bprint("The ", ColoredTeamName(self.team), " held the ball for too long.\n");
 +                      bprint("The ", Team_ColoredFullName(self.team), " held the ball for too long.\n");
 +
                self.touch = func_null;
                self.movetype = MOVETYPE_NOCLIP;
                self.velocity = '0 0 0'; // just in case?
@@@ -342,9 -341,9 +342,9 @@@ void GoalTouch(void
        {
                LogNB("fault", ball.pusher);
                if(nb_teams == 2)
 -                      bprint(ColoredTeamName(otherteam), " gets a point due to ", pname, "^7's silliness.\n");
 +                      bprint(Team_ColoredFullName(otherteam), " gets a point due to ", pname, "^7's silliness.\n");
                else
 -                      bprint(ColoredTeamName(ball.team), " loses a point due to ", pname, "^7's silliness.\n");
 +                      bprint(Team_ColoredFullName(ball.team), " loses a point due to ", pname, "^7's silliness.\n");
                pscore = -1;
        }
        else if(self.team == GOAL_OUT)
        else                                                       //score
        {
                LogNB(strcat("goal:", ftos(self.team)), ball.pusher);
 -              bprint("Goaaaaal! ", pname, "^7 scored a point for the ", ColoredTeamName(ball.team), ".\n");
 +              bprint("Goaaaaal! ", pname, "^7 scored a point for the ", Team_ColoredFullName(ball.team), ".\n");
                pscore = 1;
        }
  
@@@ -425,28 -424,28 +425,28 @@@ void nb_spawnteams(void
        {
                switch(e.team)
                {
 -              case COLOR_TEAM1:
 +              case FL_TEAM_1:
                        if(!t_r)
                        {
                                nb_spawnteam("Red", e.team-1)   ;
                                t_r = 1;
                        }
                        break;
 -              case COLOR_TEAM2:
 +              case FL_TEAM_2:
                        if(!t_b)
                        {
                                nb_spawnteam("Blue", e.team-1)  ;
                                t_b = 1;
                        }
                        break;
 -              case COLOR_TEAM3:
 +              case FL_TEAM_3:
                        if(!t_y)
                        {
                                nb_spawnteam("Yellow", e.team-1);
                                t_y = 1;
                        }
                        break;
 -              case COLOR_TEAM4:
 +              case FL_TEAM_4:
                        if(!t_p)
                        {
                                nb_spawnteam("Pink", e.team-1)  ;
@@@ -576,22 -575,22 +576,22 @@@ void SpawnGoal(void
  
  void spawnfunc_nexball_redgoal(void)
  {
 -      self.team = COLOR_TEAM1;
 +      self.team = FL_TEAM_1;
        SpawnGoal();
  }
  void spawnfunc_nexball_bluegoal(void)
  {
 -      self.team = COLOR_TEAM2;
 +      self.team = FL_TEAM_2;
        SpawnGoal();
  }
  void spawnfunc_nexball_yellowgoal(void)
  {
 -      self.team = COLOR_TEAM3;
 +      self.team = FL_TEAM_3;
        SpawnGoal();
  }
  void spawnfunc_nexball_pinkgoal(void)
  {
 -      self.team = COLOR_TEAM4;
 +      self.team = FL_TEAM_4;
        SpawnGoal();
  }
  
@@@ -774,14 -773,13 +774,13 @@@ void W_Nexball_Attack2(void
        missile.flags = FL_PROJECTILE;
  }
  
- var const float() nullfunc;
  float ball_customize()
  {
        if(!self.owner)
        {
                self.effects &~= EF_FLAME;
                self.scale = 1;
-               self.customizeentityforclient = nullfunc;
+               self.customizeentityforclient = func_null;
                return TRUE;
        }               
        
diff --combined qcsrc/server/w_hagar.qc
index 34788cdcecb183de1b6ac46ded93a0bdc405eebd,55e361ebbcdb9ca395f145407edc9b0d957f07ef..b4b79abb832363bfea7fcd11d775bb0c8eb84554
@@@ -351,7 -351,7 +351,7 @@@ float w_hagar(float req
        else if (req == WR_THINK)
        {
                float loadable_secondary;
-               loadable_secondary = autocvar_g_balance_hagar_secondary_load && autocvar_g_balance_hagar_secondary;
+               loadable_secondary = (autocvar_g_balance_hagar_secondary_load && autocvar_g_balance_hagar_secondary);
  
                if (loadable_secondary)
                        W_Hagar_Attack2_Load(); // must always run each frame
                if not(self.hagar_load) // require releasing loaded rockets first
                        W_Reload(min(autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_secondary_ammo), autocvar_g_balance_hagar_reload_ammo, autocvar_g_balance_hagar_reload_time, "weapons/reload.wav");
        }
 +      else if (req == WR_SUICIDEMESSAGE)
 +      {
 +              return WEAPON_HAGAR_SUICIDE;
 +      }
 +      else if (req == WR_KILLMESSAGE)
 +      {
 +              if(w_deathtype & HITTYPE_SECONDARY)
 +                      return WEAPON_HAGAR_MURDER_BURST;
 +              else
 +                      return WEAPON_HAGAR_MURDER_SPRAY;
 +      }
        return TRUE;
  }
  #endif
@@@ -470,6 -459,15 +470,6 @@@ float w_hagar(float req
                precache_sound("weapons/hagexp2.wav");
                precache_sound("weapons/hagexp3.wav");
        }
 -      else if (req == WR_SUICIDEMESSAGE)
 -              w_deathtypestring = _("%s played with tiny hagar rockets");
 -      else if (req == WR_KILLMESSAGE)
 -      {
 -              if(w_deathtype & HITTYPE_BOUNCE) // must be secondary; unchecked: SPLASH
 -                      w_deathtypestring = _("%s was pummeled with a burst of hagar rockets by %s");
 -              else // unchecked: SPLASH, SECONDARY
 -                      w_deathtypestring = _("%s was pummeled with hagar rockets by %s");
 -      }
        return TRUE;
  }
  #endif
diff --combined qcsrc/server/w_seeker.qc
index e261b97fc6d66c9321ff4002624c193385ffa9ef,975449f5d10c723c5fb765204c66641ae277e0c8..13c010f2a13010937f6d7a2a37fa8e2f426ba107
@@@ -495,8 -495,8 +495,8 @@@ void Seeker_Fire_Tag(
        missile.solid           = SOLID_BBOX;
  
        missile.takedamage       = DAMAGE_YES;
-       missile.event_damage    = Seeker_Tag_Explode;
-       missile.health          = autocvar_g_balance_seeker_tag_health;
+       missile.event_damage     = Seeker_Tag_Damage;
+       missile.health           = autocvar_g_balance_seeker_tag_health;
        missile.damageforcescale = autocvar_g_balance_seeker_tag_damageforcescale;
  
        setorigin (missile, w_shotorg);
@@@ -612,17 -612,6 +612,17 @@@ float w_seeker(float req
        {
                W_Reload(min(autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_tag_ammo), autocvar_g_balance_seeker_reload_ammo, autocvar_g_balance_seeker_reload_time, "weapons/reload.wav");
        }
 +      else if (req == WR_SUICIDEMESSAGE)
 +      {
 +              return WEAPON_SEEKER_SUICIDE;
 +      }
 +      else if (req == WR_KILLMESSAGE)
 +      {
 +              if(w_deathtype & HITTYPE_SECONDARY)
 +                      return WEAPON_SEEKER_MURDER_TAG;
 +              else
 +                      return WEAPON_SEEKER_MURDER_SPRAY;
 +      }
        return TRUE;
  }
  #endif
@@@ -675,6 -664,15 +675,6 @@@ float w_seeker(float req
                precache_sound("weapons/tagexp3.wav");
                precache_sound("weapons/tag_impact.wav");
        }
 -      else if (req == WR_SUICIDEMESSAGE)
 -              w_deathtypestring = _("%s played with tiny seeker rockets");
 -      else if (req == WR_KILLMESSAGE)
 -      {
 -              if(w_deathtype & HITTYPE_SECONDARY)
 -                      w_deathtypestring = _("%s was tagged with a seeker by %s");
 -              else
 -                      w_deathtypestring = _("%s was pummeled with seeker rockets by %s");
 -      }
        return TRUE;
  }
  #endif