]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/hud.qc
Can only hope there's no mistakes in this
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud.qc
index c668e5666377b44dbb25981edd35e0e04dcd1a45..21dd0222b9ead829ba705088a04168d529f72479 100644 (file)
@@ -415,7 +415,7 @@ void HUD_Weapons(void)
        float i, f, a;
        float screen_ar, center_x = 0, center_y;
        float weapon_count, weapon_id;
-       float row, column, rows = 0, columns;
+       float row, column, rows = 0, columns = 0;
        float aspect = autocvar_hud_panel_weapons_aspect;
 
        float panel_weapon_accuracy;
@@ -433,7 +433,7 @@ void HUD_Weapons(void)
        float fadetime = max(0, autocvar_hud_panel_weapons_complainbubble_fadetime);
 
        vector weapon_pos, weapon_size = '0 0 0';
-       local noref vector old_panel_size; // fteqcc sucks
+       local noref vector max_panel_size; // fteqcc sucks
        vector color;
 
        // check to see if we want to continue
@@ -519,38 +519,41 @@ void HUD_Weapons(void)
                        return;
                }
 
-               old_panel_size = panel_size;
-               if(panel_bg_padding)
-                       old_panel_size -= '2 2 0' * panel_bg_padding;
+               max_panel_size = panel_size - '2 2 0' * panel_bg_padding;
 
-               // first find values for the standard table (with all the weapons)
-               rows = old_panel_size_y/old_panel_size_x;
-               rows = bound(1, floor((sqrt(4 * aspect * rows * WEP_COUNT + rows * rows) + rows + 0.5) / 2), WEP_COUNT);
-               columns = ceil(WEP_COUNT/rows);
-               weapon_size_x = old_panel_size_x / columns;
-               weapon_size_y = old_panel_size_y / rows;
-
-               // change table values to include only the owned weapons
-               float columns_save = columns;
-               if(weapon_count <= rows)
+               // calculate distribution and size of table cells
+               if(max_panel_size_x > max_panel_size_y)
                {
-                       rows = weapon_count;
-                       columns = 1;
+                       while(weapon_count > columns * rows)
+                       {
+                               ++rows;
+                               columns = ceil(max_panel_size_x / (max_panel_size_y / rows * aspect));
+                       }
+
+                       weapon_size_x = max_panel_size_x / columns;
+                       weapon_size_y = max_panel_size_y / rows;
+                       columns = ceil(weapon_count / rows);
                }
                else
-                       columns = ceil(weapon_count / rows);
+               {
+                       while(weapon_count > columns * rows)
+                       {
+                               ++columns;
+                               rows = ceil(max_panel_size_y / (max_panel_size_x / columns / aspect));
+                       }
 
-               // enlarge weapon_size to match desired aspect ratio in order to capitalize on panel space
-               if(columns < columns_save)
-                       weapon_size_x = min(old_panel_size_x / columns, aspect * weapon_size_y);
+                       weapon_size_x = max_panel_size_x / columns;
+                       weapon_size_y = max_panel_size_y / rows;
+                       rows = ceil(weapon_count / columns);
+               }
 
                // reduce size of the panel
                panel_size_x = columns * weapon_size_x;
                panel_size_y = rows * weapon_size_y;
-               panel_pos_x += (old_panel_size_x - panel_size_x) / 2;
-               panel_pos_y += (old_panel_size_y - panel_size_y) / 2;
-               if(panel_bg_padding)
-                       panel_size += '2 2 0' * panel_bg_padding;
+               panel_pos_x += (max_panel_size_x - panel_size_x) / 2;
+               panel_pos_y += (max_panel_size_y - panel_size_y) / 2;
+
+               panel_size += '2 2 0' * panel_bg_padding;
        }
        else
                weapon_count = WEP_COUNT;
@@ -689,7 +692,9 @@ void HUD_Weapons(void)
        if(autocvar_hud_panel_weapons_accuracy)
                Accuracy_LoadColors();
 
+       // 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);
        for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
        {
                // retrieve information about the current weapon to be drawn
@@ -734,15 +739,15 @@ void HUD_Weapons(void)
                        switch(autocvar_hud_panel_weapons_label)
                        {
                                case 1: // weapon number
-                                       drawstring(weapon_pos, ftos(weapon_id), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+                                       drawstring(weapon_pos, ftos(weapon_id), label_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                                        break;
 
                                case 2: // bind
-                                       drawstring(weapon_pos, getcommandkey(ftos(weapon_id), strcat("weapon_group_", ftos(weapon_id))), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+                                       drawstring(weapon_pos, getcommandkey(ftos(weapon_id), strcat("weapon_group_", ftos(weapon_id))), label_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                                        break;
 
                                case 3: // weapon name
-                                       drawstring(weapon_pos, strtolower(self.message), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+                                       drawstring(weapon_pos, strtolower(self.message), label_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                                        break;
 
                                default: // nothing
@@ -895,6 +900,13 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent,
        else
                ammo = getstati(GetAmmoStat(ammoType));
 
+       if(!isCurrent)
+       {
+               float scale = bound(0, autocvar_hud_panel_ammo_noncurrent_scale, 1);
+               myPos = myPos + (mySize - mySize * scale) * 0.5;
+               mySize = mySize * scale;
+       }
+
        vector iconPos, textPos;
        if(autocvar_hud_panel_ammo_iconalign)
        {
@@ -912,11 +924,11 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent,
        vector iconColor = isShadowed ? '0 0 0' : '1 1 1';
        vector textColor;
        if(isInfinite)
-               textColor = '0 0.5 0.75';
+               textColor = '0.2 0.95 0';
        else if(isShadowed)
                textColor = '0 0 0';
        else if(ammo < 10)
-               textColor = '0.7 0 0';
+               textColor = '0.8 0.04 0';
        else
                textColor = '1 1 1';
 
@@ -924,9 +936,11 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent,
        if(isCurrent)
                alpha = panel_fg_alpha;
        else if(isShadowed)
-               alpha = panel_fg_alpha * 0.7 * 0.5;
+               alpha = panel_fg_alpha * bound(0, autocvar_hud_panel_ammo_noncurrent_alpha, 1) * 0.5;
        else
-               alpha = panel_fg_alpha * 0.7;
+               alpha = panel_fg_alpha * bound(0, autocvar_hud_panel_ammo_noncurrent_alpha, 1);
+
+       string text = isInfinite ? "\xE2\x88\x9E" : ftos(ammo); // Use infinity symbol (U+221E)
 
        // Draw item
 
@@ -937,7 +951,7 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent,
                HUD_Panel_DrawProgressBar(myPos + eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x, mySize - eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x, autocvar_hud_panel_ammo_progressbar_name, ammo/autocvar_hud_panel_ammo_maxammo, 0, 0, textColor, autocvar_hud_progressbar_alpha * alpha, DRAWFLAG_NORMAL);
 
        if(autocvar_hud_panel_ammo_text)
-               drawstring_aspect(textPos, ftos(ammo), eX * (2/3) * mySize_x + eY * mySize_y, textColor, alpha, DRAWFLAG_NORMAL);
+               drawstring_aspect(textPos, text, eX * (2/3) * mySize_x + eY * mySize_y, textColor, alpha, DRAWFLAG_NORMAL);
 
        drawpic_aspect_skin(iconPos, GetAmmoPicture(ammoType), '1 1 0' * mySize_y, iconColor, alpha, DRAWFLAG_NORMAL);
 }
@@ -2657,7 +2671,7 @@ void HUD_Vote(void)
 
 float mod_active; // is there any active mod icon?
 
-void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, float layout, float i)
+void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, float i)
 {
        float stat;
        string pic;
@@ -2719,7 +2733,7 @@ void HUD_Mod_CA(vector myPos, vector mySize)
 {
        mod_active = 1; // required in each mod function that always shows something
 
-       float layout;
+       int layout;
        if(gametype == MAPINFO_TYPE_CA)
                layout = autocvar_hud_panel_modicons_ca_layout;
        else //if(gametype == MAPINFO_TYPE_FREEZETAG)
@@ -2901,148 +2915,132 @@ void HUD_Mod_CTF(vector pos, vector mySize)
 }
 
 // Keyhunt HUD modicon section
-float kh_runheretime;
-
-void HUD_Mod_KH_Reset(void)
-{
-       kh_runheretime = 0;
-}
+vector KH_SLOTS[4];
 
 void HUD_Mod_KH(vector pos, vector mySize)
 {
        mod_active = 1; // keyhunt should never hide the mod icons panel
-       float kh_keys;
-       float keyteam;
-       float a, aa;
-       vector p = '0 0 0', pa, kh_size = '0 0 0', kh_asize = '0 0 0';
 
-       kh_keys = getstati(STAT_KH_KEYS);
+       // Read current state
 
-       p_x = pos_x;
-       if(mySize_x > mySize_y)
-       {
-               p_y = pos_y + 0.25 * mySize_y;
-               pa = p - eY * 0.25 * mySize_y;
+       float state = getstati(STAT_KH_KEYS);
+       float i, key_state;
+       float all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
+       all_keys = team1_keys = team2_keys = team3_keys = team4_keys = dropped_keys = carrying_keys = 0;
 
-               kh_size_x = mySize_x * 0.25;
-               kh_size_y = 0.75 * mySize_y;
-               kh_asize_x = mySize_x * 0.25;
-               kh_asize_y = mySize_y * 0.25;
-       }
-       else
+       for(i = 0; i < 4; ++i)
        {
-               p_y = pos_y + 0.125 * mySize_y;
-               pa = p - eY * 0.125 * mySize_y;
+               key_state = (bitshift(state, i * -5) & 31) - 1;
 
-               kh_size_x = mySize_x * 0.5;
-               kh_size_y = 0.375 * mySize_y;
-               kh_asize_x = mySize_x * 0.5;
-               kh_asize_y = mySize_y * 0.125;
-       }
+               if(key_state == -1)
+                       continue;
 
-       float i, key;
+               if(key_state == 30)
+               {
+                       ++carrying_keys;
+                       key_state = myteam;
+               }
 
-       float keycount;
-       keycount = 0;
-       for(i = 0; i < 4; ++i)
-       {
-               key = floor(kh_keys / pow(32, i)) & 31;
-               keyteam = key - 1;
-               if(keyteam == 30 && keycount <= 4)
-                       keycount += 4;
-               if(keyteam == myteam || keyteam == -1 || keyteam == 30)
-                       keycount += 1;
+               switch(key_state)
+               {
+                       case NUM_TEAM_1: ++team1_keys; break;
+                       case NUM_TEAM_2: ++team2_keys; break;
+                       case NUM_TEAM_3: ++team3_keys; break;
+                       case NUM_TEAM_4: ++team4_keys; break;
+                       case 29: ++dropped_keys; break;
+               }
+
+               ++all_keys;
        }
 
-       // this yields 8 exactly if "RUN HERE" shows
+       // Calculate slot measurements
+
+       vector slot_size;
 
-       if(keycount == 8)
+       if(all_keys == 4 && mySize_x * 0.5 < mySize_y && mySize_y * 0.5 < mySize_x)
        {
-               if(!kh_runheretime)
-                       kh_runheretime = time;
-               pa_y -= fabs(sin((time - kh_runheretime) * 3.5)) * 6; // make the arrows jump in case of RUN HERE
+               // Quadratic arrangement
+               slot_size = eX * mySize_x * 0.5 + eY * mySize_y * 0.5;
+               KH_SLOTS[0] = pos;
+               KH_SLOTS[1] = pos + eX * slot_size_x;
+               KH_SLOTS[2] = pos + eY * slot_size_y;
+               KH_SLOTS[3] = pos + eX * slot_size_x + eY * slot_size_y;
        }
        else
-               kh_runheretime = 0;
-
-       for(i = 0; i < 4; ++i)
        {
-               key = floor(kh_keys / pow(32, i)) & 31;
-               keyteam = key - 1;
-               switch(keyteam)
+               if(mySize_x > mySize_y)
                {
-                       case 30: // my key
-                               keyteam = myteam;
-                               a = 1;
-                               aa = 1;
-                               break;
-                       case -1: // no key
-                               a = 0;
-                               aa = 0;
-                               break;
-                       default: // owned or dropped
-                               a = 0.2;
-                               aa = 0.5;
-                               break;
+                       // Horizontal arrangement
+                       slot_size = eX * mySize_x / all_keys + eY * mySize_y;
+                       for(i = 0; i < all_keys; ++i)
+                               KH_SLOTS[i] = pos + eX * slot_size_x * i;
                }
-               a = a * panel_fg_alpha;
-               aa = aa * panel_fg_alpha;
-               if(a > 0)
+               else
                {
-                       switch(keyteam)
-                       {
-                               case NUM_TEAM_1:
-                                       drawpic_aspect_skin(pa, "kh_redarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% theAlpha key
-                                       break;
-                               case NUM_TEAM_2:
-                                       drawpic_aspect_skin(pa, "kh_bluearrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% theAlpha key
-                                       break;
-                               case NUM_TEAM_3:
-                                       drawpic_aspect_skin(pa, "kh_yellowarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% theAlpha key
-                                       break;
-                               case NUM_TEAM_4:
-                                       drawpic_aspect_skin(pa, "kh_pinkarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL);  // show 30% theAlpha key
-                                       break;
-                               default:
-                                       break;
-                       }
-                       switch(i) // YAY! switch(i) inside a for loop for i. DailyWTF, here we come!
-                       {
-                               case 0:
-                                       drawpic_aspect_skin(p, "kh_red", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% theAlpha key
-                                       break;
-                               case 1:
-                                       drawpic_aspect_skin(p, "kh_blue", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% theAlpha key
-                                       break;
-                               case 2:
-                                       drawpic_aspect_skin(p, "kh_yellow", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% theAlpha key
-                                       break;
-                               case 3:
-                                       drawpic_aspect_skin(p, "kh_pink", kh_size, '1 1 1', a, DRAWFLAG_NORMAL);  // show 30% theAlpha key
-                                       break;
-                       }
+                       // Vertical arrangement
+                       slot_size = eX * mySize_x + eY * mySize_y / all_keys;
+                       for(i = 0; i < all_keys; ++i)
+                               KH_SLOTS[i] = pos + eY * slot_size_y * i;
                }
-               if(mySize_x > mySize_y)
+       }
+
+       // Make icons blink in case of RUN HERE
+
+       float blink = 0.6 + sin(2*M_PI*time) / 2.5; // Oscillate between 0.2 and 1
+       float alpha;
+       alpha = 1;
+
+       if(carrying_keys)
+               switch(myteam)
+               {
+                       case NUM_TEAM_1: if(team1_keys == all_keys) alpha = blink; break;
+                       case NUM_TEAM_2: if(team2_keys == all_keys) alpha = blink; break;
+                       case NUM_TEAM_3: if(team3_keys == all_keys) alpha = blink; break;
+                       case NUM_TEAM_4: if(team4_keys == all_keys) alpha = blink; break;
+               }
+
+       // Draw icons
+
+       i = 0;
+
+       while(team1_keys--)
+               if(myteam == NUM_TEAM_1 && carrying_keys)
                {
-                       p_x += 0.25 * mySize_x;
-                       pa_x += 0.25 * mySize_x;
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+                       --carrying_keys;
                }
                else
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+       while(team2_keys--)
+               if(myteam == NUM_TEAM_2 && carrying_keys)
                {
-                       if(i == 1)
-                       {
-                               p_y = pos_y + 0.625 * mySize_y;
-                               pa_y = pos_y + 0.5 * mySize_y;
-                               p_x = pos_x;
-                               pa_x = pos_x;
-                       }
-                       else
-                       {
-                               p_x += 0.5 * mySize_x;
-                               pa_x += 0.5 * mySize_x;
-                       }
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+                       --carrying_keys;
                }
-       }
+               else
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+       while(team3_keys--)
+               if(myteam == NUM_TEAM_3 && carrying_keys)
+               {
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+                       --carrying_keys;
+               }
+               else
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+       while(team4_keys--)
+               if(myteam == NUM_TEAM_4 && carrying_keys)
+               {
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+                       --carrying_keys;
+               }
+               else
+                       drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+       while(dropped_keys--)
+               drawpic_aspect_skin(KH_SLOTS[i++], "kh_dropped", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
 }
 
 // Keepaway HUD mod icon
@@ -3267,7 +3265,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
        }
 }
 
-void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, float layout, float i)
+void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, float i)
 {
        float stat, pps_ratio;
        string pic;
@@ -3340,7 +3338,7 @@ void HUD_Mod_Dom(vector myPos, vector mySize)
 {
        mod_active = 1; // required in each mod function that always shows something
 
-       float layout = autocvar_hud_panel_modicons_dom_layout;
+       int layout = autocvar_hud_panel_modicons_dom_layout;
        float rows, columns, aspect_ratio;
        rows = mySize_y/mySize_x;
        aspect_ratio = (layout) ? 3 : 1;
@@ -4473,9 +4471,7 @@ Main HUD system
 void HUD_Reset (void)
 {
        // reset gametype specific icons
-       if(gametype == MAPINFO_TYPE_KEYHUNT)
-               HUD_Mod_KH_Reset();
-       else if(gametype == MAPINFO_TYPE_CTF)
+       if(gametype == MAPINFO_TYPE_CTF)
                HUD_Mod_CTF_Reset();
 }