]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/hud.qc
Nades: rename registry globals
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud.qc
index 5e7cfb9e3a2ceb38fc32487bf4e3e8cca89c65a6..eb577f46bf02bfba42d26d5f5579ad1c391fe9e3 100644 (file)
@@ -2,17 +2,19 @@
 #include "_all.qh"
 
 #include "hud_config.qh"
+#include "mapvoting.qh"
 #include "scoreboard.qh"
-#include "sortlist.qh"
 #include "teamradar.qh"
 #include "t_items.qh"
 
-#include "../common/buffs.qh"
+#include "../dpdefs/keycodes.qh"
+
+#include "../common/buffs/all.qh"
 #include "../common/constants.qh"
-#include "../common/counting.qh"
 #include "../common/deathtypes.qh"
+#include "../common/items/all.qc"
 #include "../common/mapinfo.qh"
-#include "../common/nades.qh"
+#include "../common/nades/all.qh"
 
 #include "../server/mutators/gamemode_ctf.qh"
 
@@ -20,7 +22,6 @@
 
 #include "../csqcmodellib/cl_player.qh"
 
-#include "../warpzonelib/mathlib.qh"
 
 /*
 ==================
@@ -28,89 +29,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;
@@ -162,7 +80,7 @@ float HUD_GetRowCount(int item_count, vector size, float item_aspect)
        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)
+vector HUD_GetTableSize_BestItemAR(int item_count, vector psize, float item_aspect)
 {
        float columns, rows;
        float ratio, best_ratio = 0;
@@ -202,28 +120,6 @@ vector HUD_GetTableSize(int item_count, vector psize, float item_aspect)
                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)
 {
@@ -303,30 +199,6 @@ 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
@@ -462,7 +334,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];
@@ -480,7 +352,7 @@ int weaponorder_cmp(int i, int j, entity pass)
 }
 
 void HUD_Weapons(void)
-{
+{SELFPARAM();
        // declarations
        WepSet weapons_stat = WepSet_GetFromStat();
        int i;
@@ -507,7 +379,8 @@ void HUD_Weapons(void)
        vector color;
 
        // check to see if we want to continue
-       if(hud != HUD_NORMAL) { return; }
+       if(intermission == 2) return;
+       if(hud != HUD_NORMAL) return;
 
        if(!autocvar__hud_configure)
        {
@@ -540,14 +413,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);
 
@@ -568,7 +441,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);
                }
@@ -599,7 +472,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(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;
@@ -654,7 +535,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)
@@ -759,7 +640,7 @@ void HUD_Weapons(void)
 
        if(!rows) // if rows is > 0 onlyowned code has already updated these vars
        {
-               vector table_size = HUD_GetTableSize(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;
@@ -792,11 +673,17 @@ void HUD_Weapons(void)
        // draw items
        row = column = 0;
        vector label_size = '1 1 0' * min(weapon_size.x, weapon_size.y) * bound(0, autocvar_hud_panel_weapons_label_scale, 1);
+       vector noncurrent_pos = '0 0 0';
+       vector noncurrent_size = weapon_size * bound(0, autocvar_hud_panel_weapons_noncurrent_scale, 1);
+       float noncurrent_alpha = panel_fg_alpha * bound(0, autocvar_hud_panel_weapons_noncurrent_alpha, 1);
+       bool isCurrent;
+
        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);
 
                // skip if this weapon doesn't exist
                if(!self || weapon_id < 0) { continue; }
@@ -807,12 +694,12 @@ void HUD_Weapons(void)
                        continue;
 
                // figure out the drawing position of weapon
-               weapon_pos = (panel_pos
-                       + eX * column * weapon_size.x
-                       + eY * row * weapon_size.y);
+               weapon_pos = (panel_pos + eX * column * weapon_size.x + eY * row * weapon_size.y);
+               noncurrent_pos.x = weapon_pos.x + (weapon_size.x - noncurrent_size.x) / 2;
+               noncurrent_pos.y = weapon_pos.y + (weapon_size.y - noncurrent_size.y) / 2;
 
                // draw background behind currently selected weapon
-               if(self.weapon == switchweapon)
+               if(isCurrent)
                        drawpic_aspect_skin(weapon_pos, "weapon_current_bg", weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 
                // draw the weapon accuracy
@@ -830,7 +717,10 @@ void HUD_Weapons(void)
                if(weapons_stat & WepSet_FromWeapon(self.weapon))
                {
                        // draw the weapon image
-                       drawpic_aspect_skin(weapon_pos, self.model2, weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+                       if(isCurrent)
+                               drawpic_aspect_skin(weapon_pos, self.model2, weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+                       else
+                               drawpic_aspect_skin(noncurrent_pos, self.model2, noncurrent_size, '1 1 1', noncurrent_alpha, DRAWFLAG_NORMAL);
 
                        // draw weapon label string
                        switch(autocvar_hud_panel_weapons_label)
@@ -892,7 +782,7 @@ void HUD_Weapons(void)
                }
                else // draw a "ghost weapon icon" if you don't have the weapon
                {
-                       drawpic_aspect_skin(weapon_pos, self.model2, weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
+                       drawpic_aspect_skin(noncurrent_pos, self.model2, noncurrent_size, '0.2 0.2 0.2', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
                }
 
                // draw the complain message
@@ -968,8 +858,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    = Nade_Color(bonusType);
-       string nadeIcon     = Nade_Icon(bonusType);
+       vector nadeColor    = Nades[bonusType].m_color;
+       string nadeIcon     = Nades[bonusType].m_icon;
 
        vector iconPos, textPos;
 
@@ -1075,6 +965,7 @@ int nade_prevframe;
 float nade_statuschange_time;
 void HUD_Ammo(void)
 {
+       if(intermission == 2) return;
        if(hud != HUD_NORMAL) return;
        if(!autocvar__hud_configure)
        {
@@ -1292,196 +1183,218 @@ void DrawNumIcon(vector myPos, vector mySize, float x, string icon, bool vertica
 
 // Powerups (#2)
 //
-void HUD_Powerups(void)
+
+// Powerup item fields (reusing existing fields)
+.string message;  // Human readable name
+.string netname;  // Icon name
+.vector colormod; // Color
+.float count;     // Time left
+.float lifetime;  // Maximum time
+
+entity powerupItems;
+int powerupItemsCount;
+
+void resetPowerupItems()
 {
-       float strength_time, shield_time, superweapons_time;
+       entity item;
+       for(item = powerupItems; item; item = item.chain)
+               item.count = 0;
+
+       powerupItemsCount = 0;
+}
+
+void addPowerupItem(string name, string icon, vector color, float currentTime, float lifeTime)
+{
+       if(!powerupItems)
+               powerupItems = spawn();
+
+       entity item;
+       for(item = powerupItems; item.count; item = item.chain)
+               if(!item.chain)
+                       item.chain = spawn();
+
+       item.message  = name;
+       item.netname  = icon;
+       item.colormod = color;
+       item.count    = currentTime;
+       item.lifetime = lifeTime;
+
+       ++powerupItemsCount;
+}
+
+int getPowerupItemAlign(int align, int column, int row, int columns, int rows, bool isVertical)
+{
+       if(align < 2)
+               return align;
+
+       bool isTop    =  isVertical && rows > 1 && row == 0;
+       bool isBottom =  isVertical && rows > 1 && row == rows-1;
+       bool isLeft   = !isVertical && columns > 1 && column == 0;
+       bool isRight  = !isVertical && columns > 1 && column == columns-1;
+
+       if(isTop    || isLeft)  return (align == 2) ? 1 : 0;
+       if(isBottom || isRight) return (align == 2) ? 0 : 1;
+
+       return 2;
+}
+
+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;
+
+       // Initialize items
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_powerups) return;
                if(spectatee_status == -1) return;
-               if(!(getstati(STAT_ITEMS, 0, 24) & (IT_STRENGTH | IT_INVINCIBLE | IT_SUPERWEAPON))) return;
-               if (getstati(STAT_HEALTH) <= 0) return;
+               if(getstati(STAT_HEALTH) <= 0) return;
+               if(!(allItems & (ITEM_Strength.m_itemid | ITEM_Shield.m_itemid | IT_SUPERWEAPON)) && !allBuffs) return;
 
-               strength_time = bound(0, getstatf(STAT_STRENGTH_FINISHED) - time, 99);
-               shield_time = bound(0, getstatf(STAT_INVINCIBLE_FINISHED) - time, 99);
-               superweapons_time = bound(0, getstatf(STAT_SUPERWEAPONS_FINISHED) - time, 99);
+               strengthTime = bound(0, getstatf(STAT_STRENGTH_FINISHED) - time, 99);
+               shieldTime = bound(0, getstatf(STAT_INVINCIBLE_FINISHED) - time, 99);
+               superTime = bound(0, getstatf(STAT_SUPERWEAPONS_FINISHED) - time, 99);
 
-               if (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_SUPERWEAPONS)
-                       superweapons_time = 99; // force max
+               if(allItems & IT_UNLIMITED_SUPERWEAPONS)
+                       superTime = 99;
 
-               // prevent stuff to show up on mismatch that will be fixed next frame
-               if (!(getstati(STAT_ITEMS, 0, 24) & IT_SUPERWEAPON))
-                       superweapons_time = 0;
+               // Prevent stuff to show up on mismatch that will be fixed next frame
+               if(!(allItems & IT_SUPERWEAPON))
+                       superTime = 0;
        }
        else
        {
-               strength_time = 15;
-               shield_time = 27;
-               superweapons_time = 13;
+               strengthTime = 15;
+               shieldTime = 27;
+               superTime = 13;
+               allBuffs = 0;
        }
 
-       HUD_Panel_UpdateCvars();
+       // Add items to linked list
+       resetPowerupItems();
 
-       draw_beginBoldFont();
+       if(strengthTime)
+               addPowerupItem("Strength", "strength", autocvar_hud_progressbar_strength_color, strengthTime, 30);
+       if(shieldTime)
+               addPowerupItem("Shield", "shield", autocvar_hud_progressbar_shield_color, shieldTime, 30);
+       if(superTime)
+               addPowerupItem("Superweapons", "superweapons", autocvar_hud_progressbar_superweapons_color, superTime, 30);
 
-       vector pos, mySize;
-       pos = panel_pos;
-       mySize = panel_size;
+       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);
+       ));
+
+       if(!powerupItemsCount)
+               return;
+
+       // Draw panel background
+       HUD_Panel_UpdateCvars();
+       HUD_Panel_DrawBg(1);
+
+       // Set drawing area
+       vector pos = panel_pos;
+       vector size = panel_size;
+       bool isVertical = size.y > size.x;
 
-       HUD_Panel_DrawBg(bound(0, max(strength_time, shield_time, superweapons_time), 1));
        if(panel_bg_padding)
        {
                pos += '1 1 0' * panel_bg_padding;
-               mySize -= '2 2 0' * panel_bg_padding;
+               size -= '2 2 0' * panel_bg_padding;
        }
 
-       float panel_ar = mySize.x/mySize.y;
-       bool is_vertical = (panel_ar < 1);
-       vector shield_offset = '0 0 0', strength_offset = '0 0 0', superweapons_offset = '0 0 0';
-
-       int superweapons_is = -1;
+       // Find best partitioning of the drawing area
+       const float DESIRED_ASPECT = 6;
+       float aspect = 0, a;
+       int columns = 0, c;
+       int rows = 0, r;
+       int i = 1;
 
-       if(superweapons_time)
+       do
        {
-               if(strength_time)
-               {
-                       if(shield_time)
-                               superweapons_is = 0;
-                       else
-                               superweapons_is = 2;
-               }
-               else
-               {
-                       if(shield_time)
-                               superweapons_is = 1;
-                       else
-                               superweapons_is = 2;
-               }
-       }
+               c = floor(powerupItemsCount / i);
+               r = ceil(powerupItemsCount / c);
+               a = isVertical ? (size.y/r) / (size.x/c) : (size.x/c) / (size.y/r);
 
-       // FIXME handle superweapons here
-       if(superweapons_is == 0)
-       {
-               if (panel_ar >= 4 || (panel_ar >= 1/4 && panel_ar < 1))
-               {
-                       mySize.x *= (1.0 / 3.0);
-                       superweapons_offset.x = mySize.x;
-                       if (autocvar_hud_panel_powerups_flip)
-                               shield_offset.x = 2*mySize.x;
-                       else
-                               strength_offset.x = 2*mySize.x;
-               }
-               else
+               if(i == 1 || fabs(DESIRED_ASPECT - a) < fabs(DESIRED_ASPECT - aspect))
                {
-                       mySize.y *= (1.0 / 3.0);
-                       superweapons_offset.y = mySize.y;
-                       if (autocvar_hud_panel_powerups_flip)
-                               shield_offset.y = 2*mySize.y;
-                       else
-                               strength_offset.y = 2*mySize.y;
+                       aspect = a;
+                       columns = c;
+                       rows = r;
                }
        }
-       else
+       while(++i <= powerupItemsCount);
+
+       // Prevent single items from getting too wide
+       if(powerupItemsCount == 1 && aspect > DESIRED_ASPECT)
        {
-               if (panel_ar >= 4 || (panel_ar >= 1/4 && panel_ar < 1))
+               if(isVertical)
                {
-                       mySize.x *= 0.5;
-                       if (autocvar_hud_panel_powerups_flip)
-                               shield_offset.x = mySize.x;
-                       else
-                               strength_offset.x = mySize.x;
+                       size.y *= 0.5;
+                       pos.y += size.y * 0.5;
                }
                else
                {
-                       mySize.y *= 0.5;
-                       if (autocvar_hud_panel_powerups_flip)
-                               shield_offset.y = mySize.y;
-                       else
-                               strength_offset.y = mySize.y;
+                       size.x *= 0.5;
+                       pos.x += size.x * 0.5;
                }
        }
 
-       bool shield_baralign, strength_baralign, superweapons_baralign;
-       bool shield_iconalign, strength_iconalign, superweapons_iconalign;
+       // Draw items from linked list
+       vector itemPos = pos;
+       vector itemSize = eX * (size.x / columns) + eY * (size.y / rows);
+       vector textColor = '1 1 1';
 
-       if (autocvar_hud_panel_powerups_flip)
-       {
-               strength_baralign = (autocvar_hud_panel_powerups_baralign == 2 || autocvar_hud_panel_powerups_baralign == 1);
-               shield_baralign = (autocvar_hud_panel_powerups_baralign == 3 || autocvar_hud_panel_powerups_baralign == 1);
-               strength_iconalign = (autocvar_hud_panel_powerups_iconalign == 2 || autocvar_hud_panel_powerups_iconalign == 1);
-               shield_iconalign = (autocvar_hud_panel_powerups_iconalign == 3 || autocvar_hud_panel_powerups_iconalign == 1);
-       }
-       else
-       {
-               shield_baralign = (autocvar_hud_panel_powerups_baralign == 2 || autocvar_hud_panel_powerups_baralign == 1);
-               strength_baralign = (autocvar_hud_panel_powerups_baralign == 3 || autocvar_hud_panel_powerups_baralign == 1);
-               shield_iconalign = (autocvar_hud_panel_powerups_iconalign == 2 || autocvar_hud_panel_powerups_iconalign == 1);
-               strength_iconalign = (autocvar_hud_panel_powerups_iconalign == 3 || autocvar_hud_panel_powerups_iconalign == 1);
-       }
+       int fullSeconds = 0;
+       int align = 0;
+       int column = 0;
+       int row = 0;
 
-       if(superweapons_is == 0)
-       {
-               superweapons_iconalign = strength_iconalign;
-               superweapons_baralign = 2;
-       }
-       else if(superweapons_is == 1)
-       {
-               superweapons_offset = strength_offset;
-               superweapons_iconalign = strength_iconalign;
-               superweapons_baralign = strength_baralign;
-       }
-       else // if(superweapons_is == 2)
+       draw_beginBoldFont();
+       for(entity item = powerupItems; item.count; item = item.chain)
        {
-               superweapons_offset = shield_offset;
-               superweapons_iconalign = shield_iconalign;
-               superweapons_baralign = shield_baralign;
-       }
+               itemPos = eX * (pos.x + column * itemSize.x) + eY * (pos.y + row * itemSize.y);
 
-       if(shield_time)
-       {
-               const float maxshield = 30;
-               float shield = ceil(shield_time);
+               // Draw progressbar
                if(autocvar_hud_panel_powerups_progressbar)
-                       HUD_Panel_DrawProgressBar(pos + shield_offset, mySize, autocvar_hud_panel_powerups_progressbar_shield, shield/maxshield, is_vertical, shield_baralign, autocvar_hud_progressbar_shield_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
-               if(autocvar_hud_panel_powerups_text)
                {
-                       if(shield > 1)
-                               DrawNumIcon(pos + shield_offset, mySize, shield, "shield", is_vertical, shield_iconalign, '1 1 1', 1);
-                       if(shield <= 5)
-                               DrawNumIcon_expanding(pos + shield_offset, mySize, shield, "shield", is_vertical, shield_iconalign, '1 1 1', 1, bound(0, (shield - shield_time) / 0.5, 1));
+                       align = getPowerupItemAlign(autocvar_hud_panel_powerups_baralign, column, row, columns, rows, isVertical);
+                       HUD_Panel_DrawProgressBar(itemPos, itemSize, "progressbar", item.count / item.lifetime, isVertical, align, item.colormod, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                }
-       }
 
-       if(strength_time)
-       {
-               const float maxstrength = 30;
-               float strength = ceil(strength_time);
-               if(autocvar_hud_panel_powerups_progressbar)
-                       HUD_Panel_DrawProgressBar(pos + strength_offset, mySize, autocvar_hud_panel_powerups_progressbar_strength, strength/maxstrength, is_vertical, strength_baralign, autocvar_hud_progressbar_strength_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+               // Draw icon and text
                if(autocvar_hud_panel_powerups_text)
                {
-                       if(strength > 1)
-                               DrawNumIcon(pos + strength_offset, mySize, strength, "strength", is_vertical, strength_iconalign, '1 1 1', 1);
-                       if(strength <= 5)
-                               DrawNumIcon_expanding(pos + strength_offset, mySize, strength, "strength", is_vertical, strength_iconalign, '1 1 1', 1, bound(0, (strength - strength_time) / 0.5, 1));
+                       align = getPowerupItemAlign(autocvar_hud_panel_powerups_iconalign, column, row, columns, rows, isVertical);
+                       fullSeconds = ceil(item.count);
+                       textColor = '0.6 0.6 0.6' + (item.colormod * 0.4);
+
+                       if(item.count > 1)
+                               DrawNumIcon(itemPos, itemSize, fullSeconds, item.netname, isVertical, align, textColor, panel_fg_alpha);
+                       if(item.count <= 5)
+                               DrawNumIcon_expanding(itemPos, itemSize, fullSeconds, item.netname, isVertical, align, textColor, panel_fg_alpha, bound(0, (fullSeconds - item.count) / 0.5, 1));
                }
-       }
 
-       if(superweapons_time)
-       {
-               const float maxsuperweapons = 30;
-               float superweapons = ceil(superweapons_time);
-               if(autocvar_hud_panel_powerups_progressbar)
-                       HUD_Panel_DrawProgressBar(pos + superweapons_offset, mySize, autocvar_hud_panel_powerups_progressbar_superweapons, superweapons/maxsuperweapons, is_vertical, superweapons_baralign, autocvar_hud_progressbar_superweapons_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
-               if(autocvar_hud_panel_powerups_text)
+               // Determine next section
+               if(isVertical)
                {
-                       if(superweapons > 1)
-                               DrawNumIcon(pos + superweapons_offset, mySize, superweapons, "superweapons", is_vertical, superweapons_iconalign, '1 1 1', 1);
-                       if(superweapons <= 5)
-                               DrawNumIcon_expanding(pos + superweapons_offset, mySize, superweapons, "superweapons", is_vertical, superweapons_iconalign, '1 1 1', 1, bound(0, (superweapons - superweapons_time) / 0.5, 1));
+                       if(++column >= columns)
+                       {
+                               column = 0;
+                               ++row;
+                       }
+               }
+               else
+               {
+                       if(++row >= rows)
+                       {
+                               row = 0;
+                               ++column;
+                       }
                }
        }
-
        draw_endBoldFont();
 }
 
@@ -1492,6 +1405,7 @@ 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;
@@ -1798,6 +1712,7 @@ 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;
@@ -1909,20 +1824,9 @@ 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;
@@ -1980,8 +1884,170 @@ void HUD_Timer(void)
 
 // Radar (#6)
 //
+
+float HUD_Radar_Clickable()
+{
+       return hud_panel_radar_mouse && !hud_panel_radar_temp_hidden;
+}
+
+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;
+               }
+       }
+       else if ( hud_panel_radar_mouse )
+       {
+               hud_panel_radar_mouse = 0;
+               mouseClicked = 0;
+               if(autocvar_hud_cursormode)
+               if(!mv_active)
+                       setcursormode(0);
+       }
+}
+void HUD_Radar_Hide_Maximized()
+{
+       HUD_Radar_Show_Maximized(false,false);
+}
+
+
+float HUD_Radar_InputEvent(float bInputType, float nPrimary, float nSecondary)
+{
+       if(!hud_panel_radar_maximized || !hud_panel_radar_mouse ||
+               autocvar__hud_configure || mv_active)
+               return false;
+
+       if(bInputType == 3)
+       {
+               mousepos_x = nPrimary;
+               mousepos_y = nSecondary;
+               return true;
+       }
+
+       if(nPrimary == K_MOUSE1)
+       {
+               if(bInputType == 0) // key pressed
+                       mouseClicked |= S_MOUSE1;
+               else if(bInputType == 1) // key released
+                       mouseClicked -= (mouseClicked & S_MOUSE1);
+       }
+       else if(nPrimary == K_MOUSE2)
+       {
+               if(bInputType == 0) // key pressed
+                       mouseClicked |= S_MOUSE2;
+               else if(bInputType == 1) // key released
+                       mouseClicked -= (mouseClicked & S_MOUSE2);
+       }
+       else if ( nPrimary == K_ESCAPE && bInputType == 0 )
+       {
+               HUD_Radar_Hide_Maximized();
+       }
+       else
+       {
+               // allow console/use binds to work without hiding the map
+               string con_keys;
+               float keys;
+               float i;
+               con_keys = strcat(findkeysforcommand("toggleconsole", 0)," ",findkeysforcommand("+use", 0)) ;
+               keys = tokenize(con_keys); // findkeysforcommand returns data for this
+               for (i = 0; i < keys; ++i)
+               {
+                       if(nPrimary == stof(argv(i)))
+                               return false;
+               }
+
+               if ( getstati(STAT_HEALTH) <= 0 )
+               {
+                       // Show scoreboard
+                       if ( bInputType < 2 )
+                       {
+                               con_keys = findkeysforcommand("+showscores", 0);
+                               keys = tokenize(con_keys);
+                               for (i = 0; i < keys; ++i)
+                               {
+                                       if ( nPrimary == stof(argv(i)) )
+                                       {
+                                               hud_panel_radar_temp_hidden = bInputType == 0;
+                                               return false;
+                                       }
+                               }
+                       }
+               }
+               else if ( bInputType == 0 )
+                       HUD_Radar_Hide_Maximized();
+
+               return false;
+       }
+
+       return true;
+}
+
+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;
+
+               mousepos_x = bound(0, mousepos_x, vid_conwidth);
+               mousepos_y = bound(0, mousepos_y, vid_conheight);
+       }
+
+       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
+               if ( mousepos_x < panel_pos_x || mousepos_x > panel_pos_x + panel_size_x ||
+                        mousepos_y < panel_pos_y || mousepos_y > panel_pos_y + panel_size_y )
+               {
+                       HUD_Radar_Hide_Maximized();
+                       return;
+               }
+               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);
+}
+
 void HUD_Radar(void)
 {
+       if(intermission == 2) return;
        if (!autocvar__hud_configure)
        {
                if (hud_panel_radar_maximized)
@@ -2000,6 +2066,9 @@ void HUD_Radar(void)
                }
        }
 
+       if ( hud_panel_radar_temp_hidden )
+               return;
+
        HUD_Panel_UpdateCvars();
 
        float f = 0;
@@ -2153,8 +2222,27 @@ void HUD_Radar(void)
 
        for(tm = world; (tm = find(tm, classname, "radarlink")); )
                draw_teamradar_link(tm.origin, tm.velocity, tm.team);
+
+       vector coord;
+       vector brightcolor;
        for(tm = world; (tm = findflags(tm, teamradar_icon, 0xFFFFFF)); )
+       {
+               if ( hud_panel_radar_mouse )
+               if ( tm.health > 0 )
+               if ( tm.team == myteam+1 )
+               {
+                       coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(tm.origin));
+                       if ( vlen(mousepos-coord) < 8 )
+                       {
+                               brightcolor_x = min(1,tm.teamradar_color_x*1.5);
+                               brightcolor_y = min(1,tm.teamradar_color_y*1.5);
+                               brightcolor_z = min(1,tm.teamradar_color_z*1.5);
+                               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);
+       }
        for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
        {
                color2 = GetPlayerColor(tm.sv_entnum);
@@ -2164,6 +2252,21 @@ void HUD_Radar(void)
        draw_teamradar_player(view_origin, view_angles, '1 1 1');
 
        drawresetcliparea();
+
+       if ( hud_panel_radar_mouse )
+       {
+               string message = "Click to select teleport destination";
+
+               if ( getstati(STAT_HEALTH) <= 0 )
+               {
+                       message = "Click to select spawn location";
+               }
+
+               drawcolorcodedstring(pos + '0.5 0 0' * (mySize_x - stringwidth(message, true, hud_fontsize)) - '0 1 0' * hud_fontsize_y * 2,
+                                                        message, hud_fontsize, hud_panel_radar_foreground_alpha, DRAWFLAG_NORMAL);
+
+               hud_panel_radar_bottom = pos_y + mySize_y + hud_fontsize_y;
+       }
 }
 
 // Score (#7)
@@ -2293,6 +2396,7 @@ 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;
@@ -2476,6 +2580,7 @@ void HUD_Score(void)
 //
 void HUD_RaceTimer (void)
 {
+       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_racetimer) return;
@@ -2626,6 +2731,7 @@ 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;
@@ -2633,7 +2739,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)
@@ -2883,7 +2989,7 @@ void HUD_Mod_CTF(vector pos, vector mySize)
        yellowflag = (stat_items/CTF_YELLOW_FLAG_TAKEN) & 3;
        pinkflag = (stat_items/CTF_PINK_FLAG_TAKEN) & 3;
        neutralflag = (stat_items/CTF_NEUTRAL_FLAG_TAKEN) & 3;
-       
+
        ctf_oneflag = (stat_items & CTF_FLAG_NEUTRAL);
 
        mod_active = (redflag || blueflag || yellowflag || pinkflag || neutralflag);
@@ -3502,6 +3608,7 @@ 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;
@@ -3543,6 +3650,7 @@ void HUD_ModIcons(void)
 //
 void HUD_PressedKeys(void)
 {
+       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_pressedkeys) return;
@@ -3629,6 +3737,15 @@ void HUD_Chat(void)
 
        HUD_Panel_UpdateCvars();
 
+       if(intermission == 2)
+       {
+               // reserve some more space to the mapvote panel
+               // by resizing and moving chat panel to the bottom
+               panel_size.y = min(panel_size.y, vid_conheight * 0.2);
+               panel_pos.y = vid_conheight - panel_size.y - panel_bg_border * 2;
+               chat_posy = panel_pos.y;
+               chat_sizey = panel_size.y;
+       }
        if(autocvar__con_chat_maximized && !autocvar__hud_configure) // draw at full screen height if maximized
        {
                panel_pos.y = panel_bg_border;
@@ -3697,6 +3814,7 @@ 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;
@@ -3758,6 +3876,7 @@ void HUD_EngineInfo(void)
 } while(0)
 void HUD_InfoMessages(void)
 {
+       if(intermission == 2) return;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_infomessages) return;
@@ -3939,6 +4058,7 @@ 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;
@@ -4330,6 +4450,7 @@ 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;
@@ -4372,7 +4493,15 @@ void HUD_CenterPrint (void)
        }
        HUD_Panel_UpdateCvars();
 
-       if(scoreboard_fade_alpha)
+       if ( HUD_Radar_Clickable() )
+       {
+               if (hud_panel_radar_bottom >= 0.96 * vid_conheight)
+                       return;
+
+               panel_pos = eY * hud_panel_radar_bottom + eX * 0.5 * (vid_conwidth - panel_size_x);
+               panel_size_y = min(panel_size_y, vid_conheight - hud_panel_radar_bottom);
+       }
+       else if(scoreboard_fade_alpha)
        {
                hud_fade_alpha = hud_fade_alpha_save;
 
@@ -4548,64 +4677,15 @@ void HUD_CenterPrint (void)
        }
 }
 
-// Buffs (#18)
-//
-void HUD_Buffs(void)
-{
-       int buffs = getstati(STAT_BUFFS, 0, 24);
-       if(!autocvar__hud_configure)
-       {
-               if(!autocvar_hud_panel_buffs) return;
-               if(spectatee_status == -1) return;
-               if(getstati(STAT_HEALTH) <= 0) return;
-               if(!buffs) return;
-       }
-       else
-       {
-               buffs = Buff_Type_first.items; // force first buff
-       }
 
-       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)
-       {
-               ++b;
-               string o = strcat(rgb_to_hexcolor(Buff_Color(e.items)), Buff_PrettyName(e.items));
-               if(s == "")
-                       s = o;
-               else
-                       s = strcat(s, " ", o);
-       }
-
-       HUD_Panel_UpdateCvars();
-
-       draw_beginBoldFont();
-
-       vector pos, mySize;
-       pos = panel_pos;
-       mySize = panel_size;
-
-       HUD_Panel_DrawBg(bound(0, b, 1));
-       if(panel_bg_padding)
-       {
-               pos += '1 1 0' * panel_bg_padding;
-               mySize -= '2 2 0' * panel_bg_padding;
-       }
-
-       //float panel_ar = mySize_x/mySize_y;
-       //bool is_vertical = (panel_ar < 1);
-       //float buff_iconalign = autocvar_hud_panel_buffs_iconalign;
-       vector buff_offset = '0 0 0';
+// Minigame
+//
+#include "../common/minigames/cl_minigames_hud.qc"
 
-       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);
-               drawcolorcodedstring_aspect(pos + buff_offset, s, mySize, panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
-       }
 
-       draw_endBoldFont();
-}
+// QuickMenu (#23)
+//
+#include "quickmenu.qc"
 
 
 /*
@@ -4614,6 +4694,20 @@ Main HUD system
 ==================
 */
 
+bool HUD_Panel_CheckFlags(int showflags)
+{
+       if ( HUD_Minigame_Showpanels() )
+               return showflags & PANEL_SHOW_MINIGAME;
+       return showflags & PANEL_SHOW_MAINGAME;
+}
+
+void HUD_Panel_Draw(entity panent)
+{
+       panel = panent;
+       if ( HUD_Panel_CheckFlags(panel.panel_showflags) )
+               panel.panel_draw();
+}
+
 void HUD_Reset (void)
 {
        // reset gametype specific icons
@@ -4635,19 +4729,21 @@ void HUD_Main (void)
 
        HUD_Configure_Frame();
 
-       if(intermission == 2) // no hud during mapvote
-               hud_fade_alpha = 0;
-
        // panels that we want to be active together with the scoreboard
        // 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)
@@ -4729,7 +4825,7 @@ void HUD_Main (void)
                        }
                }
                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)
@@ -4744,16 +4840,18 @@ void HUD_Main (void)
        }
 
        hud_draw_maximized = 0;
-       // draw panels in order specified by panel_order array
+       // 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();
+               HUD_Panel_Draw(hud_panel[panel_order[i]]);
 
        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));
 
        HUD_Configure_PostDraw();