Merge branch 'master' into terencehill/centerprint_stuff
authorterencehill <piuntn@gmail.com>
Tue, 24 May 2011 14:12:36 +0000 (16:12 +0200)
committerterencehill <piuntn@gmail.com>
Tue, 24 May 2011 14:12:36 +0000 (16:12 +0200)
1  2 
qcsrc/client/View.qc
qcsrc/client/hud.qc
qcsrc/server/cl_client.qc

diff --combined qcsrc/client/View.qc
@@@ -137,7 -137,7 +137,7 @@@ vector GetCurrentFov(float fov
                        zoomspeed = 3.5;
  
        zoomdir = button_zoom;
-       if((getstati(STAT_ACTIVEWEAPON) == WEP_NEX && nex_scope) || (getstati(STAT_ACTIVEWEAPON) == WEP_SNIPERRIFLE && sniperrifle_scope)) // do NOT use switchweapon here
+       if((getstati(STAT_ACTIVEWEAPON) == WEP_NEX && nex_scope) || (getstati(STAT_ACTIVEWEAPON) == WEP_RIFLE && rifle_scope)) // do NOT use switchweapon here
                zoomdir += button_attack2;
        if(spectatee_status > 0 || isdemo())
        {
@@@ -274,7 -274,7 +274,7 @@@ float TrueAimCheck(
                case WEP_MINSTANEX:
                        mv = MOVE_NORMAL;
                        break;
-               case WEP_SNIPERRIFLE:
+               case WEP_RIFLE:
                        ta = trueaim_rifle;
                        mv = MOVE_NORMAL;
                        if(zoomscript_caught)
@@@ -683,11 -683,11 +683,11 @@@ void CSQC_UpdateView(float w, float h
        // the view to go back to normal, so reticle_type would become 0 as we fade out)
        if(spectatee_status || getstati(STAT_HEALTH) <= 0)
                reticle_type = 0; // prevent reticle from showing during the respawn zoom effect or for spectators
-       else if(activeweapon == WEP_NEX && (button_zoom || zoomscript_caught) || activeweapon == WEP_SNIPERRIFLE && (button_zoom || zoomscript_caught) || activeweapon == WEP_MINSTANEX && (button_zoom || zoomscript_caught))
+       else if(activeweapon == WEP_NEX && (button_zoom || zoomscript_caught) || activeweapon == WEP_RIFLE && (button_zoom || zoomscript_caught) || activeweapon == WEP_MINSTANEX && (button_zoom || zoomscript_caught))
                reticle_type = 2; // nex zoom
        else if(button_zoom || zoomscript_caught)
                reticle_type = 1; // normal zoom
-       else if(activeweapon == WEP_NEX && button_attack2 || activeweapon == WEP_SNIPERRIFLE && button_attack2)
+       else if(activeweapon == WEP_NEX && button_attack2 || activeweapon == WEP_RIFLE && button_attack2)
                reticle_type = 2; // nex zoom
  
        if (reticle_type)
                                        
                                        // Note: This is to stop Taoki from complaining that the image doesn't match all potential balances.
                                        // if a new image for another weapon is added, add the code (and its respective file/value) here
-                                       if ((activeweapon == WEP_SNIPERRIFLE) && (weapon_clipsize == 80))
-                                               ring_image = "gfx/crosshair_ring_sniperrifle.tga";
+                                       if ((activeweapon == WEP_RIFLE) && (weapon_clipsize == 80))
+                                               ring_image = "gfx/crosshair_ring_rifle.tga";
                                        else
                                                ring_image = "gfx/crosshair_ring.tga";
                                }
@@@ -1421,6 -1421,7 +1421,6 @@@ void CSQC_SPIDER_HUD(
        if (scoreboard_showscores)
        {
                HUD_DrawScoreboard();
 -              HUD_DrawCenterPrint();
        }
  
  }
@@@ -1487,6 -1488,7 +1487,6 @@@ void CSQC_RAPTOR_HUD(
        if (scoreboard_showscores)
        {
                HUD_DrawScoreboard();
 -              HUD_DrawCenterPrint();
        }
  
  }
@@@ -1596,6 -1598,7 +1596,6 @@@ const float STAT_VEHICLESTAT_RELOAD2 = 
        if (scoreboard_showscores)
        {
                HUD_DrawScoreboard();
 -              HUD_DrawCenterPrint();
        }
  
  }
@@@ -1634,12 -1637,25 +1634,12 @@@ void CSQC_common_hud(void
                        HUD_DrawScoreboard();
  
                        if (scoreboard_active) // scoreboard/accuracy
 -                      {       
                                HUD_Reset();
 -                              // HUD_DrawScoreboard takes care of centerprint_start
 -                      }
                        else if (intermission == 2) // map voting screen
                        {
                                HUD_FinaleOverlay();
                                HUD_Reset();
 -
 -                              centerprint_start_x = 0;
 -                              centerprint_start_y = autocvar_scr_centerpos * vid_conheight;
                        }
 -                      else // hud
 -                      {
 -                              centerprint_start_x = 0;
 -                              centerprint_start_y = autocvar_scr_centerpos * vid_conheight;
 -                      }
 -
 -                      HUD_DrawCenterPrint();
                        break;
  
                case HUD_SPIDERBOT:
diff --combined qcsrc/client/hud.qc
@@@ -142,6 -142,183 +142,6 @@@ float stringwidth_nocolors(string s, ve
        return stringwidth(s, FALSE, theSize);
  }
  
 -#define CENTERPRINT_MAX_LINES 30
 -string centerprint_messages[CENTERPRINT_MAX_LINES];
 -float centerprint_width[CENTERPRINT_MAX_LINES];
 -float centerprint_time;
 -float centerprint_expire;
 -float centerprint_num;
 -float centerprint_offset_hint;
 -vector centerprint_fontsize;
 -
 -void centerprint(string strMessage)
 -{
 -      float i, j, n, hcount;
 -      string s;
 -
 -      centerprint_fontsize = HUD_GetFontsize("scr_centersize");
 -
 -      centerprint_expire = min(centerprint_expire, time); // if any of the returns happens, this message will fade out
 -
 -      if(autocvar_scr_centertime <= 0)
 -              return;
 -
 -      if(strMessage == "")
 -              return;
 -
 -      // strip trailing newlines
 -      j = strlen(strMessage) - 1;
 -      while(substring(strMessage, j, 1) == "\n" && j >= 0)
 -              j = j - 1;
 -      strMessage = substring(strMessage, 0, j + 1);
 -
 -      if(strMessage == "")
 -              return;
 -
 -      // strip leading newlines and remember them, they are a hint that the message should be lower on the screen
 -      j = 0;
 -      while(substring(strMessage, j, 1) == "\n" && j < strlen(strMessage))
 -              j = j + 1;
 -      strMessage = substring(strMessage, j, strlen(strMessage) - j);
 -      centerprint_offset_hint = j;
 -
 -      if(strMessage == "")
 -              return;
 -
 -      // if we get here, we have a message. Initialize its height.
 -      centerprint_num = 0;
 -
 -      n = tokenizebyseparator(strMessage, "\n");
 -      i = hcount = 0;
 -      for(j = 0; j < n; ++j)
 -      {
 -              getWrappedLine_remaining = argv(j);
 -              while(getWrappedLine_remaining)
 -              {
 -                      s = getWrappedLine(vid_conwidth * 0.75, centerprint_fontsize, stringwidth_colors);
 -                      if(centerprint_messages[i] != s) // don't fade the same message in, looks stupid
 -                              centerprint_time = time;
 -                      if(centerprint_messages[i])
 -                              strunzone(centerprint_messages[i]);
 -                      centerprint_messages[i] = strzone(s);
 -                      centerprint_width[i] = stringwidth(s, TRUE, centerprint_fontsize);
 -                      ++i;
 -
 -                      // half height for empty lines looks better
 -                      if(s == "")
 -                              hcount += 0.5;
 -                      else
 -                              hcount += 1;
 -
 -                      if(i >= CENTERPRINT_MAX_LINES)
 -                              break;
 -              }
 -      }
 -
 -      float h, havail;
 -      h = centerprint_fontsize_y*hcount;
 -
 -      havail = vid_conheight;
 -      if(autocvar_con_chatpos < 0)
 -              havail -= (-autocvar_con_chatpos + autocvar_con_chat) * autocvar_con_chatsize; // avoid overlapping chat
 -      if(havail > vid_conheight - 70)
 -              havail = vid_conheight - 70; // avoid overlapping HUD
 -
 -#if 0
 -      float forbiddenmin, forbiddenmax, allowedmin, allowedmax, preferred;
 -
 -      // here, the centerprint would cover the crosshair. REALLY BAD.
 -      forbiddenmin = vid_conheight * 0.5 - h - 16;
 -      forbiddenmax = vid_conheight * 0.5 + 16;
 -
 -      allowedmin = scoreboard_bottom;
 -      allowedmax = havail - h;
 -      preferred = (havail - h)/2;
 -
 -
 -      // possible orderings (total: 4! / 4 = 6)
 -      //  allowedmin allowedmax forbiddenmin forbiddenmax
 -      //  forbiddenmin forbiddenmax allowedmin allowedmax
 -      if(allowedmax < forbiddenmin || allowedmin > forbiddenmax)
 -      {
 -              // forbidden doesn't matter in this case
 -              centerprint_start_y = bound(allowedmin, preferred, allowedmax);
 -      }
 -      //  allowedmin forbiddenmin allowedmax forbiddenmax
 -      else if(allowedmin < forbiddenmin && allowedmax < forbiddenmax)
 -      {
 -              centerprint_start_y = bound(allowedmin, preferred, forbiddenmin);
 -      }
 -      //  allowedmin forbiddenmin forbiddenmax allowedmax
 -      else if(allowedmin < forbiddenmin)
 -      {
 -              // make sure the forbidden zone is not covered
 -              if(preferred > (forbiddenmin + forbiddenmax) * 0.5)
 -                      centerprint_start_y = bound(allowedmin, preferred, forbiddenmin);
 -              else
 -                      centerprint_start_y = bound(forbiddenmax, preferred, allowedmin);
 -      }
 -      //  forbiddenmin allowedmin allowedmax forbiddenmax
 -      else if(allowedmax < forbiddenmax)
 -      {
 -              // it's better to leave the allowed zone (overlap with scoreboard) than
 -              // to cover the forbidden zone (crosshair)
 -              if(preferred > (forbiddenmin + forbiddenmax) * 0.5)
 -                      centerprint_start_y = forbiddenmax;
 -              else
 -                      centerprint_start_y = forbiddenmin;
 -      }
 -      //  forbiddenmin allowedmin forbiddenmax allowedmax
 -      else
 -      {
 -              centerprint_start_y = bound(forbiddenmax, preferred, allowedmax);
 -      }
 -#else
 -#endif
 -
 -      centerprint_num = i;
 -
 -      centerprint_expire = time + autocvar_scr_centertime;
 -}
 -
 -void HUD_DrawCenterPrint (void)
 -{
 -      float i;
 -      vector pos;
 -      string ts;
 -      float a, sz;
 -
 -      if(time - centerprint_time < 0.25)
 -              a = (time - centerprint_time) / 0.25;
 -      else
 -              a = bound(0, 1 - 4 * (time - centerprint_expire), 1);
 -
 -      if(a <= 0)
 -              return;
 -
 -      sz = 0.8 + (a / 5);
 -
 -      if(centerprint_num * autocvar_scr_centersize > 24 && scoreboard_active) // 24 = height of Scoreboard text
 -              centerprint_start_y = scoreboard_bottom + centerprint_fontsize_y;
 -
 -      pos = centerprint_start;
 -      for (i=0; i<centerprint_num; i = i + 1)
 -      {
 -              ts = centerprint_messages[i];
 -              drawfontscale = sz * '1 1 0';
 -              pos_x = (vid_conwidth - stringwidth(ts, TRUE, centerprint_fontsize)) * 0.5;
 -              if (ts != "")
 -              {
 -                      drawcolorcodedstring(pos + '0 1 0' * (1 - sz) * 0.5 *centerprint_fontsize_y, ts, centerprint_fontsize, a, DRAWFLAG_NORMAL);
 -                      pos_y = pos_y + centerprint_fontsize_y;
 -              }
 -              else
 -                      // half height for empty lines looks better
 -                      pos_y = pos_y + sz * centerprint_fontsize_y * 0.5;
 -              drawfontscale = '1 1 0';
 -      }
 -}
 -
  void drawstringright(vector position, string text, vector scale, vector rgb, float alpha, float flag)
  {
        position_x -= 2 / 3 * strlen(text) * scale_x;
@@@ -423,7 -600,7 +423,7 @@@ float GetAmmoTypeForWep(float i
                case WEP_HLAC: return 3;
                case WEP_MINSTANEX: return 3;
                case WEP_NEX: return 3;
-               case WEP_SNIPERRIFLE: return 1;
+               case WEP_RIFLE: return 1;
                case WEP_HAGAR: return 2;
                case WEP_ROCKET_LAUNCHER: return 2;
                case WEP_SEEKER: return 2;
@@@ -1503,7 -1680,7 +1503,7 @@@ void HUD_KillNotify(string s1, string s
        } else if(msg == MSG_KILL) {
                w = DEATH_WEAPONOF(type);
                if(WEP_VALID(w)) {
-                       if((w == WEP_SNIPERRIFLE || w == WEP_MINSTANEX) && type & HITTYPE_HEADSHOT) // all headshot weapons go here
+                       if((w == WEP_RIFLE || w == WEP_MINSTANEX) && type & HITTYPE_HEADSHOT) // all headshot weapons go here
                                HUD_KillNotify_Push(s1, s2, 1, DEATH_HEADSHOT);
                        else
                                HUD_KillNotify_Push(s1, s2, 1, type);
        }
  }
  
 -#define DAMAGE_CENTERPRINT_SPACER NEWLINES
 -
  void HUD_Centerprint(string s1, string s2, float type, float msg)
  {
        float gentle;
        gentle = (autocvar_cl_gentle || autocvar_cl_gentle_messages);
        if(msg == MSG_SUICIDE) {
                if (type == DEATH_TEAMCHANGE) {
 -                      centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("You are now on: %s"), s1)));
 +                      centerprint(strcat(sprintf(_("You are now on: %s"), s1)));
                } else if (type == DEATH_AUTOTEAMCHANGE) {
 -                      centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("You have been moved into a different team to improve team balance\nYou are now on: %s"), s1)));
 +                      centerprint(strcat(sprintf(_("You have been moved into a different team to improve team balance\nYou are now on: %s"), s1)));
                } else if (type == DEATH_CAMP) {
                        if(gentle)
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1Reconsider your tactics, camper!")));
 +                              centerprint(strcat(_("^1Reconsider your tactics, camper!")));
                        else
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1Die camper!")));
 +                              centerprint(strcat(_("^1Die camper!")));
                } else if (type == DEATH_NOAMMO) {
                        if(gentle)
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You are reinserted into the game for running out of ammo...")));
 +                              centerprint(strcat(_("^1You are reinserted into the game for running out of ammo...")));
                        else
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You were killed for running out of ammo...")));
 +                              centerprint(strcat(_("^1You were killed for running out of ammo...")));
                } else if (type == DEATH_ROT) {
                        if(gentle)
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You need to preserve your health")));
 +                              centerprint(strcat(_("^1You need to preserve your health")));
                        else
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You grew too old without taking your medicine")));
 +                              centerprint(strcat(_("^1You grew too old without taking your medicine")));
                } else if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) {
                        if(gentle)
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1Don't go against team mates!")));
 +                              centerprint(strcat(_("^1Don't go against team mates!")));
                        else
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1Don't shoot your team mates!")));
 +                              centerprint(strcat(_("^1Don't shoot your team mates!")));
                } else if (type == DEATH_QUIET) {
                        // do nothing
                } else { // generic message
                        if(gentle)
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You need to be more careful!")));
 +                              centerprint(strcat(_("^1You need to be more careful!")));
                        else
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You killed your own dumb self!")));
 +                              centerprint(strcat(_("^1You killed your own dumb self!")));
                }
        } else if(msg == MSG_KILL) {
                if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) {
                        if(gentle) {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1Moron! You went against %s, a team mate!"), s1)));
 +                              centerprint(strcat(sprintf(_("^1Moron! You went against %s, a team mate!"), s1)));
                        } else {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1Moron! You fragged %s, a team mate!"), s1)));
 +                              centerprint(strcat(sprintf(_("^1Moron! You fragged %s, a team mate!"), s1)));
                        }
                } else if (type == KILL_FIRST_BLOOD) {
                        if(gentle) {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1First score")));
 +                              centerprint(strcat(_("^1First score")));
                        } else {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1First blood")));
 +                              centerprint(strcat(_("^1First blood")));
                        }
                } else if (type == KILL_FIRST_VICTIM) {
                        if(gentle) {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1First casualty")));
 +                              centerprint(strcat(_("^1First casualty")));
                        } else {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1First victim")));
 +                              centerprint(strcat(_("^1First victim")));
                        }
                } else if (type == KILL_TYPEFRAG) { // s2 contains "advanced kill messages" such as ping, handicap...
                        if(gentle) {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You scored against ^7%s^1 who was typing!"), s1), s2));
 +                              centerprint(strcat(sprintf(_("^1You scored against ^7%s^1 who was typing!"), s1), s2));
                        } else {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You typefragged ^7%s"), s1), s2));
 +                              centerprint(strcat(sprintf(_("^1You typefragged ^7%s"), s1), s2));
                        }
                } else if (type == KILL_TYPEFRAGGED) {
                        if(gentle) {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You were scored against by ^7%s^1 while you were typing!"), s1), s2));
 +                              centerprint(strcat(sprintf(_("^1You were scored against by ^7%s^1 while you were typing!"), s1), s2));
                        } else {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You were typefragged by ^7%s"), s1), s2));
 +                              centerprint(strcat(sprintf(_("^1You were typefragged by ^7%s"), s1), s2));
                        }
                } else if (type == KILL_FRAG) {
                        if(gentle) {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^4You scored against ^7%s"), s1), s2));
 +                              centerprint(strcat(sprintf(_("^4You scored against ^7%s"), s1), s2));
                        } else {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^4You fragged ^7%s"), s1), s2));
 +                              centerprint(strcat(sprintf(_("^4You fragged ^7%s"), s1), s2));
                        }
                } else { // generic message
                        if(gentle) {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You were scored against by ^7%s"), s1), s2));
 +                              centerprint(strcat(sprintf(_("^1You were scored against by ^7%s"), s1), s2));
                        } else {
 -                              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You were fragged by ^7%s"), s1), s2));
 +                              centerprint(strcat(sprintf(_("^1You were fragged by ^7%s"), s1), s2));
                        }
                }
        } else if(msg == MSG_KILL_ACTION) {
                // TODO: invent more centerprints here?
 -              centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1Watch your step!")));
 +              centerprint(strcat(_("^1Watch your step!")));
        }
  }
  
@@@ -4317,152 -4496,6 +4317,152 @@@ void HUD_Physics(void
                drawstring_aspect(panel_pos + acceleration_offset, strcat(ftos_decimals(acceleration, 2), "g"), panel_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
  }
  
 +#define CENTERPRINT_MAX_MSGS 10
 +#define CENTERPRINT_MAX_ENTRIES 50
 +float cpm_index;
 +string centerprint_messages[CENTERPRINT_MAX_MSGS];
 +float centerprint_msgID[CENTERPRINT_MAX_MSGS];
 +float centerprint_time[CENTERPRINT_MAX_MSGS];
 +
 +string msg_without_CPID(string s)
 +{
 +      return substring(s, strstrofs(s, " ", 0) + 1, strlen(s));
 +}
 +float get_CPID(string s)
 +{
 +      if(substring(s, 0, 1) != "\r")
 +              return 0;
 +      return stof(substring(s, 1, strstrofs(s, " ", 0)));
 +}
 +void centerprint(string strMessage)
 +{
 +      float i, j;
 +
 +      if(autocvar_hud_panel_centerprint_time <= 0)
 +              return;
 +
 +      if(strMessage == "")
 +              return;
 +
 +      float new_id = get_CPID(strMessage);
 +
 +      for (i=0, j=cpm_index; i<CENTERPRINT_MAX_MSGS; ++i, ++j)
 +      {
 +              if (j == CENTERPRINT_MAX_MSGS)
 +                      j = 0;
 +              if (new_id && new_id == centerprint_msgID[j] && centerprint_time[j] + autocvar_hud_panel_centerprint_time >= time)
 +              {
 +                      if(centerprint_messages[j])
 +                              strunzone(centerprint_messages[j]);
 +                      centerprint_messages[j] == strzone(msg_without_CPID(strMessage));
 +                      centerprint_time[j] = time;
 +                      return;
 +              }
 +              if(centerprint_messages[j] == strMessage)
 +              {
 +                      centerprint_time[j] = time;
 +                      centerprint_msgID[j] = new_id;
 +                      return;
 +              }
 +      }
 +
 +      --cpm_index;
 +      if (cpm_index == -1)
 +              cpm_index = CENTERPRINT_MAX_MSGS - 1;
 +      if(centerprint_messages[cpm_index])
 +              strunzone(centerprint_messages[cpm_index]);
 +      if (new_id)
 +              centerprint_messages[cpm_index] = strzone(msg_without_CPID(strMessage));
 +      else
 +              centerprint_messages[cpm_index] = strzone(strMessage);
 +      centerprint_msgID[cpm_index] = new_id;
 +      centerprint_time[cpm_index] = time;
 +}
 +
 +// CenterPrint (#16)
 +//
 +void HUD_CenterPrint (void)
 +{
 +      if(!autocvar__hud_configure)
 +      {
 +              if(!autocvar_hud_panel_centerprint) return;
 +      }
 +      else
 +              hud_configure_active_panel = HUD_PANEL_CENTERPRINT;
 +
 +      HUD_Panel_UpdateCvars(centerprint);
 +
 +      HUD_Panel_DrawBg(1);
 +      if(panel_bg_padding)
 +      {
 +              panel_pos += '1 1 0' * panel_bg_padding;
 +              panel_size -= '2 2 0' * panel_bg_padding;
 +      }
 +
 +      float entries, height;
 +      vector fontsize;
 +      // entries = bound(1, floor(CENTERPRINT_MAX_ENTRIES * 4 * panel_size_y/panel_size_x), CENTERPRINT_MAX_ENTRIES);
 +      // height = panel_size_y/entries;
 +      // fontsize = '1 1 0' * height;
 +      height = vid_conheight/40 * autocvar_hud_panel_centerprint_fontscale;
 +      fontsize = '1 1 0' * height;
 +      entries = bound(1, floor(panel_size_y/height), CENTERPRINT_MAX_ENTRIES);
 +
 +      float i, j, k, n;
 +      float a, sz, fade, align;
 +      vector pos;
 +      string ts;
 +
 +      pos = panel_pos;
 +      fade = min(autocvar_hud_panel_centerprint_time/8, 0.25);
 +      align = bound(0, autocvar_hud_panel_centerprint_align, 1);
 +      for (i=0, j=cpm_index; i<CENTERPRINT_MAX_MSGS; ++i, ++j)
 +      {
 +              if (j == CENTERPRINT_MAX_MSGS)
 +                      j = 0;
 +              if (centerprint_time[j] + autocvar_hud_panel_centerprint_time < time)
 +                      continue;
 +              else if (centerprint_time[j] + autocvar_hud_panel_centerprint_time - fade > time)
 +              {
 +                      a = 1;
 +                      sz = 1;
 +              }
 +              else if (centerprint_time[j] + autocvar_hud_panel_centerprint_time > time)
 +              {
 +                      a = (centerprint_time[j] + autocvar_hud_panel_centerprint_time - time) / fade;
 +                      sz = 0.8 + a * (1 - 0.8);
 +              }
 +
 +              drawfontscale = sz * '1 1 0';
 +              n = tokenizebyseparator(centerprint_messages[j], "\n");
 +              for(k = 0; k < n; ++k)
 +              {
 +                      getWrappedLine_remaining = argv(k);
 +                      while(getWrappedLine_remaining)
 +                      {
 +                              ts = getWrappedLine(panel_size_x, fontsize, stringwidth_colors);
 +                              if (ts != "")
 +                              {
 +                                      if (align)
 +                                              pos_x = panel_pos_x + (panel_size_x - stringwidth(ts, TRUE, fontsize)) * align;
 +                                      drawcolorcodedstring(pos + '0 1 0' * 1.5 * (1 - sz) * fontsize_y, ts, fontsize, a, DRAWFLAG_NORMAL);
 +                                      pos_y += fontsize_y * 1.5;
 +                              }
 +                              else
 +                                      pos_y += fontsize_y;
 +                              if (pos_y > panel_pos_y + panel_size_y - fontsize_y)
 +                              {
 +                                      drawfontscale = '1 1 0';
 +                                      return;
 +                              }
 +                      }
 +              }
 +              if (a < 1)
 +                      pos_y -= 1.5 * fontsize_y * (1 - a*a);
 +              drawfontscale = '1 1 0';
 +      }
 +}
 +
  /*
  ==================
  Main HUD system
@@@ -4512,8 -4545,6 +4512,8 @@@ switch (id) {
                 HUD_InfoMessages(); break;\
        case (HUD_PANEL_PHYSICS):\
                 HUD_Physics(); break;\
 +      case (HUD_PANEL_CENTERPRINT):\
 +               HUD_CenterPrint(); break;\
  } ENDS_WITH_CURLY_BRACE
  
  void HUD_Main (void)
@@@ -1134,7 -1134,7 +1134,7 @@@ float ClientInit_SendEntity(entity to, 
        WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_grenadelauncher_bouncefactor
        WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_grenadelauncher_bouncestop
        WriteByte(MSG_ENTITY, autocvar_g_balance_nex_secondary); // client has to know if it should zoom or not
-       WriteByte(MSG_ENTITY, autocvar_g_balance_sniperrifle_secondary); // client has to know if it should zoom or not
+       WriteByte(MSG_ENTITY, autocvar_g_balance_rifle_secondary); // client has to know if it should zoom or not
        WriteByte(MSG_ENTITY, serverflags); // client has to know if it should zoom or not
        WriteByte(MSG_ENTITY, autocvar_g_balance_minelayer_limit); // minelayer max mines
        WriteByte(MSG_ENTITY, autocvar_g_balance_hagar_secondary_load_max); // hagar max loadable rockets
@@@ -1302,14 -1302,14 +1302,14 @@@ void KillIndicator_Think(
                        if(self.owner.killindicator_teamchange)
                        {
                                if(self.owner.killindicator_teamchange == -1)
 -                                      centerprint(self.owner, strcat("Changing team in ", ftos(self.cnt), " seconds"));
 +                                      centerprint(self.owner, strcat(CPID_TEAMCHANGE, "Changing team in ", ftos(self.cnt), " seconds"));
                                else if(self.owner.killindicator_teamchange == -2)
 -                                      centerprint(self.owner, strcat("Spectating in ", ftos(self.cnt), " seconds"));
 +                                      centerprint(self.owner, strcat(CPID_TEAMCHANGE, "Spectating in ", ftos(self.cnt), " seconds"));
                                else
 -                                      centerprint(self.owner, strcat("Changing to ", ColoredTeamName(self.owner.killindicator_teamchange), " in ", ftos(self.cnt), " seconds"));
 +                                      centerprint(self.owner, strcat(CPID_TEAMCHANGE, "Changing to ", ColoredTeamName(self.owner.killindicator_teamchange), " in ", ftos(self.cnt), " seconds"));
                        }
                        else
 -                              centerprint(self.owner, strcat("^1Suicide in ", ftos(self.cnt), " seconds"));
 +                              centerprint(self.owner, strcat(CPID_KILL, "^1Suicide in ", ftos(self.cnt), " seconds"));
                }
                self.nextthink = time + 1;
                self.cnt -= 1;
@@@ -1639,6 -1639,9 +1639,9 @@@ void ClientConnect (void
  
        self.playerid = (playerid_last = playerid_last + 1);
  
+     if(clienttype(self) == CLIENTTYPE_BOT)
+         PlayerStats_AddPlayer(self);
        if(autocvar_sv_eventlog)
                GameLogEcho(strcat(":join:", ftos(self.playerid), ":", ftos(num_for_edict(self)), ":", ((clienttype(self) == CLIENTTYPE_REAL) ? self.netaddress : "bot"), ":", self.netname));
  
@@@ -1983,24 -1986,24 +1986,24 @@@ string getTimeoutText(float addOneSecon
                else {
                        retStr = strcat("Timeout begins in ", ftos(remainingLeadTime), " seconds!\n");
                }
 -              return retStr;
 +              return strcat(CPID_TIMEOUT_COUNTDOWN, retStr);
        }
        else if (timeoutStatus == 2) {
                if (addOneSecond) {
                        retStr = strcat("Timeout ends in ", ftos(remainingTimeoutTime + 1), " seconds!\n");
                        //don't show messages like "Timeout ends in 0 seconds"...
                        if ((remainingTimeoutTime + 1) > 0)
 -                              return retStr;
 +                              return strcat(CPID_TIMEOUT_COUNTDOWN, retStr);
                        else
 -                              return "";
 +                              return strcat(CPID_TIMEOUT_COUNTDOWN, "");
                }
                else {
                        retStr = strcat("Timeout ends in ", ftos(remainingTimeoutTime), " seconds!\n");
                        //don't show messages like "Timeout ends in 0 seconds"...
 -                      if (remainingTimeoutTime > 0)
 -                              return retStr;
 +                      if ((remainingTimeoutTime) > 0)
 +                              return strcat(CPID_TIMEOUT_COUNTDOWN, retStr);
                        else
 -                              return "";
 +                              return strcat(CPID_TIMEOUT_COUNTDOWN, "");
                }
        }
        else return "";
@@@ -2440,7 -2443,7 +2443,7 @@@ void LeaveSpectatorMode(
                                bprint ("^4", self.netname, "^4 is playing now\n");
  
                        if(!autocvar_g_campaign)
 -                              centerprint(self,""); // clear MOTD
 +                              centerprint(self, CPID_MOTD); // clear MOTD
  
                        return;
                } else {
@@@ -2898,7 -2901,7 +2901,7 @@@ void PlayerPreThink (void
        }
  
        if(!zoomstate_set)
-               SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_NEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_SNIPERRIFLE && autocvar_g_balance_sniperrifle_secondary == 0));
+               SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_NEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE && autocvar_g_balance_rifle_secondary == 0));
  
        float oldspectatee_status;
        oldspectatee_status = self.spectatee_status;
@@@ -3016,7 -3019,7 +3019,7 @@@ void PlayerPostThink (void
                {
                        if(timeleft != self.idlekick_lasttimeleft)
                        {
 -                              centerprint_atprio(self, CENTERPRIO_IDLEKICK, strcat("^3Stop idling!\n^3Disconnecting in ", ftos(timeleft), "..."));
 +                              centerprint_atprio(self, CENTERPRIO_IDLEKICK, strcat(CPID_DISCONNECT_IDLING, "^3Stop idling!\n^3Disconnecting in ", ftos(timeleft), "..."));
                                AnnounceTo(self, strcat(ftos(timeleft), ""));
                        }
                }