]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/hud.qc
Merge branch 'terencehill/menu_remove_tab_title' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud.qc
index ac1208d7e3ad1c180334bc4c7af5547c5972cae2..f3a8d673362c3040bb8ff744d1bca64ad87a1b5d 100644 (file)
@@ -1,3 +1,24 @@
+#include "hud.qh"
+#include "_all.qh"
+
+#include "hud_config.qh"
+#include "scoreboard.qh"
+#include "sortlist.qh"
+#include "teamradar.qh"
+#include "t_items.qh"
+
+#include "../common/buffs.qh"
+#include "../common/constants.qh"
+#include "../common/counting.qh"
+#include "../common/deathtypes.qh"
+#include "../common/mapinfo.qh"
+#include "../common/nades.qh"
+#include "../common/stats.qh"
+
+#include "../csqcmodellib/cl_player.qh"
+
+#include "../warpzonelib/mathlib.qh"
+
 /*
 ==================
 Misc HUD functions
@@ -19,7 +40,7 @@ void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector the
                drawpic(theOrigin, pic, theSize, theColor, theAlpha, 0);
                return;
     }
-       if (theBorderSize_x == 0 && theBorderSize_y == 0) // no border
+       if (theBorderSize.x == 0 && theBorderSize.y == 0) // no border
        {
                // draw only the central part
                drawsubpic(theOrigin, theSize, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
@@ -92,46 +113,92 @@ vector HUD_Get_Num_Color (float x, float maxvalue)
        float blinkingamt;
        vector color;
        if(x >= maxvalue) {
-               color_x = sin(2*M_PI*time);
-               color_y = 1;
-               color_z = sin(2*M_PI*time);
+               color.x = sin(2*M_PI*time);
+               color.y = 1;
+               color.z = sin(2*M_PI*time);
        }
        else if(x > maxvalue * 0.75) {
-               color_x = 0.4 - (x-150)*0.02 * 0.4; //red value between 0.4 -> 0
-               color_y = 0.9 + (x-150)*0.02 * 0.1; // green value between 0.9 -> 1
-               color_z = 0;
+               color.x = 0.4 - (x-150)*0.02 * 0.4; //red value between 0.4 -> 0
+               color.y = 0.9 + (x-150)*0.02 * 0.1; // green value between 0.9 -> 1
+               color.z = 0;
        }
        else if(x > maxvalue * 0.5) {
-               color_x = 1 - (x-100)*0.02 * 0.6; //red value between 1 -> 0.4
-               color_y = 1 - (x-100)*0.02 * 0.1; // green value between 1 -> 0.9
-               color_z = 1 - (x-100)*0.02; // blue value between 1 -> 0
+               color.x = 1 - (x-100)*0.02 * 0.6; //red value between 1 -> 0.4
+               color.y = 1 - (x-100)*0.02 * 0.1; // green value between 1 -> 0.9
+               color.z = 1 - (x-100)*0.02; // blue value between 1 -> 0
        }
        else if(x > maxvalue * 0.25) {
-               color_x = 1;
-               color_y = 1;
-               color_z = 0.2 + (x-50)*0.02 * 0.8; // blue value between 0.2 -> 1
+               color.x = 1;
+               color.y = 1;
+               color.z = 0.2 + (x-50)*0.02 * 0.8; // blue value between 0.2 -> 1
        }
        else if(x > maxvalue * 0.1) {
-               color_x = 1;
-               color_y = (x-20)*90/27/100; // green value between 0 -> 1
-               color_z = (x-20)*90/27/100 * 0.2; // blue value between 0 -> 0.2
+               color.x = 1;
+               color.y = (x-20)*90/27/100; // green value between 0 -> 1
+               color.z = (x-20)*90/27/100 * 0.2; // blue value between 0 -> 0.2
        }
        else {
-               color_x = 1;
-               color_y = 0;
-               color_z = 0;
+               color.x = 1;
+               color.y = 0;
+               color.z = 0;
        }
 
        blinkingamt = (1 - x/maxvalue/0.25);
        if(blinkingamt > 0)
        {
-               color_x = color.x - color.x * blinkingamt * sin(2*M_PI*time);
-               color_y = color.y - color.y * blinkingamt * sin(2*M_PI*time);
-               color_z = color.z - color.z * blinkingamt * sin(2*M_PI*time);
+               color.x = color.x - color.x * blinkingamt * sin(2*M_PI*time);
+               color.y = color.y - color.y * blinkingamt * sin(2*M_PI*time);
+               color.z = color.z - color.z * blinkingamt * sin(2*M_PI*time);
        }
        return color;
 }
 
+float HUD_GetRowCount(int item_count, vector size, float item_aspect)
+{
+       float aspect = size_y / size_x;
+       return bound(1, floor((sqrt(4 * item_aspect * aspect * item_count + aspect * aspect) + aspect + 0.5) / 2), item_count);
+}
+
+vector HUD_GetTableSize(int item_count, vector psize, float item_aspect)
+{
+       float columns, rows;
+       float ratio, best_ratio = 0;
+       float best_columns = 1, best_rows = 1;
+       bool vertical = (psize.x / psize.y >= item_aspect);
+       if(vertical)
+       {
+               psize = eX * psize.y + eY * psize.x;
+               item_aspect = 1 / item_aspect;
+       }
+
+       rows = ceil(sqrt(item_count));
+       columns = ceil(item_count/rows);
+       while(columns >= 1)
+       {
+               ratio = (psize.x/columns) / (psize.y/rows);
+               if(ratio > item_aspect)
+                       ratio = item_aspect * item_aspect / ratio;
+
+               if(ratio <= best_ratio)
+                       break; // ratio starts decreasing by now, skip next configurations
+
+               best_columns = columns;
+               best_rows = rows;
+               best_ratio = ratio;
+
+               if(columns == 1)
+                       break;
+
+               --columns;
+               rows = ceil(item_count/columns);
+       }
+
+       if(vertical)
+               return eX * best_rows + eY * best_columns;
+       else
+               return eX * best_columns + eY * best_rows;
+}
+
 float stringwidth_colors(string s, vector theSize)
 {
        return stringwidth(s, true, theSize);
@@ -142,20 +209,20 @@ float stringwidth_nocolors(string s, vector theSize)
        return stringwidth(s, false, theSize);
 }
 
-void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, float flag)
+void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
 {
        position.x -= 2 / 3 * strlen(text) * theScale.x;
        drawstring(position, text, theScale, rgb, theAlpha, flag);
 }
 
-void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, float flag)
+void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
 {
-       position_x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * theScale.x);
+       position.x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * theScale.x);
        drawstring(position, text, theScale, rgb, theAlpha, flag);
 }
 
 // return the string of the onscreen race timer
-string MakeRaceString(float cp, float mytime, float histime, float lapdelta, string hisname)
+string MakeRaceString(int cp, float mytime, float theirtime, float lapdelta, string theirname)
 {
        string col;
        string timestr;
@@ -163,7 +230,7 @@ string MakeRaceString(float cp, float mytime, float histime, float lapdelta, str
        string lapstr;
        lapstr = "";
 
-       if(histime == 0) // goal hit
+       if(theirtime == 0) // goal hit
        {
                if(mytime > 0)
                {
@@ -192,12 +259,12 @@ string MakeRaceString(float cp, float mytime, float histime, float lapdelta, str
                        col = "^1";
                }
        }
-       else if(histime > 0) // anticipation
+       else if(theirtime > 0) // anticipation
        {
-               if(mytime >= histime)
-                       timestr = strcat("+", ftos_decimals(mytime - histime, TIME_DECIMALS));
+               if(mytime >= theirtime)
+                       timestr = strcat("+", ftos_decimals(mytime - theirtime, TIME_DECIMALS));
                else
-                       timestr = TIME_ENCODED_TOSTRING(TIME_ENCODE(histime));
+                       timestr = TIME_ENCODED_TOSTRING(TIME_ENCODE(theirtime));
                col = "^3";
        }
        else
@@ -215,24 +282,25 @@ string MakeRaceString(float cp, float mytime, float histime, float lapdelta, str
        else
                cpname = _("Finish line");
 
-       if(histime < 0)
+       if(theirtime < 0)
                return strcat(col, cpname);
-       else if(hisname == "")
+       else if(theirname == "")
                return strcat(col, sprintf("%s (%s)", cpname, timestr));
        else
-               return strcat(col, sprintf("%s (%s %s)", cpname, timestr, strcat(hisname, col, lapstr)));
+               return strcat(col, sprintf("%s (%s %s)", cpname, timestr, strcat(theirname, col, lapstr)));
 }
 
 // Check if the given name already exist in race rankings? In that case, where? (otherwise return 0)
-float race_CheckName(string net_name) {
-       float i;
+int race_CheckName(string net_name)
+{
+       int i;
        for (i=RANKINGS_CNT-1;i>=0;--i)
                if(grecordholder[i] == net_name)
                        return i+1;
        return 0;
 }
 
-float GetPlayerColorForce(float i)
+int GetPlayerColorForce(int i)
 {
        if(!teamplay)
                return 0;
@@ -240,7 +308,7 @@ float GetPlayerColorForce(float i)
                return stof(getplayerkeyvalue(i, "colors")) & 15;
 }
 
-float GetPlayerColor(float i)
+int GetPlayerColor(int i)
 {
        if(!playerslots[i].gotscores) // unconnected
                return NUM_SPECTATOR;
@@ -250,7 +318,7 @@ float GetPlayerColor(float i)
                return GetPlayerColorForce(i);
 }
 
-string GetPlayerName(float i)
+string GetPlayerName(int i)
 {
        return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
 }
@@ -263,12 +331,13 @@ HUD panels
 */
 
 // draw the background/borders
-#define HUD_Panel_DrawBg(theAlpha)\
-if(panel.current_panel_bg != "0" && panel.current_panel_bg != "")\
-       draw_BorderPicture(panel_pos - '1 1 0' * panel_bg_border, panel.current_panel_bg, panel_size + '1 1 0' * 2 * panel_bg_border, panel_bg_color, panel_bg_alpha * theAlpha, '1 1 0' * (panel_bg_border/BORDER_MULTIPLIER))
+#define HUD_Panel_DrawBg(theAlpha) do {                                                                                                                                                                \
+       if(panel.current_panel_bg != "0" && panel.current_panel_bg != "")                                                                                               \
+               draw_BorderPicture(panel_pos - '1 1 0' * panel_bg_border, panel.current_panel_bg, panel_size + '1 1 0' * 2 * panel_bg_border, panel_bg_color, panel_bg_alpha * theAlpha, '1 1 0' * (panel_bg_border/BORDER_MULTIPLIER));\
+} while(0)
 
 //basically the same code of draw_ButtonPicture and draw_VertButtonPicture for the menu
-void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, float vertical, float baralign, vector theColor, float theAlpha, float drawflag)
+void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag)
 {
        if(!length_ratio || !theAlpha)
                return;
@@ -371,7 +440,7 @@ void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, flo
        }
 }
 
-void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, float drawflag)
+void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, int drawflag)
 {
        if(!theAlpha)
                return;
@@ -391,18 +460,17 @@ void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theA
 // Weapon icons (#0)
 //
 entity weaponorder[WEP_MAXCOUNT];
-void weaponorder_swap(float i, float j, entity pass)
+void weaponorder_swap(int i, int j, entity pass)
 {
-       entity h;
-       h = weaponorder[i];
+       entity h = weaponorder[i];
        weaponorder[i] = weaponorder[j];
        weaponorder[j] = h;
 }
 
 string weaponorder_cmp_str;
-float weaponorder_cmp(float i, float j, entity pass)
+int weaponorder_cmp(int i, int j, entity pass)
 {
-       float ai, aj;
+       int ai, aj;
        ai = strstrofs(weaponorder_cmp_str, sprintf(" %d ", weaponorder[i].weapon), 0);
        aj = strstrofs(weaponorder_cmp_str, sprintf(" %d ", weaponorder[j].weapon), 0);
        return aj - ai; // the string is in REVERSE order (higher prio at the right is what we want, but higher prio first is the string)
@@ -412,20 +480,19 @@ void HUD_Weapons(void)
 {
        // declarations
        WepSet weapons_stat = WepSet_GetFromStat();
-       float i, f, a;
+       int i;
+       float f, a;
        float screen_ar;
        vector center = '0 0 0';
-       float weapon_count, weapon_id;
-       float row, column, rows = 0, columns = 0;
+       int weapon_count, weapon_id;
+       int row, column, rows = 0, columns = 0;
+       bool vertical_order = true;
        float aspect = autocvar_hud_panel_weapons_aspect;
 
-       float panel_weapon_accuracy;
-
        float timeout = autocvar_hud_panel_weapons_timeout;
        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_full;
        vector barsize = '0 0 0', baroffset = '0 0 0';
        vector ammo_color = '1 0 1';
        float ammo_alpha = 1;
@@ -459,7 +526,7 @@ void HUD_Weapons(void)
        // figure out weapon order (how the weapons are sorted) // TODO make this configurable
        if(weaponorder_bypriority != autocvar_cl_weaponpriority || !weaponorder[0])
        {
-               float weapon_cnt;
+               int weapon_cnt;
                if(weaponorder_bypriority)
                        strunzone(weaponorder_bypriority);
                if(weaponorder_byimpulse)
@@ -489,15 +556,29 @@ void HUD_Weapons(void)
        if(!autocvar_hud_panel_weapons_complainbubble || autocvar__hud_configure || time - complain_weapon_time >= when + fadetime)
                complain_weapon = 0;
 
+       if(autocvar__hud_configure)
+       {
+               if(!weapons_stat)
+                       for(i = WEP_FIRST; i <= WEP_LAST; i += floor((WEP_LAST-WEP_FIRST)/5))
+                               weapons_stat |= WepSet_FromWeapon(i);
+
+               #if 0
+               /// debug code
+               if(cvar("wep_add"))
+               {
+                       weapons_stat = '0 0 0';
+                       float countw = 1 + floor((floor(time * cvar("wep_add"))) % WEP_COUNT);
+                       for(i = WEP_FIRST; i <= countw; ++i)
+                               weapons_stat |= WepSet_FromWeapon(i);
+               }
+               #endif
+       }
+
        // determine which weapons are going to be shown
        if (autocvar_hud_panel_weapons_onlyowned)
        {
                if(autocvar__hud_configure)
                {
-                       if (!weapons_stat)
-                               for(i = WEP_FIRST; i <= WEP_LAST; i += floor((WEP_LAST-WEP_FIRST)/5))
-                                       weapons_stat |= WepSet_FromWeapon(i);
-
                        if(menu_enabled != 2)
                                HUD_Panel_DrawBg(1); // also draw the bg of the entire panel
                }
@@ -505,12 +586,9 @@ void HUD_Weapons(void)
                // do we own this weapon?
                weapon_count = 0;
                for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
-                       if(weapons_stat & WepSet_FromWeapon(weaponorder[i].weapon))
+                       if((weapons_stat & WepSet_FromWeapon(weaponorder[i].weapon)) || (weaponorder[i].weapon == complain_weapon))
                                ++weapon_count;
 
-               // add it anyway if weaponcomplain is shown
-               if(complain_weapon)
-                       ++weapon_count;
 
                // might as well commit suicide now, no reason to live ;)
                if (weapon_count == 0)
@@ -519,41 +597,63 @@ void HUD_Weapons(void)
                        return;
                }
 
-               vector max_panel_size = panel_size - '2 2 0' * panel_bg_padding;
+               vector old_panel_size = panel_size;
+               vector padded_panel_size = panel_size - '2 2 0' * panel_bg_padding;
 
-               // calculate distribution and size of table cells
-               if(max_panel_size.x > max_panel_size.y)
-               {
-                       while(weapon_count > columns * rows)
-                       {
-                               ++rows;
-                               columns = ceil(max_panel_size.x / (max_panel_size.y / rows * aspect));
-                       }
+               // get the all-weapons layout
+               vector table_size = HUD_GetTableSize(WEP_COUNT, padded_panel_size, aspect);
+               columns = table_size.x;
+               rows = table_size.y;
+               weapon_size.x = padded_panel_size.x / columns;
+               weapon_size.y = padded_panel_size.y / rows;
 
-                       weapon_size_x = max_panel_size.x / columns;
-                       weapon_size_y = max_panel_size.y / rows;
-                       columns = ceil(weapon_count / rows);
+               // NOTE: although weapons should aways look the same even if onlyowned is enabled,
+               // we enlarge them a bit when possible to better match the desired aspect ratio
+               if(padded_panel_size.x / padded_panel_size.y < aspect)
+               {
+                       // maximum number of rows that allows to display items with the desired aspect ratio
+                       int max_rows = floor(padded_panel_size.y / (weapon_size.x / aspect));
+                       columns = min(columns, ceil(weapon_count / max_rows));
+                       rows = ceil(weapon_count / columns);
+                       weapon_size.y = min(padded_panel_size.y / rows, weapon_size.x / aspect);
+                       weapon_size.x = min(padded_panel_size.x / columns, aspect * weapon_size.y);
+                       vertical_order = false;
                }
                else
                {
-                       while(weapon_count > columns * rows)
-                       {
-                               ++columns;
-                               rows = ceil(max_panel_size.y / (max_panel_size.x / columns / aspect));
-                       }
-
-                       weapon_size_x = max_panel_size.x / columns;
-                       weapon_size_y = max_panel_size.y / rows;
-                       rows = ceil(weapon_count / columns);
+                       int max_columns = floor(padded_panel_size.x / (weapon_size.y * aspect));
+                       rows = min(rows, ceil(weapon_count / max_columns));
+                       columns = ceil(weapon_count / rows);
+                       weapon_size.x = min(padded_panel_size.x / columns, aspect * weapon_size.y);
+                       weapon_size.y = min(padded_panel_size.y / rows, weapon_size.x / aspect);
+                       vertical_order = true;
                }
 
                // reduce size of the panel
-               panel_size_x = columns * weapon_size.x;
-               panel_size_y = rows * weapon_size.y;
-               panel_pos.x += (max_panel_size.x - panel_size.x) / 2;
-               panel_pos.y += (max_panel_size.y - panel_size.y) / 2;
-
+               panel_size.x = columns * weapon_size.x;
+               panel_size.y = rows * weapon_size.y;
                panel_size += '2 2 0' * panel_bg_padding;
+
+               // center the resized panel, or snap it to the screen edge when close enough
+               if(panel_pos.x > vid_conwidth * 0.001)
+               {
+                       if(panel_pos.x + old_panel_size.x > vid_conwidth * 0.999)
+                               panel_pos.x += old_panel_size.x - panel_size.x;
+                       else
+                               panel_pos.x += (old_panel_size.x - panel_size.x) / 2;
+               }
+               else if(old_panel_size.x > vid_conwidth * 0.999)
+                       panel_pos.x += (old_panel_size.x - panel_size.x) / 2;
+
+               if(panel_pos.y > vid_conheight * 0.001)
+               {
+                       if(panel_pos.y + old_panel_size.y > vid_conheight * 0.999)
+                               panel_pos.y += old_panel_size.y - panel_size.y;
+                       else
+                               panel_pos.y += (old_panel_size.y - panel_size.y) / 2;
+               }
+               else if(old_panel_size.y > vid_conheight * 0.999)
+                       panel_pos.y += (old_panel_size.y - panel_size.y) / 2;
        }
        else
                weapon_count = WEP_COUNT;
@@ -581,8 +681,8 @@ void HUD_Weapons(void)
                        if (autocvar_hud_panel_weapons_timeout_effect == 2 || autocvar_hud_panel_weapons_timeout_effect == 3)
                        {
                                f *= f; // for a cooler movement
-                               center_x = panel_pos.x + panel_size.x/2;
-                               center_y = panel_pos.y + panel_size.y/2;
+                               center.x = panel_pos.x + panel_size.x/2;
+                               center.y = panel_pos.y + panel_size.y/2;
                                screen_ar = vid_conwidth/vid_conheight;
                                if (center.x/center.y < screen_ar) //bottom left
                                {
@@ -599,7 +699,7 @@ void HUD_Weapons(void)
                                                panel_pos.y -= f * (panel_pos.y + panel_size.y);
                                }
                                if(f == 1)
-                                       center_x = -1; // mark the panel as off screen
+                                       center.x = -1; // mark the panel as off screen
                        }
                        weaponprevtime = time - (1 - f) * timein_effect_length;
                }
@@ -624,8 +724,8 @@ void HUD_Weapons(void)
                        {
                                f *= f; // for a cooler movement
                                f = 1 - f;
-                               center_x = panel_pos.x + panel_size.x/2;
-                               center_y = panel_pos.y + panel_size.y/2;
+                               center.x = panel_pos.x + panel_size.x/2;
+                               center.y = panel_pos.y + panel_size.y/2;
                                screen_ar = vid_conwidth/vid_conheight;
                                if (center.x/center.y < screen_ar) //bottom left
                                {
@@ -648,7 +748,7 @@ void HUD_Weapons(void)
        // draw the background, then change the virtual size of it to better fit other items inside
        HUD_Panel_DrawBg(1);
 
-       if(center_x == -1)
+       if(center.x == -1)
        {
                draw_endBoldFont();
                return;
@@ -664,10 +764,12 @@ void HUD_Weapons(void)
 
        if(!rows) // if rows is > 0 onlyowned code has already updated these vars
        {
-               rows = panel_size.y/panel_size.x;
-               rows = bound(1, floor((sqrt(4 * aspect * rows * weapon_count + rows * rows) + rows + 0.5) / 2), weapon_count);
-               columns = ceil(weapon_count/rows);
-               weapon_size = eX * panel_size.x*(1/columns) + eY * panel_size.y*(1/rows);
+               vector table_size = HUD_GetTableSize(WEP_COUNT, panel_size, aspect);
+               columns = table_size.x;
+               rows = table_size.y;
+               weapon_size.x = panel_size.x / columns;
+               weapon_size.y = panel_size.y / rows;
+               vertical_order = (panel_size.x / panel_size.y >= aspect);
        }
 
        // calculate position/size for visual bar displaying ammount of ammo status
@@ -678,15 +780,15 @@ void HUD_Weapons(void)
 
                if(weapon_size.x/weapon_size.y > aspect)
                {
-                       barsize_x = aspect * weapon_size.y;
-                       barsize_y = weapon_size.y;
-                       baroffset_x = (weapon_size.x - barsize.x) / 2;
+                       barsize.x = aspect * weapon_size.y;
+                       barsize.y = weapon_size.y;
+                       baroffset.x = (weapon_size.x - barsize.x) / 2;
                }
                else
                {
-                       barsize_y = 1/aspect * weapon_size.x;
-                       barsize_x = weapon_size.x;
-                       baroffset_y = (weapon_size.y - barsize.y) / 2;
+                       barsize.y = 1/aspect * weapon_size.x;
+                       barsize.x = weapon_size.x;
+                       baroffset.y = (weapon_size.y - barsize.y) / 2;
                }
        }
        if(autocvar_hud_panel_weapons_accuracy)
@@ -721,7 +823,7 @@ void HUD_Weapons(void)
                // draw the weapon accuracy
                if(autocvar_hud_panel_weapons_accuracy)
                {
-                       panel_weapon_accuracy = weapon_accuracy[self.weapon-WEP_FIRST];
+                       float panel_weapon_accuracy = weapon_accuracy[self.weapon-WEP_FIRST];
                        if(panel_weapon_accuracy >= 0)
                        {
                                color = Accuracy_GetColor(panel_weapon_accuracy);
@@ -757,6 +859,7 @@ void HUD_Weapons(void)
                        // draw ammo status bar
                        if(autocvar_hud_panel_weapons_ammo && (self.ammo_field != ammo_none))
                        {
+                               float ammo_full;
                                a = getstati(GetAmmoStat(self.ammo_field)); // how much ammo do we have?
 
                                if(a > 0)
@@ -823,12 +926,33 @@ void HUD_Weapons(void)
                        drawstring_aspect(weapon_pos + '1 1 0' * padding, s, weapon_size - '2 2 0' * padding, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
                }
 
+               #if 0
+               /// debug code
+               if(!autocvar_hud_panel_weapons_onlyowned)
+               {
+                       drawfill(weapon_pos + '1 1 0', weapon_size - '2 2 0', '1 1 1', panel_fg_alpha * 0.2, DRAWFLAG_NORMAL);
+                       drawstring(weapon_pos, ftos(i + 1), label_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               }
+               #endif
+
                // continue with new position for the next weapon
-               ++row;
-               if(row >= rows)
+               if(vertical_order)
                {
-                       row = 0;
                        ++column;
+                       if(column >= columns)
+                       {
+                               column = 0;
+                               ++row;
+                       }
+               }
+               else
+               {
+                       ++row;
+                       if(row >= rows)
+                       {
+                               row = 0;
+                               ++column;
+                       }
                }
        }
 
@@ -838,26 +962,26 @@ void HUD_Weapons(void)
 // Ammo (#1)
 void DrawNadeScoreBar(vector myPos, vector mySize, vector color)
 {
-       
+
        HUD_Panel_DrawProgressBar(
                myPos + eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize.x,
                mySize - eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize.x,
-               autocvar_hud_panel_ammo_progressbar_name, 
-               getstatf(STAT_NADE_BONUS_SCORE), 0, 0, color, 
+               autocvar_hud_panel_ammo_progressbar_name,
+               getstatf(STAT_NADE_BONUS_SCORE), 0, 0, color,
                autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 
 }
 
-void DrawAmmoNades(vector myPos, vector mySize, float draw_expanding, float expand_time)
+void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time)
 {
        float theAlpha = 1, a, b;
        vector nade_color, picpos, numpos;
-       
+
        nade_color = Nade_Color(getstati(STAT_NADE_BONUS_TYPE));
-       
+
        a = getstatf(STAT_NADE_BONUS);
        b = getstatf(STAT_NADE_BONUS_SCORE);
-       
+
        if(autocvar_hud_panel_ammo_iconalign)
        {
                numpos = myPos;
@@ -875,23 +999,23 @@ void DrawAmmoNades(vector myPos, vector mySize, float draw_expanding, float expa
        {
                if(autocvar_hud_panel_ammo_text)
                        drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
-               
+
                if(draw_expanding)
                        drawpic_aspect_skin_expanding(picpos, "nade_nbg", '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL, expand_time);
-                       
+
                drawpic_aspect_skin(picpos, "nade_bg" , '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
                drawpic_aspect_skin(picpos, "nade_nbg" , '1 1 0' * mySize.y, nade_color, panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
        }
 }
 
-void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent, float isInfinite)
+void DrawAmmoItem(vector myPos, vector mySize, .int ammoType, bool isCurrent, bool isInfinite)
 {
        if(ammoType == ammo_none)
                return;
 
        // Initialize variables
 
-       float ammo;
+       int ammo;
        if(autocvar__hud_configure)
        {
                isCurrent = (ammoType == ammo_rockets); // Rockets always current
@@ -919,7 +1043,7 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent,
                textPos = myPos + eX * mySize.y;
        }
 
-       float isShadowed = (ammo <= 0 && !isCurrent && !isInfinite);
+       bool isShadowed = (ammo <= 0 && !isCurrent && !isInfinite);
 
        vector iconColor = isShadowed ? '0 0 0' : '1 1 1';
        vector textColor;
@@ -956,8 +1080,8 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent,
        drawpic_aspect_skin(iconPos, GetAmmoPicture(ammoType), '1 1 0' * mySize.y, iconColor, alpha, DRAWFLAG_NORMAL);
 }
 
-float nade_prevstatus;
-float nade_prevframe;
+int nade_prevstatus;
+int nade_prevframe;
 float nade_statuschange_time;
 void HUD_Ammo(void)
 {
@@ -983,10 +1107,11 @@ void HUD_Ammo(void)
                mySize -= '2 2 0' * panel_bg_padding;
        }
 
-       float rows = 0, columns, row, column;
+       int rows = 0, columns, row, column;
        float nade_cnt = getstatf(STAT_NADE_BONUS), nade_score = getstatf(STAT_NADE_BONUS_SCORE);
-       float draw_nades = (nade_cnt > 0 || nade_score > 0), nade_statuschange_elapsedtime;
-       float total_ammo_count;
+       bool draw_nades = (nade_cnt > 0 || nade_score > 0);
+       float nade_statuschange_elapsedtime;
+       int total_ammo_count;
 
        vector ammo_size;
        if (autocvar_hud_panel_ammo_onlycurrent)
@@ -1007,34 +1132,29 @@ void HUD_Ammo(void)
        else
                nade_prevstatus = nade_prevframe = nade_statuschange_time = 0;
 
-       rows = mySize.y/mySize.x;
-       rows = bound(1, floor((sqrt(4 * (3/1) * rows * (total_ammo_count) + rows * rows) + rows + 0.5) / 2), (total_ammo_count));
-       //                               ^^^ ammo item aspect goes here
-
+       rows = HUD_GetRowCount(total_ammo_count, mySize, 3);
        columns = ceil((total_ammo_count)/rows);
-
        ammo_size = eX * mySize.x*(1/columns) + eY * mySize.y*(1/rows);
-       
 
        vector offset = '0 0 0'; // fteqcc sucks
        float newSize;
        if(ammo_size.x/ammo_size.y > 3)
        {
                newSize = 3 * ammo_size.y;
-               offset_x = ammo_size.x - newSize;
+               offset.x = ammo_size.x - newSize;
                pos.x += offset.x/2;
-               ammo_size_x = newSize;
+               ammo_size.x = newSize;
        }
        else
        {
                newSize = 1/3 * ammo_size.x;
-               offset_y = ammo_size.y - newSize;
+               offset.y = ammo_size.y - newSize;
                pos.y += offset.y/2;
-               ammo_size_y = newSize;
+               ammo_size.y = newSize;
        }
 
-       float i;
-       float infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO);
+       int i;
+       bool infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO);
        row = column = 0;
        if(autocvar_hud_panel_ammo_onlycurrent)
        {
@@ -1062,7 +1182,7 @@ void HUD_Ammo(void)
        }
        else
        {
-               .float ammotype;
+               .int ammotype;
                row = column = 0;
                for(i = 0; i < AMMO_COUNT; ++i)
                {
@@ -1096,7 +1216,7 @@ void HUD_Ammo(void)
        draw_endBoldFont();
 }
 
-void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, float vertical, float icon_right_align, vector color, float theAlpha, float fadelerp)
+void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, bool vertical, bool icon_right_align, vector color, float theAlpha, float fadelerp)
 {
        vector newPos = '0 0 0', newSize = '0 0 0';
        vector picpos, numpos;
@@ -1105,19 +1225,19 @@ void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, fl
        {
                if(mySize.y/mySize.x > 2)
                {
-                       newSize_y = 2 * mySize.x;
-                       newSize_x = mySize.x;
+                       newSize.y = 2 * mySize.x;
+                       newSize.x = mySize.x;
 
-                       newPos_y = myPos.y + (mySize.y - newSize.y) / 2;
-                       newPos_x = myPos.x;
+                       newPos.y = myPos.y + (mySize.y - newSize.y) / 2;
+                       newPos.x = myPos.x;
                }
                else
                {
-                       newSize_x = 1/2 * mySize.y;
-                       newSize_y = mySize.y;
+                       newSize.x = 1/2 * mySize.y;
+                       newSize.y = mySize.y;
 
-                       newPos_x = myPos.x + (mySize.x - newSize.x) / 2;
-                       newPos_y = myPos.y;
+                       newPos.x = myPos.x + (mySize.x - newSize.x) / 2;
+                       newPos.y = myPos.y;
                }
 
                if(icon_right_align)
@@ -1143,19 +1263,19 @@ void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, fl
 
        if(mySize.x/mySize.y > 3)
        {
-               newSize_x = 3 * mySize.y;
-               newSize_y = mySize.y;
+               newSize.x = 3 * mySize.y;
+               newSize.y = mySize.y;
 
-               newPos_x = myPos.x + (mySize.x - newSize.x) / 2;
-               newPos_y = myPos.y;
+               newPos.x = myPos.x + (mySize.x - newSize.x) / 2;
+               newPos.y = myPos.y;
        }
        else
        {
-               newSize_y = 1/3 * mySize.x;
-               newSize_x = mySize.x;
+               newSize.y = 1/3 * mySize.x;
+               newSize.x = mySize.x;
 
-               newPos_y = myPos.y + (mySize.y - newSize.y) / 2;
-               newPos_x = myPos.x;
+               newPos.y = myPos.y + (mySize.y - newSize.y) / 2;
+               newPos.x = myPos.x;
        }
 
        if(icon_right_align) // right align
@@ -1175,7 +1295,7 @@ void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, fl
        drawpic_aspect_skin_expanding(picpos, icon, '1 1 0' * newSize.y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL, fadelerp);
 }
 
-void DrawNumIcon(vector myPos, vector mySize, float x, string icon, float vertical, float icon_right_align, vector color, float theAlpha)
+void DrawNumIcon(vector myPos, vector mySize, float x, string icon, bool vertical, bool icon_right_align, vector color, float theAlpha)
 {
        DrawNumIcon_expanding(myPos, mySize, x, icon, vertical, icon_right_align, color, theAlpha, 0);
 }
@@ -1226,10 +1346,10 @@ void HUD_Powerups(void)
        }
 
        float panel_ar = mySize.x/mySize.y;
-       float is_vertical = (panel_ar < 1);
+       bool is_vertical = (panel_ar < 1);
        vector shield_offset = '0 0 0', strength_offset = '0 0 0', superweapons_offset = '0 0 0';
 
-       float superweapons_is = -1;
+       int superweapons_is = -1;
 
        if(superweapons_time)
        {
@@ -1255,20 +1375,20 @@ void HUD_Powerups(void)
                if (panel_ar >= 4 || (panel_ar >= 1/4 && panel_ar < 1))
                {
                        mySize.x *= (1.0 / 3.0);
-                       superweapons_offset_x = mySize.x;
+                       superweapons_offset.x = mySize.x;
                        if (autocvar_hud_panel_powerups_flip)
-                               shield_offset_x = 2*mySize.x;
+                               shield_offset.x = 2*mySize.x;
                        else
-                               strength_offset_x = 2*mySize.x;
+                               strength_offset.x = 2*mySize.x;
                }
                else
                {
                        mySize.y *= (1.0 / 3.0);
-                       superweapons_offset_y = mySize.y;
+                       superweapons_offset.y = mySize.y;
                        if (autocvar_hud_panel_powerups_flip)
-                               shield_offset_y = 2*mySize.y;
+                               shield_offset.y = 2*mySize.y;
                        else
-                               strength_offset_y = 2*mySize.y;
+                               strength_offset.y = 2*mySize.y;
                }
        }
        else
@@ -1277,22 +1397,22 @@ void HUD_Powerups(void)
                {
                        mySize.x *= 0.5;
                        if (autocvar_hud_panel_powerups_flip)
-                               shield_offset_x = mySize.x;
+                               shield_offset.x = mySize.x;
                        else
-                               strength_offset_x = mySize.x;
+                               strength_offset.x = mySize.x;
                }
                else
                {
                        mySize.y *= 0.5;
                        if (autocvar_hud_panel_powerups_flip)
-                               shield_offset_y = mySize.y;
+                               shield_offset.y = mySize.y;
                        else
-                               strength_offset_y = mySize.y;
+                               strength_offset.y = mySize.y;
                }
        }
 
-       float shield_baralign, strength_baralign, superweapons_baralign;
-       float shield_iconalign, strength_iconalign, superweapons_iconalign;
+       bool shield_baralign, strength_baralign, superweapons_baralign;
+       bool shield_iconalign, strength_iconalign, superweapons_iconalign;
 
        if (autocvar_hud_panel_powerups_flip)
        {
@@ -1378,21 +1498,10 @@ void HUD_Powerups(void)
 // Health/armor (#3)
 //
 
-// prev_* vars contain the health/armor at the previous FRAME
-// set to -1 when player is dead or was not playing
-float prev_health, prev_armor;
-float health_damagetime, armor_damagetime;
-float health_beforedamage, armor_beforedamage;
-// old_p_* vars keep track of previous values when smoothing value changes of the progressbar
-float old_p_health, old_p_armor;
-float old_p_healthtime, old_p_armortime;
-// prev_p_* vars contain the health/armor progressbar value at the previous FRAME
-// set to -1 to forcedly stop effects when we switch spectated player (e.g. from playerX: 70h to playerY: 50h)
-float prev_p_health, prev_p_armor;
 
 void HUD_HealthArmor(void)
 {
-       float armor, health, fuel;
+       int armor, health, fuel;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_healtharmor) return;
@@ -1453,11 +1562,11 @@ void HUD_HealthArmor(void)
                mySize -= '2 2 0' * panel_bg_padding;
        }
 
-       float baralign = autocvar_hud_panel_healtharmor_baralign;
-       float iconalign = autocvar_hud_panel_healtharmor_iconalign;
+       int baralign = autocvar_hud_panel_healtharmor_baralign;
+       int iconalign = autocvar_hud_panel_healtharmor_iconalign;
 
-    float maxhealth = autocvar_hud_panel_healtharmor_maxhealth;
-    float maxarmor = autocvar_hud_panel_healtharmor_maxarmor;
+    int maxhealth = autocvar_hud_panel_healtharmor_maxhealth;
+    int maxarmor = autocvar_hud_panel_healtharmor_maxarmor;
        if(autocvar_hud_panel_healtharmor == 2) // combined health and armor display
        {
                vector v;
@@ -1495,27 +1604,27 @@ void HUD_HealthArmor(void)
        else
        {
                float panel_ar = mySize.x/mySize.y;
-               float is_vertical = (panel_ar < 1);
+               bool is_vertical = (panel_ar < 1);
                vector health_offset = '0 0 0', armor_offset = '0 0 0';
                if (panel_ar >= 4 || (panel_ar >= 1/4 && panel_ar < 1))
                {
                        mySize.x *= 0.5;
                        if (autocvar_hud_panel_healtharmor_flip)
-                               health_offset_x = mySize.x;
+                               health_offset.x = mySize.x;
                        else
-                               armor_offset_x = mySize.x;
+                               armor_offset.x = mySize.x;
                }
                else
                {
                        mySize.y *= 0.5;
                        if (autocvar_hud_panel_healtharmor_flip)
-                               health_offset_y = mySize.y;
+                               health_offset.y = mySize.y;
                        else
-                               armor_offset_y = mySize.y;
+                               armor_offset.y = mySize.y;
                }
 
-               float health_baralign, armor_baralign, fuel_baralign;
-               float health_iconalign, armor_iconalign;
+               bool health_baralign, armor_baralign, fuel_baralign;
+               bool health_iconalign, armor_iconalign;
                if (autocvar_hud_panel_healtharmor_flip)
                {
                        armor_baralign = (autocvar_hud_panel_healtharmor_baralign == 2 || autocvar_hud_panel_healtharmor_baralign == 1);
@@ -1719,7 +1828,7 @@ void HUD_Notify(void)
        float fade_time = max(0, autocvar_hud_panel_notify_fadetime);
        float icon_aspect = max(1, autocvar_hud_panel_notify_icon_aspect);
 
-       float entry_count = bound(1, floor(NOTIFY_MAX_ENTRIES * size.y / size.x), NOTIFY_MAX_ENTRIES);
+       int entry_count = bound(1, floor(NOTIFY_MAX_ENTRIES * size.y / size.x), NOTIFY_MAX_ENTRIES);
        float entry_height = size.y / entry_count;
 
        float panel_width_half = size.x * 0.5;
@@ -1734,7 +1843,8 @@ void HUD_Notify(void)
 
        vector attacker_pos, victim_pos, icon_pos;
        string attacker, victim, icon;
-       float i, j, count, step, limit, alpha;
+       int i, j, count, step, limit;
+       float alpha;
 
        if (autocvar_hud_panel_notify_flip)
        {
@@ -1902,10 +2012,10 @@ void HUD_Radar(void)
        if (hud_panel_radar_maximized && !autocvar__hud_configure)
        {
                panel_size = autocvar_hud_panel_radar_maximized_size;
-               panel_size_x = bound(0.2, panel_size.x, 1) * vid_conwidth;
-               panel_size_y = bound(0.2, panel_size.y, 1) * vid_conheight;
-               panel_pos_x = (vid_conwidth - panel_size.x) / 2;
-               panel_pos_y = (vid_conheight - panel_size.y) / 2;
+               panel_size.x = bound(0.2, panel_size.x, 1) * vid_conwidth;
+               panel_size.y = bound(0.2, panel_size.y, 1) * vid_conheight;
+               panel_pos.x = (vid_conwidth - panel_size.x) / 2;
+               panel_pos.y = (vid_conheight - panel_size.y) / 2;
 
                string panel_bg;
                panel_bg = strcat(hud_skin_path, "/border_default"); // always use the default border when maximized
@@ -1985,7 +2095,7 @@ void HUD_Radar(void)
                mySize -= '2 2 0' * panel_bg_padding;
        }
 
-       float color2;
+       int color2;
        entity tm;
        float scale2d, normalsize, bigsize;
 
@@ -2016,8 +2126,8 @@ void HUD_Radar(void)
                c2 = rotate('1 0 0' * mi_min.x + '0 1 0' * mi_max.y, teamradar_angle * DEG2RAD);
                c3 = rotate('1 0 0' * mi_max.x + '0 1 0' * mi_min.y, teamradar_angle * DEG2RAD);
                span = '0 0 0';
-               span_x = max(c0_x, c1_x, c2_x, c3_x) - min(c0_x, c1_x, c2_x, c3_x);
-               span_y = max(c0_y, c1_y, c2_y, c3_y) - min(c0_y, c1_y, c2_y, c3_y);
+               span.x = max(c0_x, c1_x, c2_x, c3_x) - min(c0_x, c1_x, c2_x, c3_x);
+               span.y = max(c0_y, c1_y, c2_y, c3_y) - min(c0_y, c1_y, c2_y, c3_y);
 
                // max-min distance must fit the radar in x=x, y=y
                bigsize = min(
@@ -2068,9 +2178,9 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
 {
        float score;
        entity tm = world, pl;
-       float SCOREPANEL_MAX_ENTRIES = 6;
+       int SCOREPANEL_MAX_ENTRIES = 6;
        float SCOREPANEL_ASPECTRATIO = 2;
-       float entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize.y/mySize.x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES);
+       int entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize.y/mySize.x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES);
        vector fontsize = '1 1 0' * (mySize.y/entries);
 
        vector rgb, score_color;
@@ -2080,7 +2190,8 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
        float name_size = mySize.x*0.75;
        float spacing_size = mySize.x*0.04;
        const float highlight_alpha = 0.2;
-       float i = 0, me_printed = 0, first_pl = 0;
+       int i = 0, first_pl = 0;
+       bool me_printed = false;
        string s;
        if (autocvar__hud_configure)
        {
@@ -2171,7 +2282,7 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
                {
                        if (i == first_pl)
                                rgb = '0 1 0'; //first: green
-                       me_printed = 1;
+                       me_printed = true;
                        drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                }
                if (team_count)
@@ -2301,28 +2412,24 @@ void HUD_Score(void)
                }
                if(spectatee_status == -1)
                {
-                       rows = mySize.y/mySize.x;
-                       rows = bound(1, floor((sqrt(4 * (3/1) * rows * team_count + rows * rows) + rows + 0.5) / 2), team_count);
-                       //                               ^^^ ammo item aspect goes here
-
+                       rows = HUD_GetRowCount(team_count, mySize, 3);
                        columns = ceil(team_count/rows);
-
                        score_size = eX * mySize.x*(1/columns) + eY * mySize.y*(1/rows);
 
                        float newSize;
                        if(score_size.x/score_size.y > 3)
                        {
                                newSize = 3 * score_size.y;
-                               offset_x = score_size.x - newSize;
+                               offset.x = score_size.x - newSize;
                                pos.x += offset.x/2;
-                               score_size_x = newSize;
+                               score_size.x = newSize;
                        }
                        else
                        {
                                newSize = 1/3 * score_size.x;
-                               offset_y = score_size.y - newSize;
+                               offset.y = score_size.y - newSize;
                                pos.y += offset.y/2;
-                               score_size_y = newSize;
+                               score_size.y = newSize;
                        }
                }
                else
@@ -2400,17 +2507,17 @@ void HUD_RaceTimer (void)
        vector newSize = '0 0 0';
        if(mySize.x/mySize.y > 4)
        {
-               newSize_x = 4 * mySize.y;
-               newSize_y = mySize.y;
+               newSize.x = 4 * mySize.y;
+               newSize.y = mySize.y;
 
-               pos_x = pos.x + (mySize.x - newSize.x) / 2;
+               pos.x = pos.x + (mySize.x - newSize.x) / 2;
        }
        else
        {
-               newSize_y = 1/4 * mySize.x;
-               newSize_x = mySize.x;
+               newSize.y = 1/4 * mySize.x;
+               newSize.x = mySize.x;
 
-               pos_y = pos.y + (mySize.y - newSize.y) / 2;
+               pos.y = pos.y + (mySize.y - newSize.y) / 2;
        }
        mySize = newSize;
 
@@ -2519,15 +2626,6 @@ void HUD_RaceTimer (void)
 
 // Vote window (#9)
 //
-float vote_yescount;
-float vote_nocount;
-float vote_needed;
-float vote_highlighted; // currently selected vote
-
-float vote_active; // is there an active vote?
-float vote_prev; // previous state of vote_active to check for a change
-float vote_alpha;
-float vote_change; // "time" when vote_active changed
 
 void HUD_Vote(void)
 {
@@ -2608,17 +2706,17 @@ void HUD_Vote(void)
        vector newSize = '0 0 0';
        if(mySize.x/mySize.y > 3)
        {
-               newSize_x = 3 * mySize.y;
-               newSize_y = mySize.y;
+               newSize.x = 3 * mySize.y;
+               newSize.y = mySize.y;
 
-               pos_x = pos.x + (mySize.x - newSize.x) / 2;
+               pos.x = pos.x + (mySize.x - newSize.x) / 2;
        }
        else
        {
-               newSize_y = 1/3 * mySize.x;
-               newSize_x = mySize.x;
+               newSize.y = 1/3 * mySize.x;
+               newSize.x = mySize.x;
 
-               pos_y = pos.y + (mySize.y - newSize.y) / 2;
+               pos.y = pos.y + (mySize.y - newSize.y) / 2;
        }
        mySize = newSize;
 
@@ -2669,11 +2767,11 @@ void HUD_Vote(void)
 // Mod icons panel (#10)
 //
 
-float mod_active; // is there any active mod icon?
+bool mod_active; // is there any active mod icon?
 
-void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, float i)
+void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
 {
-       float stat = -1;
+       int stat = -1;
        string pic = "";
        vector color = '0 0 0';
        switch(i)
@@ -2704,14 +2802,14 @@ void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, flo
        if(mySize.x/mySize.y > aspect_ratio)
        {
                i = aspect_ratio * mySize.y;
-               myPos_x = myPos.x + (mySize.x - i) / 2;
-               mySize_x = i;
+               myPos.x = myPos.x + (mySize.x - i) / 2;
+               mySize.x = i;
        }
        else
        {
                i = 1/aspect_ratio * mySize.x;
-               myPos_y = myPos.y + (mySize.y - i) / 2;
-               mySize_y = i;
+               myPos.y = myPos.y + (mySize.y - i) / 2;
+               mySize.y = i;
        }
 
        if(layout)
@@ -2733,10 +2831,10 @@ void HUD_Mod_CA(vector myPos, vector mySize)
                layout = autocvar_hud_panel_modicons_ca_layout;
        else //if(gametype == MAPINFO_TYPE_FREEZETAG)
                layout = autocvar_hud_panel_modicons_freezetag_layout;
-       float rows, columns, aspect_ratio;
-       rows = mySize.y/mySize.x;
+       int rows, columns;
+       float aspect_ratio;
        aspect_ratio = (layout) ? 2 : 1;
-       rows = bound(1, floor((sqrt((4 * aspect_ratio * team_count + rows) * rows) + rows + 0.5) / 2), team_count);
+       rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
        columns = ceil(team_count/rows);
 
        int i;
@@ -2760,7 +2858,7 @@ void HUD_Mod_CA(vector myPos, vector mySize)
 
 // CTF HUD modicon section
 float redflag_prevframe, blueflag_prevframe; // status during previous frame
-float redflag_prevstatus, blueflag_prevstatus; // last remembered status
+int redflag_prevstatus, blueflag_prevstatus; // last remembered status
 float redflag_statuschange_time, blueflag_statuschange_time; // time when the status changed
 
 void HUD_Mod_CTF_Reset(void)
@@ -2774,9 +2872,9 @@ void HUD_Mod_CTF(vector pos, vector mySize)
        vector flag_size;
        float f; // every function should have that
 
-       float redflag, blueflag; // current status
+       int redflag, blueflag; // current status
        float redflag_statuschange_elapsedtime, blueflag_statuschange_elapsedtime; // time since the status changed
-       float stat_items;
+       int stat_items;
 
        stat_items = getstati(STAT_ITEMS, 0, 24);
        redflag = (stat_items/IT_RED_FLAG_TAKEN) & 3;
@@ -2918,9 +3016,9 @@ void HUD_Mod_KH(vector pos, vector mySize)
 
        // Read current state
 
-       float state = getstati(STAT_KH_KEYS);
-       float i, key_state;
-       float all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
+       int state = getstati(STAT_KH_KEYS);
+       int i, key_state;
+       int all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
        all_keys = team1_keys = team2_keys = team3_keys = team4_keys = dropped_keys = carrying_keys = 0;
 
        for(i = 0; i < 4; ++i)
@@ -3039,7 +3137,7 @@ void HUD_Mod_KH(vector pos, vector mySize)
 }
 
 // Keepaway HUD mod icon
-float kaball_prevstatus; // last remembered status
+int kaball_prevstatus; // last remembered status
 float kaball_statuschange_time; // time when the status changed
 
 // we don't need to reset for keepaway since it immediately
@@ -3054,8 +3152,8 @@ void HUD_Mod_Keepaway(vector pos, vector mySize)
        float BLINK_FREQ = 5;
        float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
 
-       float stat_items = getstati(STAT_ITEMS, 0, 24);
-       float kaball = (stat_items/IT_KEY1) & 1;
+       int stat_items = getstati(STAT_ITEMS, 0, 24);
+       int kaball = (stat_items/IT_KEY1) & 1;
 
        if(kaball != kaball_prevstatus)
        {
@@ -3087,7 +3185,8 @@ void HUD_Mod_Keepaway(vector pos, vector mySize)
 // Nexball HUD mod icon
 void HUD_Mod_NexBall(vector pos, vector mySize)
 {
-       float stat_items, nb_pb_starttime, dt, p;
+       float nb_pb_starttime, dt, p;
+       int stat_items;
 
        stat_items = getstati(STAT_ITEMS, 0, 24);
        nb_pb_starttime = getstatf(STAT_NB_METERSTART);
@@ -3120,7 +3219,7 @@ float srecordtime_prev; // last remembered srecordtime
 float srecordtime_change_time; // time when srecordtime last changed
 
 float race_status_time;
-float race_status_prev;
+int race_status_prev;
 string race_status_name_prev;
 void HUD_Mod_Race(vector pos, vector mySize)
 {
@@ -3260,7 +3359,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
        }
 }
 
-void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, float i)
+void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
 {
        float stat = -1;
        string pic = "";
@@ -3294,14 +3393,14 @@ void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, fl
        if(mySize.x/mySize.y > aspect_ratio)
        {
                i = aspect_ratio * mySize.y;
-               myPos_x = myPos.x + (mySize.x - i) / 2;
-               mySize_x = i;
+               myPos.x = myPos.x + (mySize.x - i) / 2;
+               mySize.x = i;
        }
        else
        {
                i = 1/aspect_ratio * mySize.x;
-               myPos_y = myPos.y + (mySize.y - i) / 2;
-               mySize_y = i;
+               myPos.y = myPos.y + (mySize.y - i) / 2;
+               mySize.y = i;
        }
 
        if (layout) // show text too
@@ -3329,10 +3428,10 @@ void HUD_Mod_Dom(vector myPos, vector mySize)
        mod_active = 1; // required in each mod function that always shows something
 
        int layout = autocvar_hud_panel_modicons_dom_layout;
-       float rows, columns, aspect_ratio;
-       rows = mySize.y/mySize.x;
+       int rows, columns;
+       float aspect_ratio;
        aspect_ratio = (layout) ? 3 : 1;
-       rows = bound(1, floor((sqrt((4 * aspect_ratio * team_count + rows) * rows) + rows + 0.5) / 2), team_count);
+       rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
        columns = ceil(team_count/rows);
 
        int i;
@@ -3370,7 +3469,7 @@ void HUD_ModIcons_SetFunc()
        }
 }
 
-float mod_prev; // previous state of mod_active to check for a change
+int mod_prev; // previous state of mod_active to check for a change
 float mod_alpha;
 float mod_change; // "time" when mod_active changed
 
@@ -3442,17 +3541,17 @@ void HUD_PressedKeys(void)
                vector newSize = '0 0 0';
                if(mySize.x/mySize.y > aspect)
                {
-                       newSize_x = aspect * mySize.y;
-                       newSize_y = mySize.y;
+                       newSize.x = aspect * mySize.y;
+                       newSize.y = mySize.y;
 
-                       pos_x = pos.x + (mySize.x - newSize.x) / 2;
+                       pos.x = pos.x + (mySize.x - newSize.x) / 2;
                }
                else
                {
-                       newSize_y = 1/aspect * mySize.x;
-                       newSize_x = mySize.x;
+                       newSize.y = 1/aspect * mySize.x;
+                       newSize.x = mySize.x;
 
-                       pos_y = pos.y + (mySize.y - newSize.y) / 2;
+                       pos.y = pos.y + (mySize.y - newSize.y) / 2;
                }
                mySize = newSize;
        }
@@ -3505,8 +3604,8 @@ void HUD_Chat(void)
 
        if(autocvar__con_chat_maximized && !autocvar__hud_configure) // draw at full screen height if maximized
        {
-               panel_pos_y = panel_bg_border;
-               panel_size_y = vid_conheight - panel_bg_border * 2;
+               panel_pos.y = panel_bg_border;
+               panel_size.y = vid_conheight - panel_bg_border * 2;
                if(panel.current_panel_bg == "0") // force a border when maximized
                {
                        string panel_bg;
@@ -3564,7 +3663,7 @@ void HUD_Chat(void)
 //
 float prevfps;
 float prevfps_time;
-float framecounter;
+int framecounter;
 
 float frametimeavg;
 float frametimeavg1; // 1 frame ago
@@ -3624,11 +3723,12 @@ void HUD_EngineInfo(void)
 
 // Info messages panel (#14)
 //
-#define drawInfoMessage(s)\
-       if(autocvar_hud_panel_infomessages_flip)\
-               o_x = pos.x + mySize.x - stringwidth(s, true, fontsize);\
-       drawcolorcodedstring(o, s, fontsize, a, DRAWFLAG_NORMAL);\
-       o.y += fontsize.y;
+#define drawInfoMessage(s) do {                                                                                                                                                                                \
+       if(autocvar_hud_panel_infomessages_flip)                                                                                                                                                \
+               o.x = pos.x + mySize.x - stringwidth(s, true, fontsize);                                                                                                        \
+       drawcolorcodedstring(o, s, fontsize, a, DRAWFLAG_NORMAL);                                                                                                               \
+       o.y += fontsize.y;                                                                                                                                                                                              \
+} while(0)
 void HUD_InfoMessages(void)
 {
        if(!autocvar__hud_configure)
@@ -3652,17 +3752,17 @@ void HUD_InfoMessages(void)
        vector newSize = '0 0 0';
        if(mySize.x/mySize.y > 5)
        {
-               newSize_x = 5 * mySize.y;
-               newSize_y = mySize.y;
+               newSize.x = 5 * mySize.y;
+               newSize.y = mySize.y;
 
-               pos_x = pos.x + (mySize.x - newSize.x) / 2;
+               pos.x = pos.x + (mySize.x - newSize.x) / 2;
        }
        else
        {
-               newSize_y = 1/5 * mySize.x;
-               newSize_x = mySize.x;
+               newSize.y = 1/5 * mySize.x;
+               newSize.x = mySize.x;
 
-               pos_y = pos.y + (mySize.y - newSize.y) / 2;
+               pos.y = pos.y + (mySize.y - newSize.y) / 2;
        }
 
        mySize = newSize;
@@ -3686,22 +3786,22 @@ void HUD_InfoMessages(void)
                                s = _("^1Observing");
                        else
                                s = sprintf(_("^1Spectating: ^7%s"), GetPlayerName(player_localentnum - 1));
-                       drawInfoMessage(s)
+                       drawInfoMessage(s);
 
                        if(spectatee_status == -1)
                                s = sprintf(_("^1Press ^3%s^1 to spectate"), getcommandkey("primary fire", "+fire"));
                        else
                                s = sprintf(_("^1Press ^3%s^1 or ^3%s^1 for next or previous player"), getcommandkey("next weapon", "weapnext"), getcommandkey("previous weapon", "weapprev"));
-                       drawInfoMessage(s)
+                       drawInfoMessage(s);
 
                        if(spectatee_status == -1)
                                s = sprintf(_("^1Use ^3%s^1 or ^3%s^1 to change the speed"), getcommandkey("next weapon", "weapnext"), getcommandkey("previous weapon", "weapprev"));
                        else
                                s = sprintf(_("^1Press ^3%s^1 to observe"), getcommandkey("secondary fire", "+fire2"));
-                       drawInfoMessage(s)
+                       drawInfoMessage(s);
 
                        s = sprintf(_("^1Press ^3%s^1 for gamemode info"), getcommandkey("server info", "+show_info"));
-                       drawInfoMessage(s)
+                       drawInfoMessage(s);
 
                        if(gametype == MAPINFO_TYPE_LMS)
                        {
@@ -3716,7 +3816,7 @@ void HUD_InfoMessages(void)
                        }
                        else
                                s = sprintf(_("^1Press ^3%s^1 to join"), getcommandkey("jump", "+jump"));
-                       drawInfoMessage(s)
+                       drawInfoMessage(s);
 
                        //show restart countdown:
                        if (time < getstatf(STAT_GAMESTARTTIME)) {
@@ -3731,7 +3831,7 @@ void HUD_InfoMessages(void)
                if(warmup_stage && !intermission)
                {
                        s = _("^2Currently in ^1warmup^2 stage!");
-                       drawInfoMessage(s)
+                       drawInfoMessage(s);
                }
 
                string blinkcolor;
@@ -3756,12 +3856,12 @@ void HUD_InfoMessages(void)
                                else
                                        s = _("^2Waiting for others to ready up...");
                        }
-                       drawInfoMessage(s)
+                       drawInfoMessage(s);
                }
                else if(warmup_stage && !intermission && !spectatee_status)
                {
                        s = sprintf(_("^2Press ^3%s^2 to end warmup"), getcommandkey("ready", "ready"));
-                       drawInfoMessage(s)
+                       drawInfoMessage(s);
                }
 
                if(teamplay && !intermission && !spectatee_status && gametype != MAPINFO_TYPE_CA && teamnagger)
@@ -3770,7 +3870,7 @@ void HUD_InfoMessages(void)
                        tm = teams.sort_next;
                        if (tm)
                        {
-                               for(0; tm.sort_next; tm = tm.sort_next)
+                               for (; tm.sort_next; tm = tm.sort_next)
                                {
                                        if(!tm.team_size || tm.team == NUM_SPECTATOR)
                                                continue;
@@ -3787,7 +3887,7 @@ void HUD_InfoMessages(void)
                                        if (tm.team != NUM_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)
+                                       drawInfoMessage(s);
                                }
                        }
                }
@@ -3795,13 +3895,13 @@ void HUD_InfoMessages(void)
        else
        {
                s = _("^7Press ^3ESC ^7to show HUD options.");
-               drawInfoMessage(s)
+               drawInfoMessage(s);
                s = _("^3Doubleclick ^7a panel for panel-specific options.");
-               drawInfoMessage(s)
+               drawInfoMessage(s);
                s = _("^3CTRL ^7to disable collision testing, ^3SHIFT ^7and");
-               drawInfoMessage(s)
+               drawInfoMessage(s);
                s = _("^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments.");
-               drawInfoMessage(s)
+               drawInfoMessage(s);
        }
 }
 
@@ -3907,19 +4007,19 @@ void HUD_Physics(void)
        {
                panel_size.x *= 0.5;
                if (autocvar_hud_panel_physics_flip)
-                       speed_offset_x = panel_size.x;
+                       speed_offset.x = panel_size.x;
                else
-                       acceleration_offset_x = panel_size.x;
+                       acceleration_offset.x = panel_size.x;
        }
        else
        {
                panel_size.y *= 0.5;
                if (autocvar_hud_panel_physics_flip)
-                       speed_offset_y = panel_size.y;
+                       speed_offset.y = panel_size.y;
                else
-                       acceleration_offset_y = panel_size.y;
+                       acceleration_offset.y = panel_size.y;
        }
-       float speed_baralign, acceleration_baralign;
+       int speed_baralign, acceleration_baralign;
        if (autocvar_hud_panel_physics_baralign == 1)
                acceleration_baralign = speed_baralign = 1;
     else if(autocvar_hud_panel_physics_baralign == 4)
@@ -3944,26 +4044,26 @@ void HUD_Physics(void)
        vector tmp_offset = '0 0 0', tmp_size = '0 0 0';
        if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 2)
        {
-               tmp_size_x = panel_size.x * 0.75;
-               tmp_size_y = panel_size.y * text_scale;
+               tmp_size.x = panel_size.x * 0.75;
+               tmp_size.y = panel_size.y * text_scale;
                if (speed_baralign)
-                       tmp_offset_x = panel_size.x - tmp_size.x;
+                       tmp_offset.x = panel_size.x - tmp_size.x;
                //else
                        //tmp_offset_x = 0;
-               tmp_offset_y = (panel_size.y - tmp_size.y) / 2;
+               tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
                drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(speed), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 
                //draw speed unit
                if (speed_baralign)
-                       tmp_offset_x = 0;
+                       tmp_offset.x = 0;
                else
-                       tmp_offset_x = tmp_size.x;
+                       tmp_offset.x = tmp_size.x;
                if (autocvar_hud_panel_physics_speed_unit_show)
                {
                        //tmp_offset_y = 0;
-                       tmp_size_x = panel_size.x * (1 - 0.75);
-                       tmp_size_y = panel_size.y * 0.4 * text_scale;
-                       tmp_offset_y = (panel_size.y * 0.4 - tmp_size.y) / 2;
+                       tmp_size.x = panel_size.x * (1 - 0.75);
+                       tmp_size.y = panel_size.y * 0.4 * text_scale;
+                       tmp_offset.y = (panel_size.y * 0.4 - tmp_size.y) / 2;
                        drawstring_aspect(panel_pos + speed_offset + tmp_offset, unit, tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                }
        }
@@ -4007,8 +4107,8 @@ void HUD_Physics(void)
                                        peak_offsetX = (1 - min(top_speed, max_speed)/max_speed) * panel_size.x;
                 else // if (speed_baralign == 2)
                     peak_offsetX = min(top_speed, max_speed)/max_speed * panel_size.x * 0.5;
-                               peak_size_x = floor(panel_size.x * 0.01 + 1.5);
-                peak_size_y = panel_size.y;
+                               peak_size.x = floor(panel_size.x * 0.01 + 1.5);
+                peak_size.y = panel_size.y;
                 if (speed_baralign == 2) // draw two peaks, on both sides
                 {
                     drawfill(panel_pos + speed_offset + eX * (0.5 * panel_size.x + peak_offsetX - peak_size.x), peak_size, autocvar_hud_progressbar_speed_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
@@ -4019,9 +4119,9 @@ void HUD_Physics(void)
                        }
 
                        //top speed
-                       tmp_offset_y = panel_size.y * 0.4;
-                       tmp_size_x = panel_size.x * (1 - 0.75);
-                       tmp_size_y = (panel_size.y - tmp_offset.y) * text_scale;
+                       tmp_offset.y = panel_size.y * 0.4;
+                       tmp_size.x = panel_size.x * (1 - 0.75);
+                       tmp_size.y = (panel_size.y - tmp_offset.y) * text_scale;
                        tmp_offset.y += (panel_size.y - tmp_offset.y - tmp_size.y) / 2;
                        drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(top_speed), tmp_size, '1 0 0', f * panel_fg_alpha, DRAWFLAG_NORMAL);
                }
@@ -4048,12 +4148,12 @@ void HUD_Physics(void)
                        tmp_size = acceleration_progressbar_scale * panel_size.x * eX + panel_size.y * eY;
 
                        if (acceleration_baralign == 1)
-                               tmp_offset_x = panel_size.x - tmp_size.x;
+                               tmp_offset.x = panel_size.x - tmp_size.x;
                        else if (acceleration_baralign == 2 || acceleration_baralign == 3)
-                               tmp_offset_x = (panel_size.x - tmp_size.x) / 2;
+                               tmp_offset.x = (panel_size.x - tmp_size.x) / 2;
                        else
-                               tmp_offset_x = 0;
-                       tmp_offset_y = 0;
+                               tmp_offset.x = 0;
+                       tmp_offset.y = 0;
                }
                else
                {
@@ -4063,10 +4163,10 @@ void HUD_Physics(void)
 
                HUD_Panel_DrawProgressBar(panel_pos + acceleration_offset + tmp_offset, tmp_size, "accelbar", f, 0, acceleration_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
        }
-       tmp_size_x = panel_size.x;
-       tmp_size_y = panel_size.y * text_scale;
-       tmp_offset_x = 0;
-       tmp_offset_y = (panel_size.y - tmp_size.y) / 2;
+       tmp_size.x = panel_size.x;
+       tmp_size.y = panel_size.y * text_scale;
+       tmp_offset.x = 0;
+       tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
        if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 3)
                drawstring_aspect(panel_pos + acceleration_offset + tmp_offset, strcat(ftos_decimals(acceleration, 2), "g"), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 
@@ -4075,21 +4175,21 @@ void HUD_Physics(void)
 
 // CenterPrint (#16)
 //
-const float CENTERPRINT_MAX_MSGS = 10;
-const float CENTERPRINT_MAX_ENTRIES = 50;
+const int CENTERPRINT_MAX_MSGS = 10;
+const int CENTERPRINT_MAX_ENTRIES = 50;
 const float CENTERPRINT_SPACING = 0.7;
-float cpm_index;
+int cpm_index;
 string centerprint_messages[CENTERPRINT_MAX_MSGS];
-float centerprint_msgID[CENTERPRINT_MAX_MSGS];
+int centerprint_msgID[CENTERPRINT_MAX_MSGS];
 float centerprint_time[CENTERPRINT_MAX_MSGS];
 float centerprint_expire_time[CENTERPRINT_MAX_MSGS];
-float centerprint_countdown_num[CENTERPRINT_MAX_MSGS];
-float centerprint_showing;
+int centerprint_countdown_num[CENTERPRINT_MAX_MSGS];
+bool centerprint_showing;
 
-void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num)
+void centerprint_generic(int new_id, string strMessage, float duration, int countdown_num)
 {
        //printf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num);
-       float i, j;
+       int i, j;
 
        if(strMessage == "" && new_id == 0)
                return;
@@ -4169,7 +4269,7 @@ void centerprint_hud(string strMessage)
 
 void reset_centerprint_messages(void)
 {
-       float i;
+       int i;
        for (i=0; i<CENTERPRINT_MAX_MSGS; ++i)
        {
                centerprint_expire_time[i] = 0;
@@ -4187,24 +4287,32 @@ void HUD_CenterPrint (void)
        {
                if(!autocvar_hud_panel_centerprint) return;
 
-               if (hud_configure_prev && hud_configure_prev != -1)
+               if(hud_configure_prev)
                        reset_centerprint_messages();
        }
        else
        {
-               if (!hud_configure_prev)
+               if(!hud_configure_prev)
                        reset_centerprint_messages();
                if (time > hud_configure_cp_generation_time)
                {
-                       float r;
-                       r = random();
-                       if (r > 0.75)
-                               centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: ^COUNT"), 1, 10);
-                       else if (r > 0.5)
-                               centerprint_generic(0, sprintf("^1Multiline message at time %s that\n^1lasts longer than normal", seconds_tostring(time)), 20, 0);
+                       if(HUD_PANEL(CENTERPRINT) == highlightedPanel)
+                       {
+                               float r;
+                               r = random();
+                               if (r > 0.8)
+                                       centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: ^COUNT"), 1, 10);
+                               else if (r > 0.55)
+                                       centerprint_generic(0, sprintf("^1Multiline message at time %s that\n^1lasts longer than normal", seconds_tostring(time)), 20, 0);
+                               else
+                                       centerprint_hud(sprintf("Message at time %s", seconds_tostring(time)));
+                               hud_configure_cp_generation_time = time + 1 + random()*4;
+                       }
                        else
-                               centerprint_hud(sprintf("Message at time %s", seconds_tostring(time)));
-                       hud_configure_cp_generation_time = time + 1 + random()*4;
+                       {
+                               centerprint_generic(0, sprintf("Centerprint message", seconds_tostring(time)), 10, 0);
+                               hud_configure_cp_generation_time = time + 10 - random()*3;
+                       }
                }
        }
 
@@ -4231,7 +4339,7 @@ void HUD_CenterPrint (void)
                if(target_pos.y > panel_pos.y)
                {
                        panel_pos = panel_pos + (target_pos - panel_pos) * sqrt(scoreboard_fade_alpha);
-                       panel_size_y = min(panel_size.y, vid_conheight - scoreboard_bottom);
+                       panel_size.y = min(panel_size.y, vid_conheight - scoreboard_bottom);
                }
        }
 
@@ -4246,7 +4354,8 @@ void HUD_CenterPrint (void)
                panel_size -= '2 2 0' * panel_bg_padding;
        }
 
-       float entries, height;
+       int entries;
+       float 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;
@@ -4255,11 +4364,11 @@ void HUD_CenterPrint (void)
        fontsize = '1 1 0' * height;
        entries = bound(1, floor(panel_size.y/height), CENTERPRINT_MAX_ENTRIES);
 
-       float i, j, k, n, g;
+       int i, j, k, n, g;
        float a, sz, align, current_msg_posY = 0, msg_size;
        vector pos;
        string ts;
-       float all_messages_expired = true;
+       bool all_messages_expired = true;
 
        pos = panel_pos;
        if (autocvar_hud_panel_centerprint_flip)
@@ -4346,7 +4455,7 @@ void HUD_CenterPrint (void)
                                if (ts != "")
                                {
                                        if (align)
-                                               pos_x = panel_pos.x + (panel_size.x - stringwidth(ts, true, fontsize)) * align;
+                                               pos.x = panel_pos.x + (panel_size.x - stringwidth(ts, true, fontsize)) * align;
                                        if (a > 0.5/255.0)  // Otherwise guaranteed invisible - don't show. This is checked a second time after some multiplications with other factors were done so temporary changes of these cannot cause flicker.
                                                drawcolorcodedstring(pos + eY * 0.5 * (1 - sz) * fontsize.y, ts, fontsize, a, DRAWFLAG_NORMAL);
                                        pos.y += fontsize.y;
@@ -4361,7 +4470,7 @@ void HUD_CenterPrint (void)
                msg_size = pos.y - msg_size;
                if (autocvar_hud_panel_centerprint_flip)
                {
-                       pos_y = current_msg_posY - CENTERPRINT_SPACING * fontsize.y;
+                       pos.y = current_msg_posY - CENTERPRINT_SPACING * fontsize.y;
                        if (a < 1 && centerprint_msgID[j] == 0) // messages with id can be replaced just after they are faded out, so never move over them the next messages
                                pos.y += (msg_size + CENTERPRINT_SPACING * fontsize.y) * (1 - sqrt(sz));
 
@@ -4396,7 +4505,7 @@ void HUD_CenterPrint (void)
 //
 void HUD_Buffs(void)
 {
-       float buffs = getstati(STAT_BUFFS, 0, 24);
+       int buffs = getstati(STAT_BUFFS, 0, 24);
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_buffs) return;
@@ -4408,8 +4517,8 @@ void HUD_Buffs(void)
        {
                buffs = Buff_Type_first.items; // force first buff
        }
-       
-       float b = 0; // counter to tell other functions that we have buffs
+
+       int b = 0; // counter to tell other functions that we have buffs
        entity e;
        string s = "";
        for(e = Buff_Type_first; e; e = e.enemy) if(buffs & e.items)
@@ -4438,10 +4547,10 @@ void HUD_Buffs(void)
        }
 
        //float panel_ar = mySize_x/mySize_y;
-       //float is_vertical = (panel_ar < 1);
+       //bool is_vertical = (panel_ar < 1);
        //float buff_iconalign = autocvar_hud_panel_buffs_iconalign;
        vector buff_offset = '0 0 0';
-       
+
        for(e = Buff_Type_first; e; e = e.enemy) if(buffs & e.items)
        {
                //DrawNumIcon(pos + buff_offset, mySize, shield, "shield", is_vertical, buff_iconalign, '1 1 1', 1);
@@ -4509,7 +4618,7 @@ void HUD_Main (void)
        // draw the dock
        if(autocvar_hud_dock != "" && autocvar_hud_dock != "0")
        {
-               float f;
+               int f;
                vector color;
                float hud_dock_color_team = autocvar_hud_dock_color_team;
                if((teamplay) && hud_dock_color_team) {
@@ -4552,13 +4661,14 @@ void HUD_Main (void)
                for(i = 0; i < HUD_PANEL_NUM; ++i)
                        panel_order[i] = -1;
                string s = "";
-               float p_num, warning = false;
-               float argc = tokenize_console(autocvar__hud_panelorder);
+               int p_num;
+               bool warning = false;
+               int argc = tokenize_console(autocvar__hud_panelorder);
                if (argc > HUD_PANEL_NUM)
                        warning = true;
                //first detect wrong/missing panel numbers
                for(i = 0; i < HUD_PANEL_NUM; ++i) {
-                       p_num = stof(argv(i));
+                       p_num = stoi(argv(i));
                        if (p_num >= 0 && p_num < HUD_PANEL_NUM) { //correct panel number?
                                if (panel_order[p_num] == -1) //found for the first time?
                                        s = strcat(s, ftos(p_num), " ");