]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/hud.qc
force showing a background in config mode, also adapt old nexuiz hud config for the...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud.qc
index 04360a03bd10a087867f3e20f1126bb32b6f3b66..80421f67b177ddfdeb2fd74dc8a7a1a27f2be20e 100644 (file)
@@ -80,6 +80,10 @@ void drawpic_skin(vector pos, string pic, vector sz, vector color, float alpha,
        drawpic(pos, strcat("gfx/hud/", cvar_string("hud_skin"), "/", pic), sz, color, alpha, drawflag);
 }
 
+void drawpic_skin_expanding(vector pos, string pic, vector sz, vector rgb, float alpha, float flag, float fadelerp) {
+       drawpic_expanding(pos, strcat("gfx/hud/", cvar_string("hud_skin"), "/", pic), sz, rgb, alpha, flag, fadelerp);
+}
+
 // return HUD background color
 vector HUD_GetBgColor()
 {
@@ -571,9 +575,10 @@ void HUD_Panel_ExportCfg(string cfgname)
                fputs(fh, strcat("seta hud_skin \"", cvar_string("hud_skin"), "\"", "\n"));
                fputs(fh, strcat("seta hud_bg \"", cvar_string("hud_bg"), "\"", "\n"));
                fputs(fh, strcat("seta hud_bg_color \"", cvar_string("hud_bg_color"), "\"", "\n"));
-               fputs(fh, strcat("seta hud_bg_alpha ", ftos(cvar("hud_bg_alpha")), "\n"));
-               fputs(fh, strcat("seta hud_bg_border ", ftos(cvar("hud_bg_border")), "\n"));
-               fputs(fh, strcat("seta hud_fg_alpha ", ftos(cvar("hud_fg_alpha")), "\n"));
+               fputs(fh, strcat("seta hud_bg_alpha ", cvar_string("hud_bg_alpha"), "\n"));
+               fputs(fh, strcat("seta hud_bg_border ", cvar_string("hud_bg_border"), "\n"));
+               fputs(fh, strcat("seta hud_bg_padding ", cvar_string("hud_bg_padding"), "\n"));
+               fputs(fh, strcat("seta hud_fg_alpha ", cvar_string("hud_fg_alpha"), "\n"));
                fputs(fh, "\n");
 
                fputs(fh, strcat("seta hud_dock \"", cvar_string("hud_dock"), "\"", "\n"));
@@ -587,6 +592,7 @@ void HUD_Panel_ExportCfg(string cfgname)
                fputs(fh, strcat("seta hud_progressbar_health_color \"", cvar_string("hud_progressbar_health_color"), "\"", "\n"));
                fputs(fh, strcat("seta hud_progressbar_armor_color \"", cvar_string("hud_progressbar_armor_color"), "\"", "\n"));
                fputs(fh, strcat("seta hud_progressbar_fuel_color \"", cvar_string("hud_progressbar_fuel_color"), "\"", "\n"));
+               fputs(fh, strcat("seta hud_progressbar_nexball_color \"", cvar_string("hud_progressbar_nexball_color"), "\"", "\n"));
                fputs(fh, "\n");
 
                // common cvars for all panels
@@ -598,8 +604,9 @@ void HUD_Panel_ExportCfg(string cfgname)
                        fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_size \"", cvar_string(strcat("hud_", HUD_Panel_GetName(i), "_size")), "\"", "\n"));
                        fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_bg \"", cvar_string(strcat("hud_", HUD_Panel_GetName(i), "_bg")), "\"", "\n"));
                        fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_bg_color \"", cvar_string(strcat("hud_", HUD_Panel_GetName(i), "_bg_color")), "\"", "\n"));
-                       fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_bg_alpha ", ftos(cvar(strcat("hud_", HUD_Panel_GetName(i), "_bg_alpha"))), "\n"));
-                       fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_bg_border ", ftos(cvar(strcat("hud_", HUD_Panel_GetName(i), "_bg_border"))), "\n"));
+                       fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_bg_alpha ", cvar_string(strcat("hud_", HUD_Panel_GetName(i), "_bg_alpha")), "\n"));
+                       fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_bg_border ", cvar_string(strcat("hud_", HUD_Panel_GetName(i), "_bg_border")), "\n"));
+                       fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_bg_padding ", cvar_string(strcat("hud_", HUD_Panel_GetName(i), "_bg_padding")), "\n"));
                        switch(i) {
                                case 0:
                                        fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_accuracy_height ", ftos(cvar(strcat("hud_", HUD_Panel_GetName(i), "_accuracy_height"))), "\n"));
@@ -657,6 +664,9 @@ vector HUD_Panel_CheckLimitSize(float id, vector mySize)
                        mySize_y = (1/4) * mySize_x; // 1/4 * width
                        break;
                case 10: 
+                       mySize_y = (1/2) * mySize_x; // 1/2 * width
+                       break;
+               case 11: 
                        mySize_y = 0.5898 * mySize_x; // 0.5898 * width, reason: bg has weird dimensions...
                        break;
        }
@@ -699,16 +709,45 @@ vector HUD_Panel_GetPos(float id)
 
 float HUD_Panel_GetBorder(float id)
 {
-       float border;
-       border = cvar(strcat("hud_", HUD_Panel_GetName(id), "_bg_border"));
-       if(!border)
-               border = cvar("hud_bg_border");
-       return border;
+       string border;
+       border = cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_bg_border"));
+       if(border == "")
+               border = cvar_string("hud_bg_border");
+       return stof(border);
+}
+
+vector HUD_Panel_GetColor(float id)
+{
+       string color;
+       color = cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_bg_color"));
+       if(color == "")
+               color = cvar_string("hud_bg_color");
+       return stov(color);
+}
+
+float HUD_Panel_GetAlpha(float id)
+{
+       string alpha;
+       alpha = cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_bg_alpha"));
+       if(alpha == "")
+               alpha = cvar_string("hud_bg_alpha");
+       return stof(alpha);
+}
+
+float HUD_Panel_GetPadding(float id)
+{
+       string padding;
+       padding = cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_bg_padding"));
+       if(padding == "")
+               padding = cvar_string("hud_bg_padding");
+       return stof(padding);
 }
 
 // draw the background/borders
 void HUD_Panel_DrawBg(float id, vector pos, vector mySize)
 {
+       float alpha;
+
        if(!hud_configure && cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_bg")) == "0")
                return;
 
@@ -717,23 +756,21 @@ void HUD_Panel_DrawBg(float id, vector pos, vector mySize)
        if(bg == "")
                bg = cvar_string("hud_bg");
 
+       if(bg == "0" && hud_configure) {
+               bg = "border"; // we probably want to see a background in config mode at all times...
+               alpha = cvar("hud_configure_bg_minalpha");
+       }
+
        if(bg != "0")
        {
                float border;
                border = max(0.0000001, HUD_Panel_GetBorder(id)); // draw_BorderPicture does not like border = 0
 
                vector color;
-               if(cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_bg_color")) != "")
-                       color = stov(cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_bg_color")));
-               else
-                       color = stov(cvar_string("hud_bg_color"));
+               color = HUD_Panel_GetColor(id);
 
-               float alpha;
-               alpha = cvar(strcat("hud_", HUD_Panel_GetName(id), "_bg_alpha"));
                if(!alpha)
-                       alpha = cvar("hud_bg_alpha");
-               if(hud_configure)
-                       alpha = max(cvar("hud_configure_bg_minalpha"), alpha);
+                       alpha = HUD_Panel_GetAlpha(id);
 
                draw_BorderPicture(pos - '1 1 0' * border, strcat("gfx/hud/", cvar_string("hud_skin"), "/", bg), mySize + '1 1 0' * 2 * border, color, alpha, '1 1 0' * (border/BORDER_MULTIPLIER));
        }
@@ -757,6 +794,8 @@ vector HUD_Panel_CheckResize(float id, vector myPos, vector mySize)
        vector targSize;
        vector myCenter;
        vector targCenter;
+       myCenter = '0 0 0'; // shut up fteqcc, there IS a reference
+       targCenter = '0 0 0'; // shut up fteqcc, there IS a reference
 
        for (i = 0; i < panel_cnt; ++i) {
                if(i == id || !HUD_Panel_CheckActive(i))
@@ -786,7 +825,6 @@ vector HUD_Panel_CheckResize(float id, vector myPos, vector mySize)
                targCenter_x = targPos_x + 0.5 * targSize_x;
                targCenter_y = targPos_y + 0.5 * targSize_y;
 
-               float k, y;
                if(myCenter_x < targCenter_x && myCenter_y < targCenter_y && resizeCorner != 1) // top left (of target panel)
                {
                        if(myPos_x + mySize_x - targPos_x < myPos_y + mySize_y - targPos_y) // push it to the side
@@ -844,6 +882,12 @@ float HUD_Panel_SetSize(float id, vector mySize)
        //mySize_x = bound(0.025 * vid_conwidth, mySize_x, vid_conwidth);
        //mySize_y = bound(0.025 * vid_conheight, mySize_y, vid_conheight);
 
+       if(cvar("hud_configure_grid"))
+       {
+               mySize_x = floor(mySize_x/cvar("hud_configure_grid_x") + 0.5) * cvar("hud_configure_grid_x");
+               mySize_y = floor(mySize_y/cvar("hud_configure_grid_y") + 0.5) * cvar("hud_configure_grid_y");
+       }
+
        // TODO: is this needed?
        // this is to check if (and how) SetPos should be called
        if(mySize_x == oldSize_x && mySize_y == oldSize_y)
@@ -871,6 +915,8 @@ vector HUD_Panel_CheckMove(float id, vector myPos, vector mySize)
        vector targSize;
        vector myCenter;
        vector targCenter;
+       myCenter = '0 0 0'; // shut up fteqcc, there IS a reference
+       targCenter = '0 0 0'; // shut up fteqcc, there IS a reference
 
        for (i = 0; i < panel_cnt; ++i) {
                if(i == id || !HUD_Panel_CheckActive(i))
@@ -897,7 +943,6 @@ vector HUD_Panel_CheckMove(float id, vector myPos, vector mySize)
                targCenter_x = targPos_x + 0.5 * targSize_x;
                targCenter_y = targPos_y + 0.5 * targSize_y;
 
-               float k, y;
                if(myCenter_x < targCenter_x && myCenter_y < targCenter_y) // top left (of the target panel)
                {
                        if(myPos_x + mySize_x - targPos_x < myPos_y + mySize_y - targPos_y) // push it to the side
@@ -951,6 +996,12 @@ void HUD_Panel_SetPos(float id, vector pos, float didntresize)
        pos_x = bound(0, pos_x, vid_conwidth - mySize_x);
        pos_y = bound(0, pos_y, vid_conheight - mySize_y);
 
+       if(cvar("hud_configure_grid"))
+       {
+               pos_x = floor(pos_x/cvar("hud_configure_grid_x") + 0.5) * cvar("hud_configure_grid_x");
+               pos_y = floor(pos_y/cvar("hud_configure_grid_y") + 0.5) * cvar("hud_configure_grid_y");
+       }
+
        if (pos_x + 0.5 * mySize_x > 0.5 * vid_conwidth)
                pos_x = pos_x - vid_conwidth;
        if (pos_y + 0.5 * mySize_y > 0.5 * vid_conheight)
@@ -1117,7 +1168,7 @@ void weaponorder_swap(float i, float j, entity pass)
 
 float weaponorder_cmp(float i, float j, entity pass)
 {
-       float d, ii, ij;
+       float d;
        d = mod(weaponorder[i].impulse + 9, 10) - mod(weaponorder[j].impulse + 9, 10);
        if(d)
                return d;
@@ -1128,13 +1179,12 @@ float weaponorder_cmp(float i, float j, entity pass)
 void HUD_WeaponIcons()
 {
        float id = 0;
-       float alpha, height, accuracybar_height, stat_weapons; // "constants"
-       vector pos, mySize, mysize, mypos, accuracy_color;
+       float alpha, stat_weapons; // "constants"
+       vector pos, mySize, accuracy_color;
        float i, weapid, fade, weapon_stats, weapon_hit, weapon_damage, weapon_cnt; // variables
 
        pos = HUD_Panel_GetPos(id);
        mySize = HUD_Panel_GetSize(id);
-       accuracybar_height = cvar_or("hud_weaponicons_accuracy_height", 3);
 
        stat_weapons = getstati(STAT_WEAPONS);
        for(i = WEP_FIRST; i <= WEP_LAST; ++i)
@@ -1195,12 +1245,9 @@ void HUD_WeaponIcons()
                        weapon_hit = weapon_hits[self.weapon-WEP_FIRST];
                        weapon_damage = weapon_fired[self.weapon-WEP_FIRST];
 
+                       // draw background behind currently selected weapon
                        if(self.weapon == activeweapon)
                                drawpic_skin(pos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows), "weapon_current_bg", eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows), '1 1 1', fade * hud_alpha_fg, DRAWFLAG_NORMAL);
-                       drawpic(pos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows), strcat("gfx/weapons/weapon", self.netname), eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows), '1 1 1', fade * hud_alpha_fg, DRAWFLAG_NORMAL);
-
-                       if(cvar_or("hud_weaponicons_number", 1))
-                               drawstring(pos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows), ftos(weapid), '1 1 0' * 0.5 * mySize_y*(1/rows), '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
 
                        // draw the weapon accuracy on the HUD
                        if(hud_accuracy_hud && !(gametype == GAME_RACE || gametype == GAME_CTS))
@@ -1210,8 +1257,14 @@ void HUD_WeaponIcons()
 
                                accuracy_color = HUD_AccuracyColor(weapon_stats);
                                if(weapon_damage)
-                                       drawpic_skin(pos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows) - '2 0 0' + eY * (mySize_y/rows - accuracybar_height), "accuracy_bar.tga", eX * mySize_x*(1/columns) + eY * accuracybar_height, accuracy_color, hud_alpha_fg, DRAWFLAG_NORMAL);
+                                       drawpic_skin(pos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows), "weapon_accuracy", eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows), accuracy_color, hud_alpha_fg, DRAWFLAG_NORMAL);
                        }
+
+                       // draw the weapon icon
+                       drawpic(pos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows), strcat("gfx/weapons/weapon", self.netname), eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows), '1 1 1', fade * hud_alpha_fg, DRAWFLAG_NORMAL);
+
+                       if(cvar_or("hud_weaponicons_number", 1))
+                               drawstring(pos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows), ftos(weapid), '1 1 0' * 0.5 * mySize_y*(1/rows), '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
                }
 
                ++row;
@@ -1294,7 +1347,6 @@ void HUD_Inventory()
 
                if(cvar("hud_inventory_onlycurrent")) {
                        if (stat_items & GetAmmoItemCode(i)) {
-                               drawpic_skin(pos, "ammo_current_bg", mySize, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
                                drawpic_skin(pos + eY * 0.05 * mySize_y, GetAmmoPicture(i), '1 1 0' * 0.8 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
                                if(a < 10)
                                        HUD_DrawXNum(pos + eX * 0.8 * mySize_y + eY * 0.25 * mySize_y, a, strlen(ftos(a)), 0, 0.5 * mySize_y, '0.7 0 0', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
@@ -1354,8 +1406,6 @@ void HUD_Inventory()
 
 // Powerups (#2)
 //
-float shield_maxtime;
-float strength_maxtime;
 void HUD_Powerups() {
        float id = 2;
        float stat_items;
@@ -1621,7 +1671,7 @@ void HUD_HealthArmor(void)
                mySize -= '2 2 0' * padding;
        }
 
-       float armor, health, x;
+       float armor, health;
        armor = getstati(STAT_ARMOR);
        health = getstati(STAT_HEALTH);
 
@@ -2223,11 +2273,65 @@ void HUD_Score()
 
        float score, distribution, leader;
        float score_len, distr_len;
-       vector score_pos, secondary_score_pos, distribution_color;
+       vector distribution_color;
        entity tm, pl, me;
        me = (spectatee_status > 0) ? playerslots[spectatee_status - 1] : playerslots[player_localentnum - 1];
 
-       if (!teamplay) { // non-teamgames
+       // TODO... this (race part) still uses constant coordinates :/
+       if((scores_flags[ps_primary] & SFL_TIME) && !teamplay) { // race/cts record display on HUD
+               /*pl = players.sort_next;
+               if(pl == me)
+                       pl = pl.sort_next;
+               if(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)
+                       if(pl.scores[ps_primary] == 0)
+                               pl = world;
+
+               score = me.(scores[ps_primary]);
+
+               float racemin, racesec, racemsec;
+               float distsec, distmsec, minusplus;
+
+               racemin = floor(score/(60 * TIME_FACTOR));
+               racesec = floor((score - racemin*(60 * TIME_FACTOR))/TIME_FACTOR);
+               racemsec = score - racemin*60*TIME_FACTOR - racesec*TIME_FACTOR;
+
+               if (pl && ((!(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)) || score)) {
+                       // distribution display
+                       distribution = me.(scores[ps_primary]) - pl.(scores[ps_primary]);
+
+                       if (distribution < TIME_FACTOR && distribution > -TIME_FACTOR)
+                               distmsec = fabs(distribution);
+                       else {
+                               distsec = floor(fabs(distribution)/TIME_FACTOR);
+                               distmsec = fabs(distribution) - distsec*TIME_FACTOR;
+                               if (distribution < 0)
+                                       distsec = -distsec;
+                       }
+
+                       if (distribution <= 0) {
+                               distribution_color = eY;
+                               minusplus = 1; // minusplus 1: always prefix with minus sign
+                       }
+                       else {
+                               distribution_color = eX;
+                               minusplus = 2; // minusplus 1: always prefix with plus sign
+                       }
+                       HUD_DrawXNum(bottomright - '0 48 0' - '16 0 0' * TIME_DECIMALS, distmsec, -TIME_DECIMALS, 0, 16, distribution_color, 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+                       HUD_DrawXNum(bottomright - '68 48 0' - '16 0 0' * TIME_DECIMALS, distsec, 4, minusplus, 16, distribution_color, 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+                       drawpic_skin(bottomright - '10 48 0' - '16 0 0' * TIME_DECIMALS, "num_dot", '16 16 0', distribution_color, hud_alpha_fg, DRAWFLAG_ADDITIVE);
+               }
+               // race record display
+               if (distribution <= 0 || distribution == score) // draw the highlight background behind the timer if we have the lead
+                       drawpic_skin(bottomright - '0 32 0' - '32 0 0' * (4 + TIME_DECIMALS), "highlight_4", '0 28 0' + '32 0 0' * (4 + TIME_DECIMALS), '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+
+               HUD_DrawXNum(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0', racemsec, -TIME_DECIMALS, 0, 30, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+               HUD_DrawXNum(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0'  - '66 0 0', racesec, -2, 0, 30, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+               drawpic_skin(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0' - '18 0 0', "num_dot", '30 30 0', '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE);
+
+               HUD_DrawXNum(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0' - '132 0 0', racemin, -2, 0, 30, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+               drawpic_skin(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0' - '84 0 0', "num_colon", '30 30 0', '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE);
+               */
+       } else if (!teamplay) { // non-teamgames
                // me vector := [team/connected frags id]
                pl = players.sort_next;
                if(pl == me)
@@ -2520,81 +2624,23 @@ void HUD_VoteWindow(void)
        }
 }
 
-// Mod icons/awards panel (#10)
+// Mod icons panel (#10)
 //
 
-float race_status_time;
-float race_status_prev;
-string race_status_name_prev;
-void HUD_DrawRaceStatus(vector pos)
-{
-       if (race_status != race_status_prev || race_status_name != race_status_name_prev) {
-               race_status_time = time + 5;
-               race_status_prev = race_status;
-               if (race_status_name_prev)
-                       strunzone(race_status_name_prev);
-               race_status_name_prev = strzone(race_status_name);
-       }
-
-       float a;
-       a = bound(0, race_status_time - time, 1);
-
-       string s;
-       s = textShortenToWidth(race_status_name, 120, '10 10 0', stringwidth_colors);
-
-       float rank;
-       if(race_status > 0)
-               rank = race_CheckName(race_status_name);
-       string rankname;
-       rankname = race_PlaceName(rank);
-
-       if(race_status == 0)
-               drawpic_skin(pos, "race_newfail", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
-       else if(race_status == 1) {
-               drawpic_skin(pos, "race_newtime", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
-               drawcolorcodedstring(pos + '40 80 0' - eX * stringwidth(s, TRUE, '5 0 0'), s, '10 10 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
-               drawstring(pos + '40 20 0' - eX * stringwidth(rankname, TRUE, '7 0 0'), rankname, '14 14 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
-       } else if(race_status == 2) {
-               if(race_status_name == GetPlayerName(player_localentnum -1) || !race_myrank || race_myrank < rank)
-                       drawpic_skin(pos, "race_newrankgreen", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
-               else
-                       drawpic_skin(pos, "race_newrankyellow", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
-               drawcolorcodedstring(pos + '40 80 0' - eX * stringwidth(s, TRUE, '5 0 0'), s, '10 10 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
-               drawstring(pos + '40 20 0' - eX * stringwidth(rankname, TRUE, '7 0 0'), rankname, '14 14 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
-       } else if(race_status == 3) {
-               drawpic_skin(pos, "race_newrecordserver", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
-               drawcolorcodedstring(pos + '40 80 0' - eX * stringwidth(s, TRUE, '5 0 0'), s, '10 10 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
-               drawstring(pos + '40 20 0' - eX * stringwidth(rankname, TRUE, '7 0 0'), rankname, '14 14 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
-       }
-
-       if (race_status_time - time <= 0) {
-               race_status_prev = -1;
-               race_status = -1;
-               if(race_status_name)
-                       strunzone(race_status_name);
-               race_status_name = string_null;
-               if(race_status_name_prev)
-                       strunzone(race_status_name_prev);
-               race_status_name_prev = string_null;
-       }
-}
-
 // CTF HUD modicon section
 float redflag_prevframe, blueflag_prevframe; // status during previous frame
 float redflag_prevstatus, blueflag_prevstatus; // last remembered status
 float redflag_statuschange_time, blueflag_statuschange_time; // time when the status changed
 
-void CSQC_ctf_hudreset(void)
+void HUD_Mod_CTF_Reset(void)
 {
        redflag_prevstatus = blueflag_prevstatus = redflag_prevframe = blueflag_prevframe = redflag_statuschange_time = blueflag_statuschange_time = 0;
 }
 
-void CSQC_ctf_hud(void)
+void HUD_Mod_CTF(vector pos, vector mySize)
 {
-       vector bottomleft, redflag_pos, blueflag_pos, sz;
+       vector redflag_pos, blueflag_pos;
        float f; // every function should have that
-       bottomleft_y = vid_conheight;
-       bottomleft_z = 0;
 
        float redflag, blueflag; // current status
        float redflag_statuschange_elapsedtime, blueflag_statuschange_elapsedtime; // time since the status changed
@@ -2604,6 +2650,12 @@ void CSQC_ctf_hud(void)
        redflag = (stat_items/IT_RED_FLAG_TAKEN) & 3;
        blueflag = (stat_items/IT_BLUE_FLAG_TAKEN) & 3;
 
+       if(hud_configure)
+       {
+               redflag = 1;
+               blueflag = 2;
+       }
+
        // when status CHANGES, set old status into prevstatus and current status into status
        if (redflag != redflag_prevframe)
        {
@@ -2688,108 +2740,53 @@ void CSQC_ctf_hud(void)
        }
 
        if (myteam == COLOR_TEAM1) { // always draw own flag on left
-               redflag_pos = bottomleft - '-4 50 0';
-               blueflag_pos = bottomleft - '-62 50 0';
+               redflag_pos = pos;
+               blueflag_pos = pos + eX * mySize_y;
        } else {
-               blueflag_pos = bottomleft - '-4 50 0';
-               redflag_pos = bottomleft - '-62 50 0';
+               blueflag_pos = pos;
+               redflag_pos = pos + eX * mySize_y;
        }
 
-       sz = '52 52 0';
-
        f = bound(0, redflag_statuschange_elapsedtime*2, 1);
        if(red_icon_prevstatus && f < 1)
-               drawpic_expanding(redflag_pos, red_icon_prevstatus, sz, '1 1 1', hud_alpha_fg * red_alpha_prevstatus, DRAWFLAG_NORMAL, f);
+               drawpic_skin_expanding(redflag_pos, red_icon_prevstatus, '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg * red_alpha_prevstatus, DRAWFLAG_NORMAL, f);
        if(red_icon)
-               drawpic_skin(redflag_pos, red_icon, sz, '1 1 1', hud_alpha_fg * red_alpha * f, DRAWFLAG_NORMAL);
+               drawpic_skin(redflag_pos, red_icon, '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg * red_alpha * f, DRAWFLAG_NORMAL);
 
        f = bound(0, blueflag_statuschange_elapsedtime*2, 1);
        if(blue_icon_prevstatus && f < 1)
-               drawpic_expanding(blueflag_pos, blue_icon_prevstatus, sz, '1 1 1', hud_alpha_fg * blue_alpha_prevstatus, DRAWFLAG_NORMAL, f);
+               drawpic_skin_expanding(blueflag_pos, blue_icon_prevstatus, '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg * blue_alpha_prevstatus, DRAWFLAG_NORMAL, f);
        if(blue_icon)
-               drawpic_skin(blueflag_pos, blue_icon, sz, '1 1 1', hud_alpha_fg * blue_alpha * f, DRAWFLAG_NORMAL);
+               drawpic_skin(blueflag_pos, blue_icon, '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg * blue_alpha * f, DRAWFLAG_NORMAL);
 }
 
-/*void HUD_Mod_Race (void) {
-       if((scores_flags[ps_primary] & SFL_TIME) && !teamplay) { // race/cts record display on HUD
-               pl = players.sort_next;
-               if(pl == me)
-                       pl = pl.sort_next;
-               if(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)
-                       if(pl.scores[ps_primary] == 0)
-                               pl = world;
-
-               score = me.(scores[ps_primary]);
-
-               float racemin, racesec, racemsec;
-               float distsec, distmsec, minusplus;
-
-               racemin = floor(score/(60 * TIME_FACTOR));
-               racesec = floor((score - racemin*(60 * TIME_FACTOR))/TIME_FACTOR);
-               racemsec = score - racemin*60*TIME_FACTOR - racesec*TIME_FACTOR;
-
-               if (pl && ((!(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)) || score)) {
-                       // distribution display
-                       distribution = me.(scores[ps_primary]) - pl.(scores[ps_primary]);
-
-                       if (distribution < TIME_FACTOR && distribution > -TIME_FACTOR)
-                               distmsec = fabs(distribution);
-                       else {
-                               distsec = floor(fabs(distribution)/TIME_FACTOR);
-                               distmsec = fabs(distribution) - distsec*TIME_FACTOR;
-                               if (distribution < 0)
-                                       distsec = -distsec;
-                       }
-
-                       if (distribution <= 0) {
-                               distribution_color = eY;
-                               minusplus = 1; // minusplus 1: always prefix with minus sign
-                       }
-                       else {
-                               distribution_color = eX;
-                               minusplus = 2; // minusplus 1: always prefix with plus sign
-                       }
-                       HUD_DrawXNum(bottomright - '0 48 0' - '16 0 0' * TIME_DECIMALS, distmsec, -TIME_DECIMALS, 0, 16, distribution_color, 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
-                       HUD_DrawXNum(bottomright - '68 48 0' - '16 0 0' * TIME_DECIMALS, distsec, 4, minusplus, 16, distribution_color, 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
-                       drawpic_skin(bottomright - '10 48 0' - '16 0 0' * TIME_DECIMALS, "num_dot", '16 16 0', distribution_color, hud_alpha_fg, DRAWFLAG_ADDITIVE);
-               }
-               // race record display
-               if (distribution <= 0 || distribution == score) // draw the highlight background behind the timer if we have the lead
-                       drawpic_skin(bottomright - '0 32 0' - '32 0 0' * (4 + TIME_DECIMALS), "highlight_4", '0 28 0' + '32 0 0' * (4 + TIME_DECIMALS), '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
-
-               HUD_DrawXNum(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0', racemsec, -TIME_DECIMALS, 0, 30, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
-               HUD_DrawXNum(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0'  - '66 0 0', racesec, -2, 0, 30, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
-               drawpic_skin(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0' - '18 0 0', "num_dot", '30 30 0', '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE);
-
-               HUD_DrawXNum(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0' - '132 0 0', racemin, -2, 0, 30, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
-               drawpic_skin(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0' - '84 0 0', "num_colon", '30 30 0', '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE);
-       }
-}*/
-
 // Keyhunt HUD modicon section
 float kh_runheretime;
 
-void CSQC_kh_hudreset(void)
+void HUD_Mod_KH_Reset(void)
 {
        kh_runheretime = 0;
 }
 
-void CSQC_kh_hud(void)
+void HUD_Mod_KH(vector pos, vector mySize)
 {
        float kh_keys;
        float keyteam;
        float a, aa;
        vector p, pa, kh_size, kh_asize;
 
-       p_x = 6;
-       p_y = vid_conheight - 34 - 3;
-       p_z = 0;
+       p_x = pos_x;
+       p_y = pos_y + 0.25 * mySize_y;
 
        kh_keys = getstati(STAT_KH_KEYS);
 
-       kh_size = '19 34 0';
-       kh_asize = '19 10 0';
-       pa = p + '0 -10 0';
+       kh_size_x = mySize_x * 0.25;
+       kh_size_y = 0.75 * mySize_y;
+
+       pa = p - eY * 0.25 * mySize_y;
+
+       kh_asize_x = mySize_x * 0.25;
+       kh_asize_y = mySize_y * 0.25;
 
        float i, key;
 
@@ -2842,16 +2839,16 @@ void CSQC_kh_hud(void)
                        switch(keyteam)
                        {
                                case COLOR_TEAM1:
-                                       drawpic (pa, "kh_redarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% alpha key
+                                       drawpic_skin(pa, "kh_redarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% alpha key
                                        break;
                                case COLOR_TEAM2:
-                                       drawpic (pa, "kh_bluearrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% alpha key
+                                       drawpic_skin(pa, "kh_bluearrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% alpha key
                                        break;
                                case COLOR_TEAM3:
-                                       drawpic (pa, "kh_yellowarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% alpha key
+                                       drawpic_skin(pa, "kh_yellowarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% alpha key
                                        break;
                                case COLOR_TEAM4:
-                                       drawpic (pa, "kh_pinkarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% alpha key
+                                       drawpic_skin(pa, "kh_pinkarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% alpha key
                                        break;
                                default:
                                        break;
@@ -2859,81 +2856,61 @@ void CSQC_kh_hud(void)
                        switch(i) // YAY! switch(i) inside a for loop for i. DailyWTF, here we come!
                        {
                                case 0:
-                                       drawpic (p, "kh_red", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% alpha key
+                                       drawpic_skin(p, "kh_red", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% alpha key
                                        break;
                                case 1:
-                                       drawpic (p, "kh_blue", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% alpha key
+                                       drawpic_skin(p, "kh_blue", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% alpha key
                                        break;
                                case 2:
-                                       drawpic (p, "kh_yellow", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% alpha key
+                                       drawpic_skin(p, "kh_yellow", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% alpha key
                                        break;
                                case 3:
-                                       drawpic (p, "kh_pink", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% alpha key
+                                       drawpic_skin(p, "kh_pink", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% alpha key
                                        break;
                        }
                }
-               p_x += 24;
-               pa_x += 24;
+               p_x += 0.25 * mySize_x;
+               pa_x += 0.25 * mySize_x;
        }
 }
 
-// Nexball HUD modicon section
-#define NBPB_SIZE '96 38 0'
-#define NBPB_BT 2                   //thickness
-#define NBPB_BRGB '1 1 1'
-#define NBPB_BALPH 1                //alpha
-#define NBPB_BFLAG DRAWFLAG_NORMAL
-#define NBPB_IALPH 0.4
-#define NBPB_IFLAG DRAWFLAG_NORMAL
-#define NBPB_IRGB '0.7 0.1 0'
-
-void CSQC_nb_hud(void)
+// Nexball HUD mod icon
+void HUD_Mod_NexBall(vector pos, vector mySize)
 {
        float stat_items, nb_pb_starttime, dt, p;
-       vector pos;
 
        stat_items = getstati(STAT_ITEMS);
        nb_pb_starttime = getstatf(STAT_NB_METERSTART);
 
-       pos_x = 4;
-       pos_y = vid_conheight - 42;
-       pos_z = 0;
-
        //Manage the progress bar if any
        if (nb_pb_starttime > 0)
        {
-               vector s;
                dt = mod(time - nb_pb_starttime, nb_pb_period);
                // one period of positive triangle
                p = 2 * dt / nb_pb_period;
                if (p > 1)
                        p = 2 - p;
 
-               s = NBPB_SIZE;
                //Draw the filling
-               drawfill(pos, p * s_x * eX + s_y * eY, NBPB_IRGB, NBPB_IALPH, NBPB_IFLAG);
-
-               //Draw the box
-               s = NBPB_SIZE;
-               drawline(NBPB_BT, pos    , pos + eX * s_x, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
-               drawline(NBPB_BT, pos    , pos + eY * s_y, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
-               drawline(NBPB_BT, pos + s, pos + eX * s_x, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
-               drawline(NBPB_BT, pos + s, pos + eY * s_y, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
+               drawpic_skin(pos, "statusbar", eX * p * mySize_x + eY * mySize_y, HUD_Panel_GetProgressBarColor("nexball"), cvar("hud_progressbar_alpha"), DRAWFLAG_NORMAL);
        }
 
-       pos_x += 12; //horizontal margin to the picture
-       pos_y += 2; //vertical margin to the picture
+       pos_x += 0.5 * mySize_x - 0.5 * mySize_y; //horizontal margin to the picture
 
        if (stat_items & IT_KEY1)
-               drawpic_skin(pos, "nexball_carrying", '80 34 0', '1 1 1', 1, DRAWFLAG_NORMAL);
+               drawpic_skin(pos, "nexball_carrying", '1 1 0' * mySize_y, '1 1 1', 1, DRAWFLAG_NORMAL);
 }
 
-// Race/CTS HUD modicon section
+// Race/CTS HUD mod icons
 float crecordtime_prev; // last remembered crecordtime
 float crecordtime_change_time; // time when crecordtime last changed
 float srecordtime_prev; // last remembered srecordtime
 float srecordtime_change_time; // time when srecordtime last changed
-void CSQC_race_hud(void)
+
+float race_status_time;
+float race_status_prev;
+string race_status_name_prev;
+void HUD_Mod_Race(vector pos, vector mySize)
 {
        entity me;
        me = playerslots[player_localentnum - 1];
@@ -2945,9 +2922,6 @@ void CSQC_race_hud(void)
                return; // no records in the actual race
 
        drawfont = hud_bigfont;
-       vector pos;
-       pos_x = 2;
-       pos_y = vid_conheight - 48;
 
        // clientside personal record
        string rr;
@@ -2974,17 +2948,16 @@ void CSQC_race_hud(void)
        f = time - crecordtime_change_time;
 
        if (f > 1) {
-               drawstring(pos, "Personal best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
-               drawstring(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+               drawstring(pos, "Personal best ", '1 1 0' * 0.15 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+               drawstring(pos + eY * 0.2 * mySize_y, TIME_ENCODED_TOSTRING(t), '1 1 0' * 0.2 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
        } else {
-               drawstring(pos, "Personal best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
-               drawstring(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
-               drawstring_expanding(pos, "Personal best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
-               drawstring_expanding(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
+               drawstring(pos, "Personal best ", '1 1 0' * 0.15 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+               drawstring(pos + eY * 0.2 * mySize_y, TIME_ENCODED_TOSTRING(t), '1 1 0' * 0.2 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+               drawstring_expanding(pos, "Personal best ", '1 1 0' * 0.15 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
+               drawstring_expanding(pos + eY * 0.2 * mySize_y, TIME_ENCODED_TOSTRING(t), '1 1 0' * 0.2 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
        }
 
        // server record
-       pos_y += 26;
        t = race_server_record;
        if(t != srecordtime_prev) {
                srecordtime_prev = t;
@@ -2993,19 +2966,74 @@ void CSQC_race_hud(void)
        f = time - srecordtime_change_time;
 
        if (f > 1) {
-               drawstring(pos, "Server best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
-               drawstring(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+               drawstring(pos + eY * 0.5 * mySize_y, "Server best ", '1 1 0' * 0.15 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+               drawstring(pos + eY * 0.5 * mySize_y + eY * 0.2 * mySize_y, TIME_ENCODED_TOSTRING(t),'1 1 0' * 0.2 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
        } else {
-               drawstring(pos, "Server best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
-               drawstring(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
-               drawstring_expanding(pos, "Server best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
-               drawstring_expanding(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
+               drawstring(pos + eY * 0.5 * mySize_y, "Server best ", '1 1 0' * 0.15 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+               drawstring(pos + eY * 0.5 * mySize_y + eY * 0.2 * mySize_y, TIME_ENCODED_TOSTRING(t),'1 1 0' * 0.2 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+               drawstring_expanding(pos + eY * 0.5 * mySize_y, "Server best ", '1 1 0' * 0.15 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
+               drawstring_expanding(pos + eY * 0.5 * mySize_y + eY * 0.2 * mySize_y, TIME_ENCODED_TOSTRING(t),'1 1 0' * 0.2 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
+       }
+
+       if (race_status != race_status_prev || race_status_name != race_status_name_prev) {
+               race_status_time = time + 5;
+               race_status_prev = race_status;
+               if (race_status_name_prev)
+                       strunzone(race_status_name_prev);
+               race_status_name_prev = strzone(race_status_name);
+       }
+
+       pos_x += mySize_x/2;
+       // race "awards"
+       float a;
+       a = bound(0, race_status_time - time, 1);
+
+       string s;
+       s = textShortenToWidth(race_status_name, 120, '10 10 0', stringwidth_colors);
+
+       float rank;
+       if(race_status > 0)
+               rank = race_CheckName(race_status_name);
+       string rankname;
+       rankname = race_PlaceName(rank);
+
+       if(race_status == 0)
+               drawpic_skin(pos, "race_newfail", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+       else if(race_status == 1) {
+               drawpic_skin(pos, "race_newtime", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+               drawcolorcodedstring(pos + '40 80 0' - eX * stringwidth(s, TRUE, '5 0 0'), s, '10 10 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+               drawstring(pos + '40 20 0' - eX * stringwidth(rankname, TRUE, '7 0 0'), rankname, '14 14 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+       } else if(race_status == 2) {
+               if(race_status_name == GetPlayerName(player_localentnum -1) || !race_myrank || race_myrank < rank)
+                       drawpic_skin(pos, "race_newrankgreen", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+               else
+                       drawpic_skin(pos, "race_newrankyellow", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+               drawcolorcodedstring(pos + '40 80 0' - eX * stringwidth(s, TRUE, '5 0 0'), s, '10 10 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+               drawstring(pos + '40 20 0' - eX * stringwidth(rankname, TRUE, '7 0 0'), rankname, '14 14 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+       } else if(race_status == 3) {
+               drawpic_skin(pos, "race_newrecordserver", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+               drawcolorcodedstring(pos + '40 80 0' - eX * stringwidth(s, TRUE, '5 0 0'), s, '10 10 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+               drawstring(pos + '40 20 0' - eX * stringwidth(rankname, TRUE, '7 0 0'), rankname, '14 14 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+       }
+
+       if (race_status_time - time <= 0) {
+               race_status_prev = -1;
+               race_status = -1;
+               if(race_status_name)
+                       strunzone(race_status_name);
+               race_status_name = string_null;
+               if(race_status_name_prev)
+                       strunzone(race_status_name_prev);
+               race_status_name_prev = string_null;
        }
        drawfont = hud_font;
 }
 
+// TODO: idea: alpha fade in/out empty panels
 void HUD_ModIcons(void)
 {
+       if (gametype != GAME_KEYHUNT && gametype != GAME_CTF && gametype != GAME_NEXBALL && gametype != GAME_CTS && gametype != GAME_RACE && !hud_configure)
+               return;
        float id = 10;
        vector pos, mySize;
        pos = HUD_Panel_GetPos(id);
@@ -3019,6 +3047,16 @@ void HUD_ModIcons(void)
                pos += '1 1 0' * padding;
                mySize -= '2 2 0' * padding;
        }
+
+       // TODO... well make them work in a panel etc
+       if(gametype == GAME_KEYHUNT)
+               HUD_Mod_KH(pos, mySize);
+       else if(gametype == GAME_CTF || hud_configure)
+               HUD_Mod_CTF(pos, mySize);
+       else if(gametype == GAME_NEXBALL)
+               HUD_Mod_NexBall(pos, mySize);
+       else if(gametype == GAME_CTS || gametype == GAME_RACE)
+               HUD_Mod_Race(pos, mySize);
 }
 
 // Draw pressed keys (#11)
@@ -3157,9 +3195,9 @@ void HUD_Reset (void)
 {
        // reset gametype specific icons
        if(gametype == GAME_KEYHUNT)
-               CSQC_kh_hudreset();
+               HUD_Mod_KH_Reset();
        else if(gametype == GAME_CTF)
-               CSQC_ctf_hudreset();
+               HUD_Mod_CTF_Reset();
 }
 
 void HUD_Main (void)
@@ -3201,9 +3239,11 @@ void HUD_Main (void)
                        HUD_RaceTimer();
        if(HUD_Panel_CheckActive(9))
                HUD_VoteWindow();
-       // TODO hud'ify
        if(HUD_Panel_CheckActive(10))
-               if(spectatee_status > 0 || cvar("cl_showpressedkeys") >= 2 || hud_configure)
+               HUD_ModIcons();
+       // TODO hud'ify
+       if(HUD_Panel_CheckActive(11))
+               if(spectatee_status > 0 || cvar("hud_pressedkeys") >= 2 || hud_configure)
                        HUD_DrawPressedKeys();
 
        // TODO hud_'ify these
@@ -3211,15 +3251,4 @@ void HUD_Main (void)
                HUD_ShowSpeed();
        if (cvar("cl_showacceleration"))
                HUD_ShowAcceleration();
-
-       // TODO... well make them work in a panel etc
-       if(gametype == GAME_KEYHUNT)
-               CSQC_kh_hud();
-       else if(gametype == GAME_CTF)
-               CSQC_ctf_hud();
-       else if(gametype == GAME_NEXBALL)
-               CSQC_nb_hud();
-       else if(gametype == GAME_CTS || gametype == GAME_RACE)
-               CSQC_race_hud();
-       return;
 }