]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/hud.qc
Merge branch 'master' into Mario/overkill
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud.qc
index 365496e7767d860ede359ca63441752bc2422a9f..bb5eb4a68f534081953aa7d860c69602659d7fa3 100644 (file)
@@ -142,16 +142,16 @@ float stringwidth_nocolors(string s, vector theSize)
        return stringwidth(s, FALSE, theSize);
 }
 
-void drawstringright(vector position, string text, vector scale, vector rgb, float theAlpha, float flag)
+void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, float flag)
 {
-       position_x -= 2 / 3 * strlen(text) * scale_x;
-       drawstring(position, text, scale, rgb, theAlpha, flag);
+       position_x -= 2 / 3 * strlen(text) * theScale_x;
+       drawstring(position, text, theScale, rgb, theAlpha, flag);
 }
 
-void drawstringcenter(vector position, string text, vector scale, vector rgb, float theAlpha, float flag)
+void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, float flag)
 {
-       position_x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * scale_x);
-       drawstring(position, text, scale, rgb, theAlpha, 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
@@ -242,7 +242,7 @@ float GetPlayerColorForce(float i)
 
 float GetPlayerColor(float i)
 {
-       if not(playerslots[i].gotscores) // unconnected
+       if(!playerslots[i].gotscores) // unconnected
                return NUM_SPECTATOR;
        else if(stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR)
                return NUM_SPECTATOR;
@@ -447,8 +447,7 @@ float GetAmmoTypeForWep(float i)
 void HUD_Weapons(void)
 {
        // declarations
-       WEPSET_DECLARE_A(weapons_stat);
-       WEPSET_COPY_AS(weapons_stat);
+       WepSet weapons_stat = WepSet_GetFromStat();
        float i, f, a;
        float screen_ar, center_x = 0, center_y;
        float weapon_count, weapon_id;
@@ -531,9 +530,9 @@ void HUD_Weapons(void)
        {
                if(autocvar__hud_configure)
                {
-                       if (WEPSET_EMPTY_A(weapons_stat))
+                       if (!weapons_stat)
                                for(i = WEP_FIRST; i <= WEP_LAST; i += floor((WEP_LAST-WEP_FIRST)/5))
-                                       WEPSET_OR_AW(weapons_stat, i);
+                                       weapons_stat |= WepSet_FromWeapon(i);
 
                        if(menu_enabled != 2)
                                HUD_Panel_DrawBg(1); // also draw the bg of the entire panel
@@ -542,7 +541,7 @@ void HUD_Weapons(void)
                // do we own this weapon?
                weapon_count = 0;
                for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
-                       if(WEPSET_CONTAINS_AW(weapons_stat, weaponorder[i].weapon))
+                       if(weapons_stat & WepSet_FromWeapon(weaponorder[i].weapon))
                                ++weapon_count;
 
                // add it anyway if weaponcomplain is shown
@@ -568,7 +567,7 @@ void HUD_Weapons(void)
                weapon_size_y = old_panel_size_y / rows;
 
                // change table values to include only the owned weapons
-               // weapon_size won't be changed
+               float columns_save = columns;
                if(weapon_count <= rows)
                {
                        rows = weapon_count;
@@ -577,6 +576,10 @@ void HUD_Weapons(void)
                else
                        columns = ceil(weapon_count / rows);
 
+               // 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);
+
                // reduce size of the panel
                panel_size_x = columns * weapon_size_x;
                panel_size_y = rows * weapon_size_y;
@@ -734,12 +737,12 @@ void HUD_Weapons(void)
 
                // skip this weapon if we don't own it (and onlyowned is enabled)-- or if weapons_complainbubble is showing for this weapon
                if(autocvar_hud_panel_weapons_onlyowned)
-               if not(WEPSET_CONTAINS_AW(weapons_stat, self.weapon) || (self.weapon == complain_weapon))
+               if (!((weapons_stat & WepSet_FromWeapon(self.weapon)) || (self.weapon == complain_weapon)))
                        continue;
 
                // figure out the drawing position of weapon
-               weapon_pos = (panel_pos 
-                       + eX * column * weapon_size_x 
+               weapon_pos = (panel_pos
+                       + eX * column * weapon_size_x
                        + eY * row * weapon_size_y);
 
                // draw background behind currently selected weapon
@@ -758,7 +761,7 @@ void HUD_Weapons(void)
                }
 
                // drawing all the weapon items
-               if(WEPSET_CONTAINS_AW(weapons_stat, self.weapon))
+               if(weapons_stat & WepSet_FromWeapon(self.weapon))
                {
                        // draw the weapon image
                        drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
@@ -1133,7 +1136,7 @@ void HUD_Powerups(void)
        {
                if(!autocvar_hud_panel_powerups) return;
                if(spectatee_status == -1) return;
-               if not(getstati(STAT_ITEMS, 0, 24) & (IT_STRENGTH | IT_INVINCIBLE | IT_SUPERWEAPON)) return;
+               if(!(getstati(STAT_ITEMS, 0, 24) & (IT_STRENGTH | IT_INVINCIBLE | IT_SUPERWEAPON))) return;
                if (getstati(STAT_HEALTH) <= 0) return;
 
                strength_time = bound(0, getstatf(STAT_STRENGTH_FINISHED) - time, 99);
@@ -1405,7 +1408,7 @@ void HUD_HealthArmor(void)
        if(autocvar_hud_panel_healtharmor == 2) // combined health and armor display
        {
                vector v;
-               v = healtharmor_maxdamage(health, armor, armorblockpercent);
+               v = healtharmor_maxdamage(health, armor, armorblockpercent, DEATH_WEAPON);
 
                float x;
                x = floor(v_x + 1);
@@ -1522,7 +1525,7 @@ void HUD_HealthArmor(void)
                                        {
                                                float BLINK_FACTOR = 0.15;
                                                float BLINK_BASE = 0.85;
-                                               float BLINK_FREQ = 9; 
+                                               float BLINK_FREQ = 9;
                                                pain_health_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
                                        }
                                }
@@ -1640,7 +1643,7 @@ void HUD_Notify(void)
        float entries, height;
        entries = bound(1, floor(KN_MAX_ENTRIES * mySize_y/mySize_x), KN_MAX_ENTRIES);
        height = mySize_y/entries;
-       
+
        vector fontsize;
        float fontheight = height * autocvar_hud_panel_notify_fontsize;
        fontsize = '0.5 0.5 0' * fontheight;
@@ -1702,7 +1705,7 @@ void HUD_Notify(void)
                        {
                                break;
                        }
-                       
+
                        attacker = notify_attackers[j];
                        victim = notify_victims[j];
                        icon = notify_icon[j];
@@ -1825,6 +1828,11 @@ void HUD_Radar(void)
                {
                        if (autocvar_hud_panel_radar == 0) return;
                        if (autocvar_hud_panel_radar != 2 && !teamplay) return;
+                       if(radar_panel_modified)
+                       {
+                               panel.update_time = time; // forces reload of panel attributes
+                               radar_panel_modified = false;
+                       }
                }
        }
 
@@ -1844,6 +1852,8 @@ void HUD_Radar(void)
                panel_bg = strcat(hud_skin_path, "/border_default"); // always use the default border when maximized
                if(precache_pic(panel_bg) == "")
                        panel_bg = "gfx/hud/default/border_default"; // fallback
+               if(!radar_panel_modified && panel_bg != panel.current_panel_bg)
+                       radar_panel_modified = true;
                if(panel.current_panel_bg)
                        strunzone(panel.current_panel_bg);
                panel.current_panel_bg = strzone(panel_bg);
@@ -1864,7 +1874,7 @@ void HUD_Radar(void)
                                f = 1;
                                break;
                }
-               
+
                switch(hud_panel_radar_maximized_rotation)
                {
                        case 0:
@@ -1893,7 +1903,7 @@ void HUD_Radar(void)
                                f = 1;
                                break;
                }
-               
+
                switch(hud_panel_radar_rotation)
                {
                        case 0:
@@ -2273,7 +2283,7 @@ void HUD_Score(void)
                        score = tm.(teamscores[ts_primary]);
                        if(autocvar__hud_configure)
                                score = 123;
-                       
+
                        if (score > max_fragcount)
                                max_fragcount = score;
 
@@ -2721,7 +2731,7 @@ void HUD_Mod_CTF(vector pos, vector mySize)
        stat_items = getstati(STAT_ITEMS, 0, 24);
        redflag = (stat_items/IT_RED_FLAG_TAKEN) & 3;
        blueflag = (stat_items/IT_BLUE_FLAG_TAKEN) & 3;
-       
+
        if(redflag || blueflag)
                mod_active = 1;
        else
@@ -2998,29 +3008,29 @@ void HUD_Mod_KH(vector pos, vector mySize)
 float kaball_prevstatus; // last remembered status
 float kaball_statuschange_time; // time when the status changed
 
-// we don't need to reset for keepaway since it immediately 
+// we don't need to reset for keepaway since it immediately
 // autocorrects prevstatus as to if the player has the ball or not
 
 void HUD_Mod_Keepaway(vector pos, vector mySize)
 {
        mod_active = 1; // keepaway should always show the mod HUD
-       
+
        float BLINK_FACTOR = 0.15;
        float BLINK_BASE = 0.85;
-       float BLINK_FREQ = 5; 
+       float BLINK_FREQ = 5;
        float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
-       
+
        float stat_items = getstati(STAT_ITEMS, 0, 24);
        float kaball = (stat_items/IT_KEY1) & 1;
-       
+
        if(kaball != kaball_prevstatus)
        {
                kaball_statuschange_time = time;
                kaball_prevstatus = kaball;
        }
-       
+
        vector kaball_pos, kaball_size;
-       
+
        if(mySize_x > mySize_y) {
                kaball_pos = pos + eX * 0.25 * mySize_x;
                kaball_size = eX * 0.5 * mySize_x + eY * mySize_y;
@@ -3028,13 +3038,13 @@ void HUD_Mod_Keepaway(vector pos, vector mySize)
                kaball_pos = pos + eY * 0.25 * mySize_y;
                kaball_size = eY * 0.5 * mySize_y + eX * mySize_x;
        }
-       
+
        float kaball_statuschange_elapsedtime = time - kaball_statuschange_time;
        float f = bound(0, kaball_statuschange_elapsedtime*2, 1);
-       
+
        if(kaball_prevstatus && f < 1)
                drawpic_aspect_skin_expanding(kaball_pos, "keepawayball_carrying", kaball_size, '1 1 1', panel_fg_alpha * kaball_alpha, DRAWFLAG_NORMAL, f);
-       
+
        if(kaball)
                drawpic_aspect_skin(pos, "keepawayball_carrying", eX * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha * kaball_alpha * f, DRAWFLAG_NORMAL);
 }
@@ -3087,7 +3097,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
        float f; // yet another function has this
        score = me.(scores[ps_primary]);
 
-       if not((scores_flags[ps_primary] & SFL_TIME) && !teamplay) // race/cts record display on HUD
+       if(!(scores_flags[ps_primary] & SFL_TIME) || teamplay) // race/cts record display on HUD
                return; // no records in the actual race
 
        // clientside personal record
@@ -3103,7 +3113,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
                if(autocvar_cl_autodemo_delete_keeprecords)
                {
                        f = autocvar_cl_autodemo_delete;
-                       f &~= 1;
+                       f &= ~1;
                        cvar_set("cl_autodemo_delete", ftos(f)); // don't delete demo with new record!
                }
        }
@@ -3452,7 +3462,14 @@ void HUD_Chat(void)
                        return;
                }
                if(autocvar__con_chat_maximized)
+               {
                        if(!hud_draw_maximized) return;
+               }
+               else if(chat_panel_modified)
+               {
+                       panel.update_time = time; // forces reload of panel attributes
+                       chat_panel_modified = false;
+               }
        }
 
        HUD_Panel_UpdateCvars();
@@ -3470,6 +3487,7 @@ void HUD_Chat(void)
                        if(panel.current_panel_bg)
                                strunzone(panel.current_panel_bg);
                        panel.current_panel_bg = strzone(panel_bg);
+                       chat_panel_modified = true;
                }
                panel_bg_alpha = max(0.75, panel_bg_alpha); // force an theAlpha of at least 0.75
        }
@@ -3548,7 +3566,7 @@ void HUD_EngineInfo(void)
                frametimeavg = (frametimeavg + frametimeavg1 + frametimeavg2 + currentframetime)/4; // average three frametimes into framecounter for slightly more stable fps readings :P
                frametimeavg2 = frametimeavg1;
                frametimeavg1 = frametimeavg;
-               
+
                float weight;
                weight = cvar("hud_panel_engineinfo_framecounter_exponentialmovingaverage_new_weight");
                if(currentframetime > 0.0001) // filter out insane values which sometimes seem to occur and throw off the average? If you are getting 10,000 fps or more, then you don't need a framerate counter.
@@ -3625,7 +3643,7 @@ void HUD_InfoMessages(void)
 
        vector fontsize;
        fontsize = '0.20 0.20 0' * mySize_y;
-       
+
        float a;
        a = panel_fg_alpha;
 
@@ -3660,9 +3678,7 @@ void HUD_InfoMessages(void)
                        s = sprintf(_("^1Press ^3%s^1 for gamemode info"), getcommandkey("server info", "+show_info"));
                        drawInfoMessage(s)
 
-                       if(gametype == MAPINFO_TYPE_ARENA)
-                               s = _("^1Wait for your turn to join");
-                       else if(gametype == MAPINFO_TYPE_LMS)
+                       if(gametype == MAPINFO_TYPE_LMS)
                        {
                                entity sk;
                                sk = playerslots[player_localnum];
@@ -3751,7 +3767,7 @@ void HUD_InfoMessages(void)
                        }
                }
        }
-       else 
+       else
        {
                s = _("^7Press ^3ESC ^7to show HUD options.");
                drawInfoMessage(s)
@@ -3826,7 +3842,7 @@ void HUD_Physics(void)
                        conversion_factor = 0.0254 * 1.943844492; // 1 m/s = 1.943844492 knots, because 1 knot = 1.852 km/h
                        break;
        }
-       
+
        vector vel = (csqcplayer ? csqcplayer.velocity : pmove_vel);
 
        float max_speed = floor( autocvar_hud_panel_physics_speed_max * conversion_factor + 0.5 );
@@ -3849,9 +3865,9 @@ void HUD_Physics(void)
                        acceleration = (vlen(vel) - vlen(acc_prevspeed));
                else
                        acceleration = (vlen(vel - '0 0 1' * vel_z) - vlen(acc_prevspeed - '0 0 1' * acc_prevspeed_z));
-               
+
                acceleration = acceleration * (1 / max(0.0001, f)) * (0.0254 / 9.80665);
-               
+
                acc_prevspeed = vel;
                acc_prevtime = time;
 
@@ -4047,7 +4063,7 @@ float centerprint_showing;
 
 void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num)
 {
-       //print(sprintf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num));
+       //printf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num);
        float i, j;
 
        if(strMessage == "" && new_id == 0)
@@ -4158,7 +4174,7 @@ void HUD_CenterPrint (void)
                        float r;
                        r = random();
                        if (r > 0.9)
-                               centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: %d"), 1, 10);
+                               centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: ^COUNT"), 1, 10);
                        else if (r > 0.8)
                                centerprint_generic(0, sprintf("^1Multiline message at time %s that\n^1lasts longer than normal", seconds_tostring(time)), 20, 0);
                        else
@@ -4184,9 +4200,9 @@ void HUD_CenterPrint (void)
                if (scoreboard_bottom >= 0.96 * vid_conheight)
                        return;
                vector target_pos;
-               
+
                target_pos = eY * scoreboard_bottom + eX * 0.5 * (vid_conwidth - panel_size_x);
-               
+
                if(target_pos_y > panel_pos_y)
                {
                        panel_pos = panel_pos + (target_pos - panel_pos) * sqrt(scoreboard_fade_alpha);
@@ -4218,8 +4234,7 @@ void HUD_CenterPrint (void)
        float a, sz, align, current_msg_pos_y = 0, msg_size;
        vector pos;
        string ts;
-
-       n = -1; // if no msg will be displayed, n stays -1
+       float all_messages_expired = TRUE;
 
        pos = panel_pos;
        if (autocvar_hud_panel_centerprint_flip)
@@ -4242,31 +4257,36 @@ void HUD_CenterPrint (void)
                                continue;
                }
 
+               all_messages_expired = FALSE;
 
-               // fade the centerprint_hud in/out 
-               if(centerprint_time[j] < 0)
-                       a = bound(0, (time - centerprint_expire_time[j]) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1);
-               else if(centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time)
-                       a = bound(0, (time - (centerprint_expire_time[j] - centerprint_time[j])) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1);
-               else if(centerprint_expire_time[j] > time)
+               // fade the centerprint_hud in/out
+               if(centerprint_time[j] < 0)  // Expired but forced. Expire time is the fade-in time.
+                       a = (time - centerprint_expire_time[j]) / max(0.0001, autocvar_hud_panel_centerprint_fade_in);
+               else if(centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time)  // Regularily printed. Not fading out yet.
+                       a = (time - (centerprint_expire_time[j] - centerprint_time[j])) / max(0.0001, autocvar_hud_panel_centerprint_fade_in);
+               else // Expiring soon, so fade it out.
                        a = (centerprint_expire_time[j] - time) / max(0.0001, autocvar_hud_panel_centerprint_fade_out);
-               else
-                       a = 0;
-               
+
+               if (a <= 0.5/255.0)  // Guaranteed invisible - don't show.
+                       continue;
+               if (a > 1)
+                       a = 1;
+
                // set the size from fading in/out before subsequent fading
-               sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize); 
-               
+               sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize);
+
                // also fade it based on positioning
                if(autocvar_hud_panel_centerprint_fade_subsequent)
                {
                        a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha, (1 - (g / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passone))), 1); // pass one: all messages after the first have half theAlpha
                        a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha, (1 - (g / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passtwo))), 1); // pass two: after that, gradually lower theAlpha even more for each message
                }
-               
+               a *= panel_fg_alpha;
+
                // finally set the size based on the new theAlpha from subsequent fading
-               sz = sz * (autocvar_hud_panel_centerprint_fade_subsequent_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_subsequent_minfontsize)); 
+               sz = sz * (autocvar_hud_panel_centerprint_fade_subsequent_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_subsequent_minfontsize));
                drawfontscale = sz * '1 1 0';
-               
+
                if (centerprint_countdown_num[j])
                        n = tokenizebyseparator(strreplace("^COUNT", count_seconds(centerprint_countdown_num[j]), centerprint_messages[j]), "\n");
                else
@@ -4301,7 +4321,8 @@ void HUD_CenterPrint (void)
                                {
                                        if (align)
                                                pos_x = panel_pos_x + (panel_size_x - stringwidth(ts, TRUE, fontsize)) * align;
-                                       drawcolorcodedstring(pos + eY * 0.5 * (1 - sz) * fontsize_y, ts, fontsize, a * panel_fg_alpha, DRAWFLAG_NORMAL);
+                                       if (a > 0.5/255.0)  // Otherwise guaranteed invisible - don't show. This is checked a second time after some multiplications with other factors were done so temporary changes of these cannot cause flicker.
+                                               drawcolorcodedstring(pos + eY * 0.5 * (1 - sz) * fontsize_y, ts, fontsize, a, DRAWFLAG_NORMAL);
                                        pos_y += fontsize_y;
                                }
                                else
@@ -4309,15 +4330,15 @@ void HUD_CenterPrint (void)
                        }
                }
 
-               ++g; // move next position number up 
-               
+               ++g; // move next position number up
+
                msg_size = pos_y - msg_size;
                if (autocvar_hud_panel_centerprint_flip)
                {
                        pos_y = current_msg_pos_y - CENTERPRINT_SPACING * fontsize_y;
                        if (a < 1 && centerprint_msgID[j] == 0) // messages with id can be replaced just after they are faded out, so never move over them the next messages
                                pos_y += (msg_size + CENTERPRINT_SPACING * fontsize_y) * (1 - sqrt(sz));
-                               
+
                        if (pos_y < panel_pos_y) // check if the next message can be shown
                        {
                                drawfontscale = '1 1 0';
@@ -4329,7 +4350,7 @@ void HUD_CenterPrint (void)
                        pos_y += CENTERPRINT_SPACING * fontsize_y;
                        if (a < 1 && centerprint_msgID[j] == 0) // messages with id can be replaced just after they are faded out, so never move over them the next messages
                                pos_y -= (msg_size + CENTERPRINT_SPACING * fontsize_y) * (1 - sqrt(sz));
-                               
+
                        if(pos_y > panel_pos_y + panel_size_y - fontsize_y) // check if the next message can be shown
                        {
                                drawfontscale = '1 1 0';
@@ -4338,7 +4359,7 @@ void HUD_CenterPrint (void)
                }
        }
        drawfontscale = '1 1 0';
-       if (n == -1)
+       if (all_messages_expired)
        {
                centerprint_showing = FALSE;
                reset_centerprint_messages();