]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/hud.qc
Merge branch 'master' into terencehill/hud_cleanups
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud.qc
index 4146412280d173781f542e24662c3b6b18d66232..5ead970345f2b10a4d7152c1a86c822263cd9c6f 100644 (file)
@@ -1,29 +1,20 @@
 #include "hud.qh"
-#include "_all.qh"
 
 #include "hud_config.qh"
 #include "mapvoting.qh"
 #include "scoreboard.qh"
-#include "sortlist.qh"
 #include "teamradar.qh"
 #include "t_items.qh"
-
-#include "../dpdefs/keycodes.qh"
-
-#include "../common/buffs.qh"
-#include "../common/constants.qh"
-#include "../common/counting.qh"
-#include "../common/deathtypes.qh"
+#include "../common/buffs/all.qh"
+#include "../common/deathtypes/all.qh"
+#include "../common/items/all.qc"
 #include "../common/mapinfo.qh"
-#include "../common/nades.qh"
-
-#include "../server/mutators/gamemode_ctf.qh"
-
+#include "../common/mutators/mutator/waypoints/all.qh"
+#include "../common/nades/all.qh"
 #include "../common/stats.qh"
+#include "../lib/csqcmodel/cl_player.qh"
+#include "../server/mutators/gamemode_ctf.qh"
 
-#include "../csqcmodellib/cl_player.qh"
-
-#include "../warpzonelib/mathlib.qh"
 
 /*
 ==================
@@ -31,89 +22,6 @@ Misc HUD functions
 ==================
 */
 
-// a border picture is a texture containing nine parts:
-//   1/4 width: left part
-//   1/2 width: middle part (stretched)
-//   1/4 width: right part
-// divided into
-//   1/4 height: top part
-//   1/2 height: middle part (stretched)
-//   1/4 height: bottom part
-void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize)
-{
-    if (theBorderSize.x < 0 && theBorderSize.y < 0) // draw whole image as it is
-    {
-               drawpic(theOrigin, pic, theSize, theColor, theAlpha, 0);
-               return;
-    }
-       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);
-               return;
-       }
-
-       vector dX, dY;
-       vector width, height;
-       vector bW, bH;
-       //pic = draw_UseSkinFor(pic);
-       width = eX * theSize.x;
-       height = eY * theSize.y;
-       if(theSize.x <= theBorderSize.x * 2)
-       {
-               // not wide enough... draw just left and right then
-               bW = eX * (0.25 * theSize.x / (theBorderSize.x * 2));
-               if(theSize.y <= theBorderSize.y * 2)
-               {
-                       // not high enough... draw just corners
-                       bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
-                       drawsubpic(theOrigin,                 width * 0.5 + height * 0.5, pic, '0 0 0',           bW + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width   * 0.5, width * 0.5 + height * 0.5, pic, eX - bW,           bW + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + height  * 0.5, width * 0.5 + height * 0.5, pic, eY - bH,           bW + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + theSize * 0.5, width * 0.5 + height * 0.5, pic, eX + eY - bW - bH, bW + bH, theColor, theAlpha, 0);
-               }
-               else
-               {
-                       dY = theBorderSize.x * eY;
-                       drawsubpic(theOrigin,                             width * 0.5          +     dY, pic, '0 0    0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width * 0.5,               width * 0.5          +     dY, pic, '0 0    0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin                        + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0',           '0 0.5  0' + bW, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width * 0.5          + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0' + eX - bW, '0 0.5  0' + bW, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin               + height - dY, width * 0.5          +     dY, pic, '0 0.75 0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width * 0.5 + height - dY, width * 0.5          +     dY, pic, '0 0.75 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
-               }
-       }
-       else
-       {
-               if(theSize.y <= theBorderSize.y * 2)
-               {
-                       // not high enough... draw just top and bottom then
-                       bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
-                       dX = theBorderSize.x * eX;
-                       drawsubpic(theOrigin,                                         dX + height * 0.5, pic, '0    0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + dX,                        width - 2 * dX + height * 0.5, pic, '0.25 0 0',           '0.5  0 0' + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width - dX,                            dX + height * 0.5, pic, '0.75 0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin              + height * 0.5,             dX + height * 0.5, pic, '0    0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + dX         + height * 0.5, width - 2 * dX + height * 0.5, pic, '0.25 0 0' + eY - bH, '0.5  0 0' + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width - dX + height * 0.5,             dX + height * 0.5, pic, '0.75 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
-               }
-               else
-               {
-                       dX = theBorderSize.x * eX;
-                       dY = theBorderSize.x * eY;
-                       drawsubpic(theOrigin,                                        dX          +     dY, pic, '0    0    0', '0.25 0.25 0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin                  + dX,      width - 2 * dX          +     dY, pic, '0.25 0    0', '0.5  0.25 0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin          + width - dX,                  dX          +     dY, pic, '0.75 0    0', '0.25 0.25 0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin          + dY,                          dX + height - 2 * dY, pic, '0    0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin          + dY         + dX, width - 2 * dX + height - 2 * dY, pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin          + dY + width - dX,             dX + height - 2 * dY, pic, '0.75 0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + height - dY,                          dX          +     dY, pic, '0    0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + height - dY         + dX, width - 2 * dX          +     dY, pic, '0.25 0.75 0', '0.5  0.25 0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + height - dY + width - dX,             dX          +     dY, pic, '0.75 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
-               }
-       }
-}
-
 vector HUD_Get_Num_Color (float x, float maxvalue)
 {
        float blinkingamt;
@@ -205,28 +113,6 @@ vector HUD_GetTableSize_BestItemAR(int item_count, vector psize, float item_aspe
                return eX * best_columns + eY * best_rows;
 }
 
-float stringwidth_colors(string s, vector theSize)
-{
-       return stringwidth(s, true, theSize);
-}
-
-float stringwidth_nocolors(string s, vector theSize)
-{
-       return stringwidth(s, false, theSize);
-}
-
-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, int flag)
-{
-       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(int cp, float mytime, float theirtime, float lapdelta, string theirname)
 {
@@ -306,42 +192,12 @@ int race_CheckName(string net_name)
        return 0;
 }
 
-int GetPlayerColorForce(int i)
-{
-       if(!teamplay)
-               return 0;
-       else
-               return stof(getplayerkeyvalue(i, "colors")) & 15;
-}
-
-int GetPlayerColor(int i)
-{
-       if(!playerslots[i].gotscores) // unconnected
-               return NUM_SPECTATOR;
-       else if(stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR)
-               return NUM_SPECTATOR;
-       else
-               return GetPlayerColorForce(i);
-}
-
-string GetPlayerName(int i)
-{
-       return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
-}
-
-
 /*
 ==================
 HUD panels
 ==================
 */
 
-// draw the background/borders
-#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, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag)
 {
@@ -465,7 +321,7 @@ void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theA
 
 // Weapon icons (#0)
 //
-entity weaponorder[WEP_MAXCOUNT];
+entity weaponorder[Weapons_MAX];
 void weaponorder_swap(int i, int j, entity pass)
 {
        entity h = weaponorder[i];
@@ -483,7 +339,7 @@ int weaponorder_cmp(int i, int j, entity pass)
 }
 
 void HUD_Weapons(void)
-{
+{SELFPARAM();
        // declarations
        WepSet weapons_stat = WepSet_GetFromStat();
        int i;
@@ -510,7 +366,6 @@ void HUD_Weapons(void)
        vector color;
 
        // check to see if we want to continue
-       if(intermission == 2) return;
        if(hud != HUD_NORMAL) return;
 
        if(!autocvar__hud_configure)
@@ -544,14 +399,14 @@ void HUD_Weapons(void)
                weapon_cnt = 0;
                for(i = WEP_FIRST; i <= WEP_LAST; ++i)
                {
-                       self = get_weaponinfo(i);
+                       setself(get_weaponinfo(i));
                        if(self.impulse >= 0)
                        {
                                weaponorder[weapon_cnt] = self;
                                ++weapon_cnt;
                        }
                }
-               for(i = weapon_cnt; i < WEP_MAXCOUNT; ++i)
+               for(i = weapon_cnt; i < Weapons_MAX; ++i)
                        weaponorder[i] = world;
                heapsort(weapon_cnt, weaponorder_swap, weaponorder_cmp, world);
 
@@ -572,7 +427,7 @@ void HUD_Weapons(void)
                if(cvar("wep_add"))
                {
                        weapons_stat = '0 0 0';
-                       float countw = 1 + floor((floor(time * cvar("wep_add"))) % WEP_COUNT);
+                       float countw = 1 + floor((floor(time * cvar("wep_add"))) % (Weapons_COUNT - 1));
                        for(i = WEP_FIRST; i <= countw; ++i)
                                weapons_stat |= WepSet_FromWeapon(i);
                }
@@ -603,7 +458,15 @@ void HUD_Weapons(void)
                vector padded_panel_size = panel_size - '2 2 0' * panel_bg_padding;
 
                // get the all-weapons layout
-               vector table_size = HUD_GetTableSize_BestItemAR(WEP_COUNT, padded_panel_size, aspect);
+               int nHidden = 0;
+               WepSet weapons_stat = WepSet_GetFromStat();
+               for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
+                       WepSet weapons_wep = WepSet_FromWeapon(i);
+                       if (weapons_stat & weapons_wep) continue;
+                       Weapon w = get_weaponinfo(i);
+                       if (w.spawnflags & WEP_FLAG_MUTATORBLOCKED) nHidden += 1;
+               }
+               vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1) - nHidden, padded_panel_size, aspect);
                columns = table_size.x;
                rows = table_size.y;
                weapon_size.x = padded_panel_size.x / columns;
@@ -658,7 +521,7 @@ void HUD_Weapons(void)
                        panel_pos.y += (old_panel_size.y - panel_size.y) / 2;
        }
        else
-               weapon_count = WEP_COUNT;
+               weapon_count = (Weapons_COUNT - 1);
 
        // animation for fading in/out the panel respectively when not in use
        if(!autocvar__hud_configure)
@@ -763,7 +626,7 @@ void HUD_Weapons(void)
 
        if(!rows) // if rows is > 0 onlyowned code has already updated these vars
        {
-               vector table_size = HUD_GetTableSize_BestItemAR(WEP_COUNT, panel_size, aspect);
+               vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1), panel_size, aspect);
                columns = table_size.x;
                rows = table_size.y;
                weapon_size.x = panel_size.x / columns;
@@ -804,7 +667,7 @@ void HUD_Weapons(void)
        for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
        {
                // retrieve information about the current weapon to be drawn
-               self = weaponorder[i];
+               setself(weaponorder[i]);
                weapon_id = self.impulse;
                isCurrent = (self.weapon == switchweapon);
 
@@ -981,8 +844,8 @@ void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expan
        float bonusNades    = getstatf(STAT_NADE_BONUS);
        float bonusProgress = getstatf(STAT_NADE_BONUS_SCORE);
        float bonusType     = getstati(STAT_NADE_BONUS_TYPE);
-       vector nadeColor    = NADES[bonusType].m_color;
-       string nadeIcon     = NADES[bonusType].m_icon;
+       vector nadeColor    = Nades[bonusType].m_color;
+       string nadeIcon     = Nades[bonusType].m_icon;
 
        vector iconPos, textPos;
 
@@ -1088,7 +951,6 @@ int nade_prevframe;
 float nade_statuschange_time;
 void HUD_Ammo(void)
 {
-       if(intermission == 2) return;
        if(hud != HUD_NORMAL) return;
        if(!autocvar__hud_configure)
        {
@@ -1361,10 +1223,8 @@ int getPowerupItemAlign(int align, int column, int row, int columns, int rows, b
        return 2;
 }
 
-void HUD_Powerups(void)
+void HUD_Powerups()
 {
-       if(intermission == 2) return;
-
        int allItems = getstati(STAT_ITEMS, 0, 24);
        int allBuffs = getstati(STAT_BUFFS, 0, 24);
        int strengthTime, shieldTime, superTime;
@@ -1375,7 +1235,7 @@ void HUD_Powerups(void)
                if(!autocvar_hud_panel_powerups) return;
                if(spectatee_status == -1) return;
                if(getstati(STAT_HEALTH) <= 0) return;
-               if(!(allItems & (IT_STRENGTH | IT_INVINCIBLE | IT_SUPERWEAPON)) && !allBuffs) return;
+               if(!(allItems & (ITEM_Strength.m_itemid | ITEM_Shield.m_itemid | IT_SUPERWEAPON)) && !allBuffs) return;
 
                strengthTime = bound(0, getstatf(STAT_STRENGTH_FINISHED) - time, 99);
                shieldTime = bound(0, getstatf(STAT_INVINCIBLE_FINISHED) - time, 99);
@@ -1406,7 +1266,7 @@ void HUD_Powerups(void)
        if(superTime)
                addPowerupItem("Superweapons", "superweapons", autocvar_hud_progressbar_superweapons_color, superTime, 30);
 
-       FOREACH(BUFFS, it.m_itemid & allBuffs, LAMBDA(
+       FOREACH(Buffs, it.m_itemid & allBuffs, LAMBDA(
                addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, getstatf(STAT_BUFF_TIME) - time, 99), 60);
        ));
 
@@ -1528,7 +1388,6 @@ void HUD_Powerups(void)
 void HUD_HealthArmor(void)
 {
        int armor, health, fuel;
-       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_healtharmor) return;
@@ -1600,7 +1459,7 @@ void HUD_HealthArmor(void)
        if(autocvar_hud_panel_healtharmor == 2) // combined health and armor display
        {
                vector v;
-               v = healtharmor_maxdamage(health, armor, armorblockpercent, DEATH_WEAPON);
+               v = healtharmor_maxdamage(health, armor, armorblockpercent, DEATH_WEAPON.m_id);
 
                float x;
                x = floor(v.x + 1);
@@ -1835,7 +1694,6 @@ void HUD_Notify_Push(string icon, string attacker, string victim)
 
 void HUD_Notify(void)
 {
-       if(intermission == 2) return;
        if (!autocvar__hud_configure)
                if (!autocvar_hud_panel_notify)
                        return;
@@ -1947,21 +1805,8 @@ void HUD_Notify(void)
        notify_count = count;
 }
 
-// Timer (#5)
-//
-// TODO: macro
-string seconds_tostring(float sec)
-{
-       float minutes;
-       minutes = floor(sec / 60);
-
-       sec -= minutes * 60;
-       return sprintf("%d:%02d", minutes, sec);
-}
-
 void HUD_Timer(void)
 {
-       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_timer) return;
@@ -2029,14 +1874,14 @@ void HUD_Radar_Show_Maximized(bool doshow,float clickable)
 {
        hud_panel_radar_maximized = doshow;
        hud_panel_radar_temp_hidden = 0;
-       
+
        if ( doshow )
        {
                if (clickable)
                {
                        if(autocvar_hud_cursormode)
                                setcursormode(1);
-                       hud_panel_radar_mouse = 1; 
+                       hud_panel_radar_mouse = 1;
                }
        }
        else if ( hud_panel_radar_mouse )
@@ -2056,7 +1901,7 @@ void HUD_Radar_Hide_Maximized()
 
 float HUD_Radar_InputEvent(float bInputType, float nPrimary, float nSecondary)
 {
-       if(!hud_panel_radar_maximized || !hud_panel_radar_mouse || 
+       if(!hud_panel_radar_maximized || !hud_panel_radar_mouse ||
                autocvar__hud_configure || mv_active)
                return false;
 
@@ -2098,7 +1943,7 @@ float HUD_Radar_InputEvent(float bInputType, float nPrimary, float nSecondary)
                        if(nPrimary == stof(argv(i)))
                                return false;
                }
-               
+
                if ( getstati(STAT_HEALTH) <= 0 )
                {
                        // Show scoreboard
@@ -2118,7 +1963,7 @@ float HUD_Radar_InputEvent(float bInputType, float nPrimary, float nSecondary)
                }
                else if ( bInputType == 0 )
                        HUD_Radar_Hide_Maximized();
-               
+
                return false;
        }
 
@@ -2129,19 +1974,19 @@ void HUD_Radar_Mouse()
 {
        if ( !hud_panel_radar_mouse ) return;
        if(mv_active) return;
-       
+
        if ( intermission )
        {
                HUD_Radar_Hide_Maximized();
                return;
        }
-       
+
        if(mouseClicked & S_MOUSE2)
        {
                HUD_Radar_Hide_Maximized();
                return;
        }
-       
+
        if(!autocvar_hud_cursormode)
        {
                mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed;
@@ -2151,14 +1996,14 @@ void HUD_Radar_Mouse()
        }
 
        HUD_Panel_UpdateCvars();
-       
-       
+
+
        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;
-               
+
        if(mouseClicked & S_MOUSE1)
        {
                // click outside
@@ -2170,11 +2015,11 @@ void HUD_Radar_Mouse()
                }
                vector pos = teamradar_texcoord_to_3dcoord(teamradar_2dcoord_to_texcoord(mousepos),view_origin_z);
                localcmd(sprintf("cmd ons_spawn %f %f %f",pos_x,pos_y,pos_z));
-               
+
                HUD_Radar_Hide_Maximized();
                return;
        }
-       
+
 
        const vector cursor_size = '32 32 0';
        drawpic(mousepos-'8 4 0', strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), cursor_size, '1 1 1', 0.8, DRAWFLAG_NORMAL);
@@ -2182,7 +2027,6 @@ void HUD_Radar_Mouse()
 
 void HUD_Radar(void)
 {
-       if(intermission == 2) return;
        if (!autocvar__hud_configure)
        {
                if (hud_panel_radar_maximized)
@@ -2375,8 +2219,8 @@ void HUD_Radar(void)
                                drawpic(coord - '8 8 0', "gfx/teamradar_icon_glow", '16 16 0', brightcolor, panel_fg_alpha, 0);
                        }
                }
-
-               draw_teamradar_icon(tm.origin, tm.teamradar_icon, tm, tm.teamradar_color, panel_fg_alpha);
+               entity icon = RadarIcons[tm.teamradar_icon];
+               draw_teamradar_icon(tm.origin, icon, tm, spritelookupcolor(tm, icon.netname, tm.teamradar_color), panel_fg_alpha);
        }
        for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
        {
@@ -2389,7 +2233,7 @@ void HUD_Radar(void)
        drawresetcliparea();
 
        if ( hud_panel_radar_mouse )
-       {                       
+       {
                string message = "Click to select teleport destination";
 
                if ( getstati(STAT_HEALTH) <= 0 )
@@ -2531,7 +2375,6 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
 
 void HUD_Score(void)
 {
-       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_score) return;
@@ -2715,7 +2558,6 @@ void HUD_Score(void)
 //
 void HUD_RaceTimer (void)
 {
-       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_racetimer) return;
@@ -2866,7 +2708,6 @@ void HUD_RaceTimer (void)
 
 void HUD_Vote(void)
 {
-       if(intermission == 2) return;
        if(autocvar_cl_allow_uid2name == -1 && (gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE || (serverflags & SERVERFLAG_PLAYERSTATS)))
        {
                vote_active = 1;
@@ -2874,7 +2715,7 @@ void HUD_Vote(void)
                {
                        vote_yescount = 0;
                        vote_nocount = 0;
-                       print(_("^1You must answer before entering hud configure mode\n"));
+                       LOG_INFO(_("^1You must answer before entering hud configure mode\n"));
                        cvar_set("_hud_configure", "0");
                }
                if(vote_called_vote)
@@ -3743,7 +3584,6 @@ float mod_change; // "time" when mod_active changed
 
 void HUD_ModIcons(void)
 {
-       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_modicons) return;
@@ -3785,7 +3625,6 @@ void HUD_ModIcons(void)
 //
 void HUD_PressedKeys(void)
 {
-       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_pressedkeys) return;
@@ -3949,7 +3788,6 @@ float frametimeavg1; // 1 frame ago
 float frametimeavg2; // 2 frames ago
 void HUD_EngineInfo(void)
 {
-       //if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_engineinfo) return;
@@ -4011,7 +3849,6 @@ void HUD_EngineInfo(void)
 } while(0)
 void HUD_InfoMessages(void)
 {
-       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_infomessages) return;
@@ -4193,7 +4030,6 @@ float acc_prevtime, acc_avg, top_speed, top_speed_time;
 float physics_update_time, discrete_speed, discrete_acceleration;
 void HUD_Physics(void)
 {
-       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_physics) return;
@@ -4585,7 +4421,6 @@ void reset_centerprint_messages(void)
 float hud_configure_cp_generation_time;
 void HUD_CenterPrint (void)
 {
-       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_centerprint) return;
@@ -4599,7 +4434,7 @@ void HUD_CenterPrint (void)
                        reset_centerprint_messages();
                if (time > hud_configure_cp_generation_time)
                {
-                       if(HUD_PANEL(CENTERPRINT) == highlightedPanel)
+                       if(highlightedPanel == HUD_PANEL(CENTERPRINT))
                        {
                                float r;
                                r = random();
@@ -4812,266 +4647,65 @@ void HUD_CenterPrint (void)
        }
 }
 
-// ItemsTime (#XX)
+
+// Minigame
 //
-const float ITEMSTIME_MAXITEMS = 10;
-float ItemsTime_time[ITEMSTIME_MAXITEMS];
-float ItemsTime_availableTime[ITEMSTIME_MAXITEMS];
-string GetItemsTimePicture(float i)
-{
-       switch(i)
-       {
-               case 0: return "item_large_armor";
-               case 1: return "item_mega_health";
-               case 2: return "strength";
-               case 3: return "shield";
-               case 4: return "item_mega_health";
-               case 5: return "strength";
-               case 6: return "shield";
-               case 7: return "fuelregen";
-               case 8: return "jetpack";
-               case 9: return "superweapons";
-               default: return "";
-       }
-}
+#include "../common/minigames/cl_minigames_hud.qc"
 
-void DrawItemsTimeItem(vector myPos, vector mySize, float ar, float itemcode, float item_time, bool item_available, float item_availableTime)
-{
-       float t = 0;
-       vector color = '0 0 0';
-       float picalpha;
 
-       if(autocvar_hud_panel_itemstime_hidespawned == 2)
-               picalpha = 1;
-       else if(item_available)
-       {
-               float BLINK_FACTOR = 0.15;
-               float BLINK_BASE = 0.85;
-               float BLINK_FREQ = 5;
-               picalpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
-       }
-       else
-               picalpha = 0.5;
-       t = floor(item_time - time + 0.999);
-       if(t < 5)
-               color = '0.7 0 0';
-       else if(t < 10)
-               color = '0.7 0.7 0';
-       else
-               color = '1 1 1';
-
-       vector picpos, numpos;
-       if(autocvar_hud_panel_itemstime_iconalign)
-       {
-               numpos = myPos;
-               picpos = myPos + eX * (ar - 1) * mySize_y;
-       }
-       else
-       {
-               numpos = myPos + eX * mySize_y;
-               picpos = myPos;
-       }
+// QuickMenu (#23)
+//
+#include "quickmenu.qc"
 
-       if(t > 0 && autocvar_hud_panel_itemstime_progressbar)
-       {
-               vector p_pos, p_size;
-               if(autocvar_hud_panel_itemstime_progressbar_reduced)
-               {
-                       p_pos = numpos;
-                       p_size = eX * ((ar - 1)/ar) * mySize_x + eY * mySize_y;
-               }
-               else
-               {
-                       p_pos = myPos;
-                       p_size = mySize;
-               }
-               HUD_Panel_DrawProgressBar(p_pos, p_size, autocvar_hud_panel_itemstime_progressbar_name, t/autocvar_hud_panel_itemstime_progressbar_maxtime, 0, autocvar_hud_panel_itemstime_iconalign, color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
-       }
 
-       if(t > 0 && autocvar_hud_panel_itemstime_text)
-               drawstring_aspect(numpos, ftos(t), eX * ((ar - 1)/ar) * mySize_x + eY * mySize_y, color, panel_fg_alpha, DRAWFLAG_NORMAL);
-       else
-               picpos.x = myPos.x + mySize.x / 2 - mySize.y / 2;
-       if(item_availableTime)
-               drawpic_aspect_skin_expanding(picpos, GetItemsTimePicture(itemcode), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL, item_availableTime);
-       drawpic_aspect_skin(picpos, GetItemsTimePicture(itemcode), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL);
-}
+/*
+==================
+Main HUD system
+==================
+*/
 
-void HUD_ItemsTime(void)
+void HUD_Vehicle()
 {
-       if(!autocvar__hud_configure)
-       {
-               if(!(
-                       (autocvar_hud_panel_itemstime == 1 && spectatee_status != 0)
-               ||      (autocvar_hud_panel_itemstime == 2 && (spectatee_status != 0 || warmup_stage))
-                       )) { return; }
-
-               ItemsTime_time[0] = getstatf(STAT_ARMOR_LARGE_TIME);
-               ItemsTime_time[1] = getstatf(STAT_HEALTH_MEGA_TIME);
-               ItemsTime_time[2] = getstatf(STAT_INVISIBLE_TIME);
-               ItemsTime_time[3] = getstatf(STAT_SPEED_TIME);
-               ItemsTime_time[4] = getstatf(STAT_EXTRALIFE_TIME);
-               ItemsTime_time[5] = getstatf(STAT_STRENGTH_TIME);
-               ItemsTime_time[6] = getstatf(STAT_SHIELD_TIME);
-               ItemsTime_time[7] = getstatf(STAT_FUELREGEN_TIME);
-               ItemsTime_time[8] = getstatf(STAT_JETPACK_TIME);
-               ItemsTime_time[9] = getstatf(STAT_SUPERWEAPONS_TIME);
-       }
-       else
-       {
-               // do not show here mutator-dependent items
-               ItemsTime_time[0] = time + 0;
-               ItemsTime_time[1] = time + 8;
-               ItemsTime_time[2] = -1; // mutator-dependent
-               ItemsTime_time[3] = -1; // mutator-dependent
-               ItemsTime_time[4] = -1; // mutator-dependent
-               ItemsTime_time[5] = time + 0;
-               ItemsTime_time[6] = time + 4;
-               ItemsTime_time[7] = time + 49;
-               ItemsTime_time[8] = -1;
-               ItemsTime_time[9] = time + 28;
-       }
-
-       float i;
-       float count = 0;
-       if(autocvar_hud_panel_itemstime_hidespawned == 1)
-               for (i = 0; i < ITEMSTIME_MAXITEMS; ++i)
-                       count += (ItemsTime_time[i] > time || -ItemsTime_time[i] > time);
-       else if(autocvar_hud_panel_itemstime_hidespawned == 2)
-               for (i = 0; i < ITEMSTIME_MAXITEMS; ++i)
-                       count += (ItemsTime_time[i] > time);
-       else
-               for (i = 0; i < ITEMSTIME_MAXITEMS; ++i)
-                       count += (ItemsTime_time[i] != -1);
-       if (count == 0)
-               return;
-
-       HUD_Panel_UpdateCvars();
-
-       vector pos, mySize;
-       pos = panel_pos;
-       mySize = panel_size;
+       if(autocvar__hud_configure) return;
+       if(intermission == 2) return;
 
-       if(panel_bg_padding)
-       {
-               pos += '1 1 0' * panel_bg_padding;
-               mySize -= '2 2 0' * panel_bg_padding;
+       if(hud == HUD_BUMBLEBEE_GUN)
+               CSQC_BUMBLE_GUN_HUD();
+       else {
+               Vehicle info = get_vehicleinfo(hud);
+               info.vr_hud(info);
        }
+}
 
-       float rows, columns;
-       float ar = max(2, autocvar_hud_panel_itemstime_ratio) + 1;
-       rows = HUD_GetRowCount(count, mySize, ar);
-       columns = ceil(count/rows);
-
-       vector itemstime_size = eX * mySize.x*(1/columns) + eY * mySize.y*(1/rows);
-
-       vector offset = '0 0 0';
-       float newSize;
-       if(autocvar_hud_panel_itemstime_dynamicsize)
-       {
-               if(autocvar__hud_configure)
-               if(menu_enabled != 2)
-                       HUD_Panel_DrawBg(1); // also draw the bg of the entire panel
+bool HUD_Panel_CheckFlags(int showflags)
+{
+       if ( HUD_Minigame_Showpanels() )
+               return showflags & PANEL_SHOW_MINIGAME;
+       if(intermission == 2)
+               return showflags & PANEL_SHOW_MAPVOTE;
+       return showflags & PANEL_SHOW_MAINGAME;
+}
 
-               // reduce panel to avoid spacing items
-               if(itemstime_size.x / itemstime_size.y < ar)
-               {
-                       newSize = rows * itemstime_size.x / ar;
-                       pos.y += (mySize.y - newSize) / 2;
-                       mySize.y = newSize;
-                       itemstime_size.y = mySize.y / rows;
-               }
-               else
-               {
-                       newSize = columns * itemstime_size.y * ar;
-                       pos.x += (mySize.x - newSize) / 2;
-                       mySize.x = newSize;
-                       itemstime_size.x = mySize.x / columns;
-               }
-               panel_pos = pos - '1 1 0' * panel_bg_padding;
-               panel_size = mySize + '2 2 0' * panel_bg_padding;
-       }
-       else
+void HUD_Panel_Draw(entity panent)
+{
+       panel = panent;
+       if(autocvar__hud_configure)
        {
-               if(itemstime_size.x/itemstime_size.y > ar)
-               {
-                       newSize = ar * itemstime_size.y;
-                       offset.x = itemstime_size.x - newSize;
-                       pos.x += offset.x/2;
-                       itemstime_size.x = newSize;
-               }
-               else
-               {
-                       newSize = 1/ar * itemstime_size.x;
-                       offset.y = itemstime_size.y - newSize;
-                       pos.y += offset.y/2;
-                       itemstime_size.y = newSize;
-               }
-       }
-
-       HUD_Panel_DrawBg(1);
-
-       float row = 0, column = 0;
-       bool item_available;
-       for (i = 0; i < ITEMSTIME_MAXITEMS; ++i) {
-               if (ItemsTime_time[i] == -1)
-                       continue;
-
-               float item_time = ItemsTime_time[i];
-               if(item_time < -1)
-               {
-                       item_available = true;
-                       item_time = -item_time;
-               }
-               else
-                       item_available = (item_time <= time);
-
-               if(ItemsTime_time[i] >= 0)
-               {
-                       if(time <= ItemsTime_time[i])
-                               ItemsTime_availableTime[i] = 0;
-                       else if(ItemsTime_availableTime[i] == 0)
-                               ItemsTime_availableTime[i] = time;
-               }
-               else if(ItemsTime_availableTime[i] == 0)
-                       ItemsTime_availableTime[i] = time;
-
-               float f = (time - ItemsTime_availableTime[i]) * 2;
-               f = (f > 1) ? 0 : bound(0, f, 1);
-
-               if(autocvar_hud_panel_itemstime_hidespawned == 1)
-                       if(!(ItemsTime_time[i] > time || -ItemsTime_time[i] > time))
-                               continue;
-
-               if(autocvar_hud_panel_itemstime_hidespawned == 2)
-                       if(!(ItemsTime_time[i] > time))
-                               continue;
-
-               DrawItemsTimeItem(pos + eX * column * (itemstime_size.x + offset.x) + eY * row * (itemstime_size.y + offset.y), itemstime_size, ar, i, item_time, item_available, f);
-               ++row;
-               if(row >= rows)
-               {
-                       row = 0;
-                       column = column + 1;
-               }
+               if(panel.panel_configflags & PANEL_CONFIG_MAIN)
+                       panel.panel_draw();
        }
+       else if(HUD_Panel_CheckFlags(panel.panel_showflags))
+               panel.panel_draw();
 }
 
-
-/*
-==================
-Main HUD system
-==================
-*/
-
-void HUD_Reset (void)
+void HUD_Reset(void)
 {
        // reset gametype specific icons
        if(gametype == MAPINFO_TYPE_CTF)
                HUD_Mod_CTF_Reset();
 }
 
-void HUD_Main (void)
+void HUD_Main(void)
 {
        int i;
        // global hud theAlpha fade
@@ -5089,12 +4723,17 @@ void HUD_Main (void)
        // they must fade only when the menu does
        if(scoreboard_fade_alpha == 1)
        {
-               (panel = HUD_PANEL(CENTERPRINT)).panel_draw();
+               HUD_Panel_Draw(HUD_PANEL(CENTERPRINT));
                return;
        }
 
        if(!autocvar__hud_configure && !hud_fade_alpha)
+       {
+               hud_fade_alpha = 1;
+               HUD_Panel_Draw(HUD_PANEL(VOTE));
+               hud_fade_alpha = 0;
                return;
+       }
 
        // Drawing stuff
        if (hud_skin_prev != autocvar_hud_skin)
@@ -5150,18 +4789,18 @@ void HUD_Main (void)
 
        // cache the panel order into the panel_order array
        if(autocvar__hud_panelorder != hud_panelorder_prev) {
-               for(i = 0; i < HUD_PANEL_NUM; ++i)
+               for(i = 0; i < hud_panels_COUNT; ++i)
                        panel_order[i] = -1;
                string s = "";
                int p_num;
                bool warning = false;
                int argc = tokenize_console(autocvar__hud_panelorder);
-               if (argc > HUD_PANEL_NUM)
+               if (argc > hud_panels_COUNT)
                        warning = true;
                //first detect wrong/missing panel numbers
-               for(i = 0; i < HUD_PANEL_NUM; ++i) {
+               for(i = 0; i < hud_panels_COUNT; ++i) {
                        p_num = stoi(argv(i));
-                       if (p_num >= 0 && p_num < HUD_PANEL_NUM) { //correct panel number?
+                       if (p_num >= 0 && p_num < hud_panels_COUNT) { //correct panel number?
                                if (panel_order[p_num] == -1) //found for the first time?
                                        s = strcat(s, ftos(p_num), " ");
                                panel_order[p_num] = 1; //mark as found
@@ -5169,14 +4808,14 @@ void HUD_Main (void)
                        else
                                warning = true;
                }
-               for(i = 0; i < HUD_PANEL_NUM; ++i) {
+               for(i = 0; i < hud_panels_COUNT; ++i) {
                        if (panel_order[i] == -1) {
                                warning = true;
                                s = strcat(s, ftos(i), " "); //add missing panel number
                        }
                }
                if (warning)
-                       dprint("Automatically fixed wrong/missing panel numbers in _hud_panelorder\n");
+                       LOG_TRACE("Automatically fixed wrong/missing panel numbers in _hud_panelorder\n");
 
                cvar_set("_hud_panelorder", s);
                if(hud_panelorder_prev)
@@ -5185,22 +4824,29 @@ void HUD_Main (void)
 
                //now properly set panel_order
                tokenize_console(s);
-               for(i = 0; i < HUD_PANEL_NUM; ++i) {
+               for(i = 0; i < hud_panels_COUNT; ++i) {
                        panel_order[i] = stof(argv(i));
                }
        }
 
        hud_draw_maximized = 0;
        // draw panels in the order specified by panel_order array
-       for(i = HUD_PANEL_NUM - 1; i >= 0; --i)
-               (panel = hud_panel[panel_order[i]]).panel_draw();
+       for(i = hud_panels_COUNT - 1; i >= 0; --i)
+               HUD_Panel_Draw(hud_panels[panel_order[i]]);
+
+       HUD_Vehicle();
 
        hud_draw_maximized = 1; // panels that may be maximized must check this var
        // draw maximized panels on top
        if(hud_panel_radar_maximized)
-               (panel = HUD_PANEL(RADAR)).panel_draw();
+               HUD_Panel_Draw(HUD_PANEL(RADAR));
        if(autocvar__con_chat_maximized)
-               (panel = HUD_PANEL(CHAT)).panel_draw();
+               HUD_Panel_Draw(HUD_PANEL(CHAT));
+       if(hud_panel_quickmenu)
+               HUD_Panel_Draw(HUD_PANEL(QUICKMENU));
+
+       if (scoreboard_active || intermission == 2)
+               HUD_Reset();
 
        HUD_Configure_PostDraw();