X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fclient%2Fhud.qc;h=3d3fe93cc41ce8ba33a5116c9cde740b1af9c9e3;hb=93d9ec19ea9e08ad5d888351e1b6ef9de7364050;hp=6b11719567d055e4234fd81ddb8344f3ba4316e8;hpb=36f4b513fd7eac9b2dc37d393cebf3b7d98ac9af;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc index 6b1171956..3d3fe93cc 100644 --- a/qcsrc/client/hud.qc +++ b/qcsrc/client/hud.qc @@ -142,183 +142,6 @@ float stringwidth_nocolors(string s, vector theSize) return stringwidth(s, FALSE, theSize); } -#define CENTERPRINT_MAX_LINES 30 -string centerprint_messages[CENTERPRINT_MAX_LINES]; -float centerprint_width[CENTERPRINT_MAX_LINES]; -float centerprint_time; -float centerprint_expire; -float centerprint_num; -float centerprint_offset_hint; -vector centerprint_fontsize; - -void centerprint(string strMessage) -{ - float i, j, n, hcount; - string s; - - centerprint_fontsize = HUD_GetFontsize("scr_centersize"); - - centerprint_expire = min(centerprint_expire, time); // if any of the returns happens, this message will fade out - - if(autocvar_scr_centertime <= 0) - return; - - if(strMessage == "") - return; - - // strip trailing newlines - j = strlen(strMessage) - 1; - while(substring(strMessage, j, 1) == "\n" && j >= 0) - j = j - 1; - strMessage = substring(strMessage, 0, j + 1); - - if(strMessage == "") - return; - - // strip leading newlines and remember them, they are a hint that the message should be lower on the screen - j = 0; - while(substring(strMessage, j, 1) == "\n" && j < strlen(strMessage)) - j = j + 1; - strMessage = substring(strMessage, j, strlen(strMessage) - j); - centerprint_offset_hint = j; - - if(strMessage == "") - return; - - // if we get here, we have a message. Initialize its height. - centerprint_num = 0; - - n = tokenizebyseparator(strMessage, "\n"); - i = hcount = 0; - for(j = 0; j < n; ++j) - { - getWrappedLine_remaining = argv(j); - while(getWrappedLine_remaining) - { - s = getWrappedLine(vid_conwidth * 0.75, centerprint_fontsize, stringwidth_colors); - if(centerprint_messages[i] != s) // don't fade the same message in, looks stupid - centerprint_time = time; - if(centerprint_messages[i]) - strunzone(centerprint_messages[i]); - centerprint_messages[i] = strzone(s); - centerprint_width[i] = stringwidth(s, TRUE, centerprint_fontsize); - ++i; - - // half height for empty lines looks better - if(s == "") - hcount += 0.5; - else - hcount += 1; - - if(i >= CENTERPRINT_MAX_LINES) - break; - } - } - - float h, havail; - h = centerprint_fontsize_y*hcount; - - havail = vid_conheight; - if(autocvar_con_chatpos < 0) - havail -= (-autocvar_con_chatpos + autocvar_con_chat) * autocvar_con_chatsize; // avoid overlapping chat - if(havail > vid_conheight - 70) - havail = vid_conheight - 70; // avoid overlapping HUD - -#if 0 - float forbiddenmin, forbiddenmax, allowedmin, allowedmax, preferred; - - // here, the centerprint would cover the crosshair. REALLY BAD. - forbiddenmin = vid_conheight * 0.5 - h - 16; - forbiddenmax = vid_conheight * 0.5 + 16; - - allowedmin = scoreboard_bottom; - allowedmax = havail - h; - preferred = (havail - h)/2; - - - // possible orderings (total: 4! / 4 = 6) - // allowedmin allowedmax forbiddenmin forbiddenmax - // forbiddenmin forbiddenmax allowedmin allowedmax - if(allowedmax < forbiddenmin || allowedmin > forbiddenmax) - { - // forbidden doesn't matter in this case - centerprint_start_y = bound(allowedmin, preferred, allowedmax); - } - // allowedmin forbiddenmin allowedmax forbiddenmax - else if(allowedmin < forbiddenmin && allowedmax < forbiddenmax) - { - centerprint_start_y = bound(allowedmin, preferred, forbiddenmin); - } - // allowedmin forbiddenmin forbiddenmax allowedmax - else if(allowedmin < forbiddenmin) - { - // make sure the forbidden zone is not covered - if(preferred > (forbiddenmin + forbiddenmax) * 0.5) - centerprint_start_y = bound(allowedmin, preferred, forbiddenmin); - else - centerprint_start_y = bound(forbiddenmax, preferred, allowedmin); - } - // forbiddenmin allowedmin allowedmax forbiddenmax - else if(allowedmax < forbiddenmax) - { - // it's better to leave the allowed zone (overlap with scoreboard) than - // to cover the forbidden zone (crosshair) - if(preferred > (forbiddenmin + forbiddenmax) * 0.5) - centerprint_start_y = forbiddenmax; - else - centerprint_start_y = forbiddenmin; - } - // forbiddenmin allowedmin forbiddenmax allowedmax - else - { - centerprint_start_y = bound(forbiddenmax, preferred, allowedmax); - } -#else -#endif - - centerprint_num = i; - - centerprint_expire = time + autocvar_scr_centertime; -} - -void HUD_DrawCenterPrint (void) -{ - float i; - vector pos; - string ts; - float a, sz; - - if(time - centerprint_time < 0.25) - a = (time - centerprint_time) / 0.25; - else - a = bound(0, 1 - 4 * (time - centerprint_expire), 1); - - if(a <= 0) - return; - - sz = 0.8 + (a / 5); - - if(centerprint_num * autocvar_scr_centersize > 24 && scoreboard_active) // 24 = height of Scoreboard text - centerprint_start_y = scoreboard_bottom + centerprint_fontsize_y; - - pos = centerprint_start; - for (i=0; i= 0) + { + weaponorder[weapon_cnt] = self; + ++weapon_cnt; + } + } + for(i = weapon_cnt; i < WEP_MAXCOUNT; ++i) + weaponorder[i] = NULL; + heapsort(weapon_cnt, weaponorder_swap, weaponorder_cmp, world); + + weaponorder_cmp_str = string_null; + } + + float when, fadetime; + when = autocvar_hud_panel_weapons_complainbubble_time; + fadetime = autocvar_hud_panel_weapons_complainbubble_fadetime; + float weapons_st = getstati(STAT_WEAPONS); + float weapon_count; + if (autocvar_hud_panel_weapons_onlyowned) + { + if(autocvar__hud_configure) + { + if (weapons_st == 0) + for(i = 0; i <= WEP_LAST-WEP_FIRST; i += floor((WEP_LAST-WEP_FIRST)/5)) + weapons_st |= power2of(i); + if(menu_enabled != 2) + HUD_Panel_DrawBg(1); // also draw the bg of the entire panel + } + + vector old_panel_size; + for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i) + { + if(weapons_st & weaponorder[i].weapons) + ++weapon_count; + } + if(!autocvar__hud_configure && (autocvar_hud_panel_weapons_complainbubble && time - complain_weapon_time < when + fadetime))// && complain_weapon >= 0 + ++weapon_count; + if (weapon_count == 0) + return; + // reduce size of the panel + if (panel_size_y > panel_size_x) + { + old_panel_size_y = panel_size_y; + panel_size_y *= weapon_count / WEP_COUNT; + panel_pos_y += (old_panel_size_y - panel_size_y) / 2; + } + else + { + old_panel_size_x = panel_size_x; + panel_size_x *= weapon_count / WEP_COUNT; + panel_pos_x += (old_panel_size_x - panel_size_x) / 2; + } + } + else + weapon_count = WEP_COUNT; if (timeout && time >= weapontime + timeout && !autocvar__hud_configure) { @@ -707,37 +600,6 @@ void HUD_Weapons(void) } } - float i, weapid, wpnalpha, weapon_cnt; - - // TODO make this configurable - if(weaponorder_bypriority != autocvar_cl_weaponpriority || !weaponorder[0]) - { - if(weaponorder_bypriority) - strunzone(weaponorder_bypriority); - if(weaponorder_byimpulse) - strunzone(weaponorder_byimpulse); - - weaponorder_bypriority = strzone(autocvar_cl_weaponpriority); - weaponorder_byimpulse = strzone(W_FixWeaponOrder_BuildImpulseList(W_FixWeaponOrder_ForceComplete(W_NumberWeaponOrder(weaponorder_bypriority)))); - weaponorder_cmp_str = strcat(" ", weaponorder_byimpulse, " "); - - weapon_cnt = 0; - for(i = WEP_FIRST; i <= WEP_LAST; ++i) - { - self = get_weaponinfo(i); - if(self.impulse >= 0) - { - weaponorder[weapon_cnt] = self; - ++weapon_cnt; - } - } - for(i = weapon_cnt; i < WEP_MAXCOUNT; ++i) - weaponorder[i] = NULL; - heapsort(weapon_cnt, weaponorder_swap, weaponorder_cmp, world); - - weaponorder_cmp_str = string_null; - } - HUD_Panel_DrawBg(1); if(panel_bg_padding) { @@ -745,6 +607,8 @@ void HUD_Weapons(void) panel_size -= '2 2 0' * panel_bg_padding; } + float weapid, wpnalpha; + if(autocvar_hud_panel_weapons_fade) { wpnalpha = 3.2 - 2 * (time - weapontime); @@ -756,21 +620,17 @@ void HUD_Weapons(void) float rows, columns; float aspect = autocvar_hud_panel_weapons_aspect; rows = panel_size_y/panel_size_x; - rows = bound(1, floor((sqrt(4 * aspect * rows * WEP_COUNT + rows * rows) + rows + 0.5) / 2), WEP_COUNT); + rows = bound(1, floor((sqrt(4 * aspect * rows * weapon_count + rows * rows) + rows + 0.5) / 2), weapon_count); - columns = ceil(WEP_COUNT/rows); + columns = ceil(weapon_count/rows); float row, column; float a, type, fullammo; - float when; - when = autocvar_hud_panel_weapons_complainbubble_time; - float fadetime; - fadetime = autocvar_hud_panel_weapons_complainbubble_fadetime; vector color; vector wpnpos; vector wpnsize; - + vector ammo_color; float ammo_alpha; wpnsize = eX * panel_size_x*(1/columns) + eY * panel_size_y*(1/rows); @@ -805,19 +665,20 @@ void HUD_Weapons(void) acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i)))); } - float weapons_st = getstati(STAT_WEAPONS); - for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i) { self = weaponorder[i]; if (!self || self.impulse < 0) continue; + if (autocvar_hud_panel_weapons_onlyowned) + if (!((weapons_st & self.weapons) || (self.weapon == complain_weapon && time - complain_weapon_time < when + fadetime && autocvar_hud_panel_weapons_complainbubble))) + continue; wpnpos = panel_pos + eX * column * wpnsize_x + eY * row * wpnsize_y; weapid = self.impulse; // draw background behind currently selected weapon - if(self.weapon == activeweapon) + if(self.weapon == switchweapon) drawpic_aspect_skin(wpnpos, "weapon_current_bg", wpnsize, '1 1 1', wpnalpha, DRAWFLAG_NORMAL); // draw the weapon accuracy @@ -963,7 +824,7 @@ string GetAmmoPicture(float i) } } -void DrawAmmoItem(vector myPos, vector mySize, float itemcode, float currently_selected) +void DrawAmmoItem(vector myPos, vector mySize, float itemcode, float currently_selected, float infinite_ammo) { float a; if(autocvar__hud_configure) @@ -975,7 +836,9 @@ void DrawAmmoItem(vector myPos, vector mySize, float itemcode, float currently_s a = getstati(GetAmmoStat(itemcode)); // how much ammo do we have of type itemcode? vector color; - if(a < 10) + if(infinite_ammo) + color = '0 0.5 0.75'; + else if(a < 10) color = '0.7 0 0'; else color = '1 1 1'; @@ -1006,12 +869,12 @@ void DrawAmmoItem(vector myPos, vector mySize, float itemcode, float currently_s if(autocvar_hud_panel_ammo_text) { - if(a > 0) + if(a > 0 || infinite_ammo) drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, color, panel_fg_alpha * alpha, DRAWFLAG_NORMAL); else // "ghost" ammo count drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, '0 0 0', panel_fg_alpha * alpha * 0.5, DRAWFLAG_NORMAL); } - if(a > 0) + if(a > 0 || infinite_ammo) drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * alpha, DRAWFLAG_NORMAL); else // "ghost" ammo icon drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '0 0 0', panel_fg_alpha * alpha * 0.5, DRAWFLAG_NORMAL); @@ -1029,6 +892,7 @@ void HUD_Ammo(void) hud_configure_active_panel = HUD_PANEL_AMMO; HUD_Panel_UpdateCvars(ammo); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -1072,20 +936,23 @@ void HUD_Ammo(void) ammo_size_y = newSize; } - float i, stat_items, currently_selected; + float i, stat_items, currently_selected, infinite_ammo; + infinite_ammo = FALSE; if (autocvar_hud_panel_ammo_onlycurrent) { if(autocvar__hud_configure) { - DrawAmmoItem(pos, ammo_size, 2, true); //show rockets + DrawAmmoItem(pos, ammo_size, 2, true, FALSE); //show rockets return; } stat_items = getstati(STAT_ITEMS); + if (stat_items & IT_UNLIMITED_WEAPON_AMMO) + infinite_ammo = TRUE; for (i = 0; i < AMMO_COUNT; ++i) { currently_selected = stat_items & GetAmmoItemCode(i); if (currently_selected) { - DrawAmmoItem(pos, ammo_size, i, true); + DrawAmmoItem(pos, ammo_size, i, true, infinite_ammo); return; } } @@ -1093,9 +960,11 @@ void HUD_Ammo(void) } stat_items = getstati(STAT_ITEMS); + if (stat_items & IT_UNLIMITED_WEAPON_AMMO) + infinite_ammo = TRUE; for (i = 0; i < AMMO_COUNT; ++i) { currently_selected = stat_items & GetAmmoItemCode(i); - DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected); + DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected, infinite_ammo); ++row; if(row >= rows) { @@ -1214,6 +1083,7 @@ void HUD_Powerups(void) } HUD_Panel_UpdateCvars(powerups); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -1368,6 +1238,7 @@ void HUD_HealthArmor(void) } HUD_Panel_UpdateCvars(healtharmor); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -2006,92 +1877,90 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s } } -#define DAMAGE_CENTERPRINT_SPACER NEWLINES - -void HUD_Centerprint(string s1, string s2, float type, float msg) +void HUD_KillCenterprint(string s1, string s2, float type, float msg) { float gentle; gentle = (autocvar_cl_gentle || autocvar_cl_gentle_messages); if(msg == MSG_SUICIDE) { if (type == DEATH_TEAMCHANGE) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("You are now on: %s"), s1))); + centerprint(sprintf(_("You are now on: %s"), s1)); } else if (type == DEATH_AUTOTEAMCHANGE) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("You have been moved into a different team to improve team balance\nYou are now on: %s"), s1))); + centerprint(sprintf(_("You have been moved into a different team to improve team balance\nYou are now on: %s"), s1)); } else if (type == DEATH_CAMP) { if(gentle) - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1Reconsider your tactics, camper!"))); + centerprint(_("^1Reconsider your tactics, camper!")); else - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1Die camper!"))); + centerprint(_("^1Die camper!")); } else if (type == DEATH_NOAMMO) { if(gentle) - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You are reinserted into the game for running out of ammo..."))); + centerprint(_("^1You are reinserted into the game for running out of ammo...")); else - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You were killed for running out of ammo..."))); + centerprint(_("^1You were killed for running out of ammo...")); } else if (type == DEATH_ROT) { if(gentle) - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You need to preserve your health"))); + centerprint(_("^1You need to preserve your health")); else - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You grew too old without taking your medicine"))); + centerprint(_("^1You grew too old without taking your medicine")); } else if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) { if(gentle) - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1Don't go against team mates!"))); + centerprint(_("^1Don't go against team mates!")); else - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1Don't shoot your team mates!"))); + centerprint(_("^1Don't shoot your team mates!")); } else if (type == DEATH_QUIET) { // do nothing } else { // generic message if(gentle) - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You need to be more careful!"))); + centerprint(_("^1You need to be more careful!")); else - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1You killed your own dumb self!"))); + centerprint(_("^1You killed your own dumb self!")); } } else if(msg == MSG_KILL) { if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) { if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1Moron! You went against ^7%s^1, a team mate!"), s1))); + centerprint(sprintf(_("^1Moron! You went against ^7%s^1, a team mate!"), s1)); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1Moron! You fragged ^7%s^1, a team mate!"), s1))); + centerprint(sprintf(_("^1Moron! You fragged ^7%s^1, a team mate!"), s1)); } } else if (type == KILL_FIRST_BLOOD) { if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1First score"))); + centerprint(_("^1First score")); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1First blood"))); + centerprint(_("^1First blood")); } } else if (type == KILL_FIRST_VICTIM) { if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1First casualty"))); + centerprint(_("^1First casualty")); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1First victim"))); + centerprint(_("^1First victim")); } } else if (type == KILL_TYPEFRAG) { // s2 contains "advanced kill messages" such as ping, handicap... if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You scored against ^7%s^1 who was typing!"), s1), s2)); + centerprint(strcat(sprintf(_("^1You scored against ^7%s^1 who was typing!"), s1), s2)); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You typefragged ^7%s"), s1), s2)); + centerprint(strcat(sprintf(_("^1You typefragged ^7%s"), s1), s2)); } } else if (type == KILL_TYPEFRAGGED) { if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You were scored against by ^7%s^1 while you were typing!"), s1), s2)); + centerprint(strcat(sprintf(_("^1You were scored against by ^7%s^1 while you were typing!"), s1), s2)); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You were typefragged by ^7%s"), s1), s2)); + centerprint(strcat(sprintf(_("^1You were typefragged by ^7%s"), s1), s2)); } } else if (type == KILL_FRAG) { if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^4You scored against ^7%s"), s1), s2)); + centerprint(strcat(sprintf(_("^4You scored against ^7%s"), s1), s2)); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^4You fragged ^7%s"), s1), s2)); + centerprint(strcat(sprintf(_("^4You fragged ^7%s"), s1), s2)); } } else { // generic message if(gentle) { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You were scored against by ^7%s"), s1), s2)); + centerprint(strcat(sprintf(_("^1You were scored against by ^7%s"), s1), s2)); } else { - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, sprintf(_("^1You were fragged by ^7%s"), s1), s2)); + centerprint(strcat(sprintf(_("^1You were fragged by ^7%s"), s1), s2)); } } } else if(msg == MSG_KILL_ACTION) { // TODO: invent more centerprints here? - centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, _("^1Watch your step!"))); + centerprint(_("^1Watch your step!")); } } @@ -2105,6 +1974,7 @@ void HUD_Notify (void) hud_configure_active_panel = HUD_PANEL_NOTIFY; HUD_Panel_UpdateCvars(notify); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -2418,6 +2288,7 @@ void HUD_Timer(void) hud_configure_active_panel = HUD_PANEL_TIMER; HUD_Panel_UpdateCvars(timer); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -2475,6 +2346,7 @@ void HUD_Radar(void) hud_configure_active_panel = HUD_PANEL_RADAR; HUD_Panel_UpdateCvars(radar); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -2599,19 +2471,20 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count) entity tm, pl; #define SCOREPANEL_MAX_ENTRIES 6 #define SCOREPANEL_ASPECTRATIO 2 - const float entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize_y/mySize_x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES); - const vector fontsize = '1 1 0' * (mySize_y/entries); + float entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize_y/mySize_x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES); + vector fontsize = '1 1 0' * (mySize_y/entries); vector rgb, score_color; rgb = '1 1 1'; score_color = '1 1 1'; - const float name_size = mySize_x*0.75; - const float spacing_size = mySize_x*0.04; + float name_size = mySize_x*0.75; + float spacing_size = mySize_x*0.04; const float highlight_alpha = 0.2; float i, me_printed, first_pl; string s; - i, first_pl = 0; + i = 0; + first_pl = 0; if (autocvar__hud_configure) { float players_per_team; @@ -2726,6 +2599,7 @@ void HUD_Score(void) hud_configure_active_panel = HUD_PANEL_SCORE; HUD_Panel_UpdateCvars(score); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -2910,6 +2784,7 @@ void HUD_RaceTimer (void) hud_configure_active_panel = HUD_PANEL_RACETIMER; HUD_Panel_UpdateCvars(racetimer); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -3105,6 +2980,7 @@ void HUD_VoteWindow(void) return; HUD_Panel_UpdateCvars(vote); + HUD_Panel_ApplyFadeAlpha(); if(uid2name_dialog) { @@ -3117,7 +2993,7 @@ void HUD_VoteWindow(void) pos = panel_pos; mySize = panel_size; - a = vote_alpha * bound(autocvar_hud_panel_vote_alreadyvoted_alpha, 1 - vote_highlighted, 1); + a = vote_alpha * (vote_highlighted ? autocvar_hud_panel_vote_alreadyvoted_alpha : 1); HUD_Panel_DrawBg(a); a = panel_fg_alpha * a; @@ -3168,7 +3044,7 @@ void HUD_VoteWindow(void) drawsetcliparea(pos_x, pos_y, mySize_x * 0.5, mySize_y); drawpic_skin(pos + eY * (5/8) * mySize_y, "voteprogress_voted", eX * mySize_x + eY * (3/8) * mySize_y, '1 1 1', a, DRAWFLAG_NORMAL); } - else if(vote_highlighted == 2) { + else if(vote_highlighted == -1) { drawsetcliparea(pos_x + 0.5 * mySize_x, pos_y, mySize_x * 0.5, mySize_y); drawpic_skin(pos + eY * (5/8) * mySize_y, "voteprogress_voted", eX * mySize_x + eY * (3/8) * mySize_y, '1 1 1', a, DRAWFLAG_NORMAL); } @@ -3187,10 +3063,6 @@ void HUD_VoteWindow(void) } drawresetcliparea(); - - if(!vote_active) { - vote_highlighted = 0; - } } // Mod icons panel (#10) @@ -3860,6 +3732,7 @@ void HUD_ModIcons(void) hud_configure_active_panel = HUD_PANEL_MODICONS; HUD_Panel_UpdateCvars(modicons); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -3914,6 +3787,7 @@ void HUD_DrawPressedKeys(void) HUD_Panel_UpdateCvars(pressedkeys); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -3978,6 +3852,7 @@ void HUD_Chat(void) hud_configure_active_panel = HUD_PANEL_CHAT; HUD_Panel_UpdateCvars(chat); + HUD_Panel_ApplyFadeAlpha(); if(autocvar__con_chat_maximized && !autocvar__hud_configure) // draw at full screen height if maximized { @@ -4053,6 +3928,7 @@ void HUD_EngineInfo(void) hud_configure_active_panel = HUD_PANEL_ENGINEINFO; HUD_Panel_UpdateCvars(engineinfo); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -4115,6 +3991,7 @@ void HUD_InfoMessages(void) hud_configure_active_panel = HUD_PANEL_INFOMESSAGES; HUD_Panel_UpdateCvars(infomessages); + HUD_Panel_ApplyFadeAlpha(); vector pos, mySize; pos = panel_pos; mySize = panel_size; @@ -4294,12 +4171,14 @@ void HUD_Physics(void) if(!autocvar__hud_configure) { if(!autocvar_hud_panel_physics) return; - if(spectatee_status == -1 && autocvar_hud_panel_physics < 2) return; + if(spectatee_status == -1 && (autocvar_hud_panel_physics == 1 || autocvar_hud_panel_physics == 3)) return; + if(autocvar_hud_panel_physics == 3 && !(gametype == GAME_RACE || gametype == GAME_CTS)) return; } else hud_configure_active_panel = HUD_PANEL_PHYSICS; HUD_Panel_UpdateCvars(physics); + HUD_Panel_ApplyFadeAlpha(); HUD_Panel_DrawBg(1); if(panel_bg_padding) @@ -4510,6 +4389,292 @@ void HUD_Physics(void) drawstring_aspect(panel_pos + acceleration_offset, strcat(ftos_decimals(acceleration, 2), "g"), panel_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); } +// CenterPrint (#16) +// +#define CENTERPRINT_MAX_MSGS 10 +#define CENTERPRINT_MAX_ENTRIES 50 +#define CENTERPRINT_SPACING 0.7 +float cpm_index; +string centerprint_messages[CENTERPRINT_MAX_MSGS]; +float centerprint_msgID[CENTERPRINT_MAX_MSGS]; +float centerprint_time[CENTERPRINT_MAX_MSGS]; +float centerprint_expire_time[CENTERPRINT_MAX_MSGS]; +float centerprint_countdown_num[CENTERPRINT_MAX_MSGS]; +float centerprint_fadetime; +float centerprint_showing; + +void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num) +{ + float i, j; + + if(strMessage == "" && new_id == 0) + return; + + // strip trailing newlines + j = strlen(strMessage) - 1; + while(substring(strMessage, j, 1) == "\n" && j >= 0) + --j; + if (j < strlen(strMessage) - 1) + strMessage = substring(strMessage, 0, j + 1); + + if(strMessage == "" && new_id == 0) + return; + + // strip leading newlines + j = 0; + while(substring(strMessage, j, 1) == "\n" && j < strlen(strMessage)) + ++j; + if (j > 0) + strMessage = substring(strMessage, j, strlen(strMessage) - j); + + if(strMessage == "" && new_id == 0) + return; + + if (!centerprint_showing) + centerprint_showing = TRUE; + + centerprint_fadetime = bound(0, autocvar_hud_panel_centerprint_fadetime, 1); + + for (i=0, j=cpm_index; i time + centerprint_fadetime || centerprint_expire_time[j] < time) + centerprint_expire_time[j] = time + centerprint_fadetime; + return; + } + break; // found a msg with the same id, at position j + } + } + + if (i == CENTERPRINT_MAX_MSGS) + { + // a msg with the same id was not found, add the msg at the next position + --cpm_index; + if (cpm_index == -1) + cpm_index = CENTERPRINT_MAX_MSGS - 1; + j = cpm_index; + } + if(centerprint_messages[j]) + strunzone(centerprint_messages[j]); + centerprint_messages[j] = strzone(strMessage); + centerprint_msgID[j] = new_id; + if (duration < 0) + centerprint_time[j] = -1; + else + { + if(duration == 0) + duration = max(1, autocvar_hud_panel_centerprint_time); + centerprint_time[j] = duration; + centerprint_expire_time[j] = time + duration; + } + centerprint_countdown_num[j] = countdown_num; +} + +void centerprint(string strMessage) +{ + centerprint_generic(0, strMessage, autocvar_hud_panel_centerprint_time, 0); +} + +void reset_centerprint_messages(void) +{ + float i; + for (i=0; i hud_configure_cp_generation_time) + { + 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); + 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 + centerprint(sprintf("Message at time %s", seconds_tostring(time))); + hud_configure_cp_generation_time = time + 1 + random()*4; + } + } + + HUD_Panel_UpdateCvars(centerprint); + + // this panel doesn't fade when showing the scoreboard + if(autocvar__menu_alpha) + HUD_Panel_ApplyFadeAlpha(); + + if(scoreboard_fade_alpha) + { + // move the panel below the scoreboard + if (scoreboard_bottom >= 0.96 * vid_conheight) + return; + vector target_pos; + target_pos = eY * scoreboard_bottom + eX * 0.5 * (vid_conwidth - panel_size_x); + panel_pos = panel_pos + (target_pos - panel_pos) * sqrt(scoreboard_fade_alpha); + panel_size_y = min(panel_size_y, vid_conheight - scoreboard_bottom); + } + + HUD_Panel_DrawBg(1); + + if (!centerprint_showing) + return; + + if(panel_bg_padding) + { + panel_pos += '1 1 0' * panel_bg_padding; + panel_size -= '2 2 0' * panel_bg_padding; + } + + float entries, height; + vector fontsize; + // entries = bound(1, floor(CENTERPRINT_MAX_ENTRIES * 4 * panel_size_y/panel_size_x), CENTERPRINT_MAX_ENTRIES); + // height = panel_size_y/entries; + // fontsize = '1 1 0' * height; + height = vid_conheight/50 * autocvar_hud_panel_centerprint_fontscale; + fontsize = '1 1 0' * height; + entries = bound(1, floor(panel_size_y/height), CENTERPRINT_MAX_ENTRIES); + + float i, j, k, n; + float a, sz, align, current_msg_pos_y, msg_size; + vector pos; + string ts; + + n = -1; // if no msg will be displayed, n stays -1 + + pos = panel_pos; + if (autocvar_hud_panel_centerprint_flip) + pos_y += panel_size_y; + align = bound(0, autocvar_hud_panel_centerprint_align, 1); + for (i=0, j=cpm_index; i 0) + { + centerprint_countdown_num[j] = centerprint_countdown_num[j] - 1; + if (centerprint_countdown_num[j] == 0) + continue; + centerprint_expire_time[j] = centerprint_expire_time[j] + centerprint_time[j]; + } + else + continue; + } + if (centerprint_time[j] < 0 || centerprint_expire_time[j] - centerprint_fadetime > time) + { + a = bound(0, (time - (centerprint_expire_time[j] - centerprint_time[j])) / centerprint_fadetime, 1); + sz = 0.8 + a * (1 - 0.8); + } + else if (centerprint_expire_time[j] > time) + { + a = (centerprint_expire_time[j] - time) / centerprint_fadetime; + sz = 0.8 + a * (1 - 0.8); + } + + drawfontscale = sz * '1 1 0'; + if (centerprint_countdown_num[j]) + n = tokenizebyseparator(sprintf(centerprint_messages[j], centerprint_countdown_num[j]), "\n"); + else + n = tokenizebyseparator(centerprint_messages[j], "\n"); + if (autocvar_hud_panel_centerprint_flip) + { + // check if the message can be entirely shown + for(k = 0; k < n; ++k) + { + getWrappedLine_remaining = argv(k); + while(getWrappedLine_remaining) + { + ts = getWrappedLine(panel_size_x * sz, fontsize, stringwidth_colors); + if (ts != "") + pos_y -= fontsize_y; + else + pos_y -= fontsize_y * CENTERPRINT_SPACING/2; + // NOTE: uncommented so as to not reject messages whenever they are "too large" -- This just continues drawing it anyway. + //if (pos_y < panel_pos_y) // check if the next line can be shown + //{ + // drawfontscale = '1 1 0'; + // return; + //} + } + } + current_msg_pos_y = pos_y; // save starting pos (first line) of the current message + } + + msg_size = pos_y; + for(k = 0; k < n; ++k) + { + getWrappedLine_remaining = argv(k); + while(getWrappedLine_remaining) + { + ts = getWrappedLine(panel_size_x * sz, fontsize, stringwidth_colors); + if (ts != "") + { + 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); + pos_y += fontsize_y; + } + else + pos_y += fontsize_y * CENTERPRINT_SPACING/2; + // NOTE: uncommented so as to not reject messages whenever they are "too large" -- This just continues drawing it anyway. + //if (!autocvar_hud_panel_centerprint_flip && pos_y > panel_pos_y + panel_size_y - fontsize_y) // check if the next line can be shown + //{ + // drawfontscale = '1 1 0'; + // return; + //} + } + } + 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(a)); + } + else + { + 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(a)); + } + } + drawfontscale = '1 1 0'; + if (n == -1) + { + centerprint_showing = FALSE; + reset_centerprint_messages(); + } +} + /* ================== Main HUD system @@ -4559,6 +4724,8 @@ switch (id) {\ HUD_InfoMessages(); break;\ case (HUD_PANEL_PHYSICS):\ HUD_Physics(); break;\ + case (HUD_PANEL_CENTERPRINT):\ + HUD_CenterPrint(); break;\ } ENDS_WITH_CURLY_BRACE void HUD_Main (void) @@ -4589,6 +4756,14 @@ void HUD_Main (void) else if(autocvar__menu_alpha == 0 && scoreboard_fade_alpha == 0) hud_fade_alpha = 1; + // panels that we want to be active together with the scoreboard + // they must call HUD_Panel_ApplyFadeAlpha(); only when showing the menu + if(scoreboard_fade_alpha == 1) + { + HUD_CenterPrint(); + return; + } + if(!autocvar__hud_configure && !hud_fade_alpha) return; @@ -4707,13 +4882,18 @@ void HUD_Main (void) if(autocvar__con_chat_maximized) HUD_Chat(); // HUD_DrawPanel(HUD_PANEL_CHAT); - if (autocvar__hud_configure && spectatee_status && hud_configure_prev == -1) // try to join if we are in hud_configure mode, but still spectating, and in the first frame (in order to get rid of motd when launching a server via the menu "HUD Setup" button) - localcmd("cmd selectteam auto; cmd join\n"); - - if(autocvar__hud_configure && tab_panel != -1) + if(autocvar__hud_configure) { - HUD_Panel_UpdatePosSizeForId(tab_panel) - drawfill(panel_pos - '1 1 0' * panel_bg_border, panel_size + '2 2 0' * panel_bg_border, '1 1 1', .2, DRAWFLAG_NORMAL); + if(tab_panel != -1) + { + HUD_Panel_UpdatePosSizeForId(tab_panel) + drawfill(panel_pos - '1 1 0' * panel_bg_border, panel_size + '2 2 0' * panel_bg_border, '1 1 1', .2, DRAWFLAG_NORMAL); + } + if(highlightedPanel != -1) + { + HUD_Panel_UpdatePosSizeForId(highlightedPanel); + HUD_Panel_HlBorder(panel_bg_border + 1.5 * hlBorderSize, '0 0.5 1', 0.25 * (1 - autocvar__menu_alpha)); + } } hud_configure_prev = autocvar__hud_configure;