From d77d35f12d537628d021b946d5fd6aa20734042d Mon Sep 17 00:00:00 2001 From: z411 Date: Wed, 4 Jan 2023 20:40:42 +0000 Subject: [PATCH] Item Pickup panel * This panel shows the weapon or item that has been just picked up, with its icon, item name, and time of pickup. * The time of pickup can be hidden by the client or the server (default in XPM ruleset). * If you pick up the same item several times in a row it will show (x2, x3...) in parentheses. * Display time, fade out time and icon size can all be configured. The size of its contents automatically change size to fit the panel size. --- _hud_common.cfg | 7 ++ _hud_descriptions.cfg | 9 ++ hud_luma.cfg | 11 +- hud_luminos.cfg | 11 +- hud_luminos_minimal.cfg | 13 ++- hud_luminos_minimal_xhair.cfg | 13 ++- hud_luminos_old.cfg | 11 +- hud_nexuiz.cfg | 13 ++- qcsrc/client/hud/hud.qh | 2 + qcsrc/client/hud/panel/_mod.inc | 1 + qcsrc/client/hud/panel/_mod.qh | 1 + qcsrc/client/hud/panel/pickup.qc | 105 +++++++++++++++++++ qcsrc/client/hud/panel/pickup.qh | 14 +++ qcsrc/client/hud/panel/timer.qc | 26 +++-- qcsrc/common/constants.qh | 1 + qcsrc/common/items/inventory.qh | 12 +++ qcsrc/common/items/item/ammo.qh | 10 +- qcsrc/common/items/item/jetpack.qh | 2 +- qcsrc/common/net_linked.qh | 1 + qcsrc/common/notifications/all.qh | 2 +- qcsrc/menu/xonotic/_mod.inc | 1 + qcsrc/menu/xonotic/_mod.qh | 1 + qcsrc/menu/xonotic/dialog_hudpanel_pickup.qc | 39 +++++++ qcsrc/menu/xonotic/dialog_hudpanel_pickup.qh | 13 +++ qcsrc/menu/xonotic/mainwindow.qc | 5 + qcsrc/server/items/items.qc | 19 +++- qcsrc/server/weapons/common.qc | 4 - qcsrc/server/world.qc | 4 + ruleset-XPM.cfg | 1 + xonotic-server.cfg | 3 + 30 files changed, 318 insertions(+), 37 deletions(-) create mode 100644 qcsrc/client/hud/panel/pickup.qc create mode 100644 qcsrc/client/hud/panel/pickup.qh create mode 100644 qcsrc/menu/xonotic/dialog_hudpanel_pickup.qc create mode 100644 qcsrc/menu/xonotic/dialog_hudpanel_pickup.qh diff --git a/_hud_common.cfg b/_hud_common.cfg index 74f48a6aa5..0c808dd378 100644 --- a/_hud_common.cfg +++ b/_hud_common.cfg @@ -49,6 +49,7 @@ seta hud_panel_scoreboard_accuracy 1 "show weapon accuracy stats panel in the sc seta hud_panel_scoreboard_ctf_leaderboard 1 "show a capture time rankings leaderboard in the scoreboard if allowed by the server" seta hud_panel_scoreboard_itemstats 1 "show item stats panel in the scoreboard" seta hud_panel_strafehud 3 "enable this panel, 1 = show if not observing, 2 = show always, 3 = show only in race/cts if not observing" +seta hud_panel_pickup 1 "enable this panel" seta hud_panel_weapons_dynamichud 1 "apply the dynamic hud effects to this panel" seta hud_panel_ammo_dynamichud 1 "apply the dynamic hud effects to this panel" @@ -69,6 +70,7 @@ seta hud_panel_centerprint_dynamichud 1 "apply the dynamic hud effects to t seta hud_panel_itemstime_dynamichud 1 "apply the dynamic hud effects to this panel" seta hud_panel_scoreboard_dynamichud 0 "apply the dynamic hud effects to this panel" seta hud_panel_strafehud_dynamichud 1 "apply the dynamic hud effects to this panel" +seta hud_panel_pickup_dynamichud 1 "apply the dynamic hud effects to this panel" seta hud_panel_weapons_ammo_full_shells 60 "show 100% of the status bar at this ammo count" seta hud_panel_weapons_ammo_full_nails 320 "show 100% of the status bar at this ammo count" @@ -275,3 +277,8 @@ seta hud_shownames_maxdistance 5000 "alpha/size is 0 at this distance" seta hud_shownames_antioverlap 1 "if two tags overlap, fade out the one further away from you" seta hud_shownames_antioverlap_minalpha 0.4 "fade out overlapping tags to this alpha value" seta hud_shownames_offset 52 "offset (along z-axis) tag from player origin by this many units" + +seta hud_panel_pickup_showtimer 1 "0 = hide timer, 1 = show timer, 2 = only when spectating" +seta hud_panel_pickup_iconsize 1.5 "icon size scale" +seta hud_panel_pickup_time 3 "pickup message duration (can't be higher than 5)" +seta hud_panel_pickup_fade_out 0.15 "how long a pickup message takes to fade out (this time is included in the message duration)" diff --git a/_hud_descriptions.cfg b/_hud_descriptions.cfg index 545e0b92b5..b183126469 100644 --- a/_hud_descriptions.cfg +++ b/_hud_descriptions.cfg @@ -380,3 +380,12 @@ seta hud_panel_strafehud_bg_color_team "" "override panel color with team color seta hud_panel_strafehud_bg_alpha "" "if set to something else than \"\" = override default panel background alpha" seta hud_panel_strafehud_bg_border "" "if set to something else than \"\" = override default size of border around the background" seta hud_panel_strafehud_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" + +seta hud_panel_pickup_pos "" "position of this base of the panel" +seta hud_panel_pickup_size "" "size of this panel" +seta hud_panel_pickup_bg "" "if set to something else than \"\" = override default background" +seta hud_panel_pickup_bg_color "" "if set to something else than \"\" = override default panel background color" +seta hud_panel_pickup_bg_color_team "" "override panel color with team color in team based games" +seta hud_panel_pickup_bg_alpha "" "if set to something else than \"\" = override default panel background alpha" +seta hud_panel_pickup_bg_border "" "if set to something else than \"\" = override default size of border around the background" +seta hud_panel_pickup_bg_padding "" "if set to something else than \"\" = override default padding of contents from border" diff --git a/hud_luma.cfg b/hud_luma.cfg index 384024e345..9aaaac6f7c 100644 --- a/hud_luma.cfg +++ b/hud_luma.cfg @@ -30,7 +30,7 @@ seta hud_progressbar_acceleration_neg_color "0.86 0.35 0" seta hud_progressbar_vehicles_ammo1_color "0.77 0.67 0" seta hud_progressbar_vehicles_ammo2_color "0.86 0.35 0" -seta _hud_panelorder "17 25 15 12 9 5 10 6 14 0 7 4 11 2 1 3 8 13 16 18 23 19 20 21 22 24 " +seta _hud_panelorder "17 25 15 12 9 5 10 6 14 0 7 4 11 2 1 3 8 13 16 18 23 19 20 21 22 24 25 26 " seta hud_configure_grid "1" seta hud_configure_grid_xsize "0.005000" @@ -382,4 +382,13 @@ seta hud_panel_strafehud_bg_alpha "0.7" seta hud_panel_strafehud_bg_border "" seta hud_panel_strafehud_bg_padding "" +seta hud_panel_pickup_pos "0.010000 0.945000" +seta hud_panel_pickup_size "0.260000 0.035000" +seta hud_panel_pickup_bg "0" +seta hud_panel_pickup_bg_color "" +seta hud_panel_pickup_bg_color_team "" +seta hud_panel_pickup_bg_alpha "1" +seta hud_panel_pickup_bg_border "" +seta hud_panel_pickup_bg_padding "" + menu_sync diff --git a/hud_luminos.cfg b/hud_luminos.cfg index 82b07077fe..6bc9883641 100644 --- a/hud_luminos.cfg +++ b/hud_luminos.cfg @@ -30,7 +30,7 @@ seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5" seta hud_progressbar_vehicles_ammo1_color "0.8 0.7 0" seta hud_progressbar_vehicles_ammo2_color "0.7 0.4 0" -seta _hud_panelorder "17 25 15 12 9 10 5 6 14 0 7 4 11 2 1 3 8 13 16 18 23 19 20 21 22 24 " +seta _hud_panelorder "17 25 15 12 9 10 5 6 14 0 7 4 11 2 1 3 8 13 16 18 23 19 20 21 22 24 25 26 " seta hud_configure_grid "1" seta hud_configure_grid_xsize "0.010000" @@ -382,4 +382,13 @@ seta hud_panel_strafehud_bg_alpha "" seta hud_panel_strafehud_bg_border "" seta hud_panel_strafehud_bg_padding "" +seta hud_panel_pickup_pos "0.010000 0.950000" +seta hud_panel_pickup_size "0.260000 0.030000" +seta hud_panel_pickup_bg "0" +seta hud_panel_pickup_bg_color "" +seta hud_panel_pickup_bg_color_team "" +seta hud_panel_pickup_bg_alpha "1" +seta hud_panel_pickup_bg_border "" +seta hud_panel_pickup_bg_padding "" + menu_sync diff --git a/hud_luminos_minimal.cfg b/hud_luminos_minimal.cfg index 3d93b90b38..c798b7564c 100644 --- a/hud_luminos_minimal.cfg +++ b/hud_luminos_minimal.cfg @@ -30,7 +30,7 @@ seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5" seta hud_progressbar_vehicles_ammo1_color "0.8 0.7 0" seta hud_progressbar_vehicles_ammo2_color "0.7 0.4 0" -seta _hud_panelorder "17 10 3 0 14 6 9 13 4 1 2 11 12 7 5 8 25 15 16 18 23 19 20 21 22 24 " +seta _hud_panelorder "17 10 3 0 14 6 9 13 4 1 2 11 12 7 5 8 25 15 16 18 23 19 20 21 22 24 25 26 " seta hud_configure_grid "1" seta hud_configure_grid_xsize "0.010000" @@ -178,7 +178,7 @@ seta hud_panel_racetimer_bg_alpha "" seta hud_panel_racetimer_bg_border "" seta hud_panel_racetimer_bg_padding "" -seta hud_panel_vote_pos "0 0.890000" +seta hud_panel_vote_pos "0.720000 0.890000" seta hud_panel_vote_size "0.170000 0.110000" seta hud_panel_vote_bg "" seta hud_panel_vote_bg_color "" @@ -382,4 +382,13 @@ seta hud_panel_strafehud_bg_alpha "" seta hud_panel_strafehud_bg_border "" seta hud_panel_strafehud_bg_padding "" +seta hud_panel_pickup_pos "0 0.960000" +seta hud_panel_pickup_size "0.270000 0.030000" +seta hud_panel_pickup_bg "0" +seta hud_panel_pickup_bg_color "" +seta hud_panel_pickup_bg_color_team "" +seta hud_panel_pickup_bg_alpha "1" +seta hud_panel_pickup_bg_border "" +seta hud_panel_pickup_bg_padding "" + menu_sync diff --git a/hud_luminos_minimal_xhair.cfg b/hud_luminos_minimal_xhair.cfg index c1a69a88ca..7532b807f3 100644 --- a/hud_luminos_minimal_xhair.cfg +++ b/hud_luminos_minimal_xhair.cfg @@ -30,7 +30,7 @@ seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5" seta hud_progressbar_vehicles_ammo1_color "0.8 0.7 0" seta hud_progressbar_vehicles_ammo2_color "0.7 0.4 0" -seta _hud_panelorder "17 25 15 3 1 2 11 10 0 14 6 9 13 4 12 7 5 8 16 18 23 19 20 21 22 24 " +seta _hud_panelorder "17 25 15 3 1 2 11 10 0 14 6 9 13 4 12 7 5 8 16 18 23 19 20 21 22 24 25 26 " seta hud_configure_grid "1" seta hud_configure_grid_xsize "0.010000" @@ -178,7 +178,7 @@ seta hud_panel_racetimer_bg_alpha "" seta hud_panel_racetimer_bg_border "" seta hud_panel_racetimer_bg_padding "" -seta hud_panel_vote_pos "0 0.890000" +seta hud_panel_vote_pos "0.720000 0.890000" seta hud_panel_vote_size "0.170000 0.110000" seta hud_panel_vote_bg "" seta hud_panel_vote_bg_color "" @@ -382,4 +382,13 @@ seta hud_panel_strafehud_bg_alpha "" seta hud_panel_strafehud_bg_border "" seta hud_panel_strafehud_bg_padding "" +seta hud_panel_pickup_pos "0 0.960000" +seta hud_panel_pickup_size "0.270000 0.030000" +seta hud_panel_pickup_bg "0" +seta hud_panel_pickup_bg_color "" +seta hud_panel_pickup_bg_color_team "" +seta hud_panel_pickup_bg_alpha "1" +seta hud_panel_pickup_bg_border "" +seta hud_panel_pickup_bg_padding "" + menu_sync diff --git a/hud_luminos_old.cfg b/hud_luminos_old.cfg index f0842bc640..80ab470df6 100644 --- a/hud_luminos_old.cfg +++ b/hud_luminos_old.cfg @@ -30,7 +30,7 @@ seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5" seta hud_progressbar_vehicles_ammo1_color "0.8 0.7 0" seta hud_progressbar_vehicles_ammo2_color "0.7 0.4 0" -seta _hud_panelorder "17 25 15 10 9 6 8 14 5 0 4 13 2 7 1 3 11 12 16 18 23 19 20 21 22 24 " +seta _hud_panelorder "17 25 15 10 9 6 8 14 5 0 4 13 2 7 1 3 11 12 16 18 23 19 20 21 22 24 25 26 " seta hud_configure_grid "1" seta hud_configure_grid_xsize "0.010000" @@ -382,4 +382,13 @@ seta hud_panel_strafehud_bg_alpha "" seta hud_panel_strafehud_bg_border "" seta hud_panel_strafehud_bg_padding "" +seta hud_panel_pickup_pos "0.700000 0.940000" +seta hud_panel_pickup_size "0.260000 0.040000" +seta hud_panel_pickup_bg "0" +seta hud_panel_pickup_bg_color "" +seta hud_panel_pickup_bg_color_team "" +seta hud_panel_pickup_bg_alpha "1" +seta hud_panel_pickup_bg_border "" +seta hud_panel_pickup_bg_padding "" + menu_sync diff --git a/hud_nexuiz.cfg b/hud_nexuiz.cfg index 2b035c8a4e..2b8fe14657 100644 --- a/hud_nexuiz.cfg +++ b/hud_nexuiz.cfg @@ -30,7 +30,7 @@ seta hud_progressbar_acceleration_neg_color "0.125 0.25 0.5" seta hud_progressbar_vehicles_ammo1_color "0.8 0.7 0" seta hud_progressbar_vehicles_ammo2_color "0.7 0.4 0" -seta _hud_panelorder "17 25 15 0 11 8 5 6 14 9 13 7 2 3 1 10 12 4 16 18 23 19 20 21 22 24 " +seta _hud_panelorder "17 25 15 0 11 8 5 6 14 9 13 7 2 3 1 10 12 4 16 18 23 19 20 21 22 24 25 26 " seta hud_configure_grid "1" seta hud_configure_grid_xsize "0.010000" @@ -211,7 +211,7 @@ seta hud_panel_pressedkeys_bg_padding "" seta hud_panel_pressedkeys_aspect "1.8" seta hud_panel_pressedkeys_attack "0" -seta hud_panel_chat_pos "0 0.760000" +seta hud_panel_chat_pos "0 0.730000" seta hud_panel_chat_size "0.420000 0.130000" seta hud_panel_chat_bg "0" seta hud_panel_chat_bg_color "" @@ -382,4 +382,13 @@ seta hud_panel_strafehud_bg_alpha "" seta hud_panel_strafehud_bg_border "" seta hud_panel_strafehud_bg_padding "" +seta hud_panel_pickup_pos "0.010000 0.860000" +seta hud_panel_pickup_size "0.330000 0.030000" +seta hud_panel_pickup_bg "0" +seta hud_panel_pickup_bg_color "" +seta hud_panel_pickup_bg_color_team "" +seta hud_panel_pickup_bg_alpha "1" +seta hud_panel_pickup_bg_border "" +seta hud_panel_pickup_bg_padding "" + menu_sync diff --git a/qcsrc/client/hud/hud.qh b/qcsrc/client/hud/hud.qh index 463dcd402d..0eb81916ce 100644 --- a/qcsrc/client/hud/hud.qh +++ b/qcsrc/client/hud/hud.qh @@ -121,6 +121,7 @@ int ts_primary, ts_secondary; float weapontime; float weaponprevtime; +float timer; float teamnagger; int hudShiftState; @@ -274,6 +275,7 @@ REGISTER_HUD_PANEL(ITEMSTIME, HUD_ItemsTime, PANEL_CONFIG_MAIN | PANE REGISTER_HUD_PANEL(QUICKMENU, HUD_QuickMenu, PANEL_CONFIG_MAIN , PANEL_SHOW_MAINGAME | PANEL_SHOW_MINIGAME ) // QUICKMENU REGISTER_HUD_PANEL(SCOREBOARD, Scoreboard_Draw, PANEL_CONFIG_NO , PANEL_SHOW_MAINGAME | PANEL_SHOW_MINIGAME | PANEL_SHOW_MAPVOTE | PANEL_SHOW_WITH_SB) // SCOREBOARD REGISTER_HUD_PANEL(STRAFEHUD, HUD_StrafeHUD, PANEL_CONFIG_MAIN | PANEL_CONFIG_CANBEOFF, PANEL_SHOW_MAINGAME ) // STRAFEHUD +REGISTER_HUD_PANEL(PICKUP, HUD_Pickup, PANEL_CONFIG_MAIN | PANEL_CONFIG_CANBEOFF, PANEL_SHOW_MAINGAME ) // PICKUP // always add new panels to the end of list // Because calling lots of functions in QC apparently cuts fps in half on many machines: diff --git a/qcsrc/client/hud/panel/_mod.inc b/qcsrc/client/hud/panel/_mod.inc index 68e368ed13..9f6c7fb5c4 100644 --- a/qcsrc/client/hud/panel/_mod.inc +++ b/qcsrc/client/hud/panel/_mod.inc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/client/hud/panel/_mod.qh b/qcsrc/client/hud/panel/_mod.qh index 1b45f0cd04..4f901379e8 100644 --- a/qcsrc/client/hud/panel/_mod.qh +++ b/qcsrc/client/hud/panel/_mod.qh @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/client/hud/panel/pickup.qc b/qcsrc/client/hud/panel/pickup.qc new file mode 100644 index 0000000000..185893138c --- /dev/null +++ b/qcsrc/client/hud/panel/pickup.qc @@ -0,0 +1,105 @@ +#include "pickup.qh" + +#include +#include +#include +#include + +// Pickup (#26) + +void HUD_Pickup_Export(int fh) +{ + // allow saving cvars that aesthetically change the panel into hud skin files +} + +void Pickup_Update(entity it, int count) +{ + if(last_pickup_item != it || time - STAT(LAST_PICKUP) > autocvar_hud_panel_pickup_time) + last_pickup_count = 0; + last_pickup_item = it; + last_pickup_count += count; +} + +float HUD_Pickup_Time(float t) +{ + float timelimit = (warmup_stage ? STAT(WARMUP_TIMELIMIT) : STAT(TIMELIMIT) * 60); + + if(autocvar_hud_panel_timer_increment || timelimit <= 0) + return floor(t - STAT(GAMESTARTTIME)); + else + return ceil(timelimit + STAT(GAMESTARTTIME) - t); +} + +void HUD_Pickup() +{ + if(!autocvar_hud_panel_pickup) return; + + HUD_Panel_LoadCvars(); + vector pos, mySize; + pos = panel_pos; + mySize = panel_size; + + if (autocvar_hud_panel_pickup_dynamichud) + HUD_Scale_Enable(); + else + HUD_Scale_Disable(); + HUD_Panel_DrawBg(); + if(panel_bg_padding) + { + pos += '1 1 0' * panel_bg_padding; + mySize -= '2 2 0' * panel_bg_padding; + } + + float last_pickup_time = STAT(LAST_PICKUP); + float display_time = min(5, autocvar_hud_panel_pickup_time); + entity it = last_pickup_item; + + if((last_pickup_time && last_pickup_time > time - display_time && it) || autocvar__hud_configure) { + string str_timer, str_name, icon; + vector sz, sz2; + vector fontsize = '1 1 0' * mySize.y; + vector iconsize = fontsize * autocvar_hud_panel_pickup_iconsize; + + if(autocvar__hud_configure) + icon = strcat(hud_skin_path, "/armor_mega"); + else + icon = strcat(hud_skin_path, "/", ((it.model2) ? it.model2 : it.m_icon)); + + sz = draw_getimagesize(icon); + sz2 = vec2(iconsize.y*(sz.x/sz.y), iconsize.y); + if(autocvar__hud_configure) + str_name = "Mega armor"; + else + str_name = ((last_pickup_count > 1) ? sprintf("%s (x%d)", it.m_name, last_pickup_count) : it.m_name); + + float a; + float fade_out_time = min(display_time, autocvar_hud_panel_pickup_fade_out); + + if(autocvar__hud_configure) + a = 1; + else if(time < last_pickup_time + display_time - fade_out_time) + a = 1; + else + a = (last_pickup_time + display_time - time) / fade_out_time; + + if(autocvar_hud_panel_pickup_showtimer) { + // 1 will show the timer always + // 2 will show the timer only if spectating + // forbid serverflag will force the 2nd behavior + if((autocvar_hud_panel_pickup_showtimer == 1 && !(serverflags & SERVERFLAG_FORBID_PICKUPTIMER)) || spectatee_status) + { + if(autocvar__hud_configure) + str_timer = "13:02"; + else + str_timer = seconds_tostring(HUD_Pickup_Time(last_pickup_time)); + drawstring(pos, str_timer, fontsize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + pos.x += stringwidth(str_timer, false, fontsize) + fontsize.x * 0.25; + } + } + + drawpic(pos - eY * ((iconsize.y - fontsize.y) / 2), icon, sz2, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + pos.x += sz2.x + fontsize.x * 0.25; + str_name = textShortenToWidth(str_name, mySize.x - (pos.x - panel_pos.x), fontsize, stringwidth_nocolors); + drawstring(pos, str_name, fontsize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL); + } +} diff --git a/qcsrc/client/hud/panel/pickup.qh b/qcsrc/client/hud/panel/pickup.qh new file mode 100644 index 0000000000..503308dd22 --- /dev/null +++ b/qcsrc/client/hud/panel/pickup.qh @@ -0,0 +1,14 @@ +#pragma once +#include "../panel.qh" + +bool autocvar_hud_panel_pickup; +bool autocvar_hud_panel_pickup_dynamichud = true; +int autocvar_hud_panel_pickup_showtimer = 1; +float autocvar_hud_panel_pickup_iconsize = 1.5; +float autocvar_hud_panel_pickup_time = 3; +float autocvar_hud_panel_pickup_fade_out = 0.15; + +entity last_pickup_item; +int last_pickup_count; + +void Pickup_Update(entity it, int count); diff --git a/qcsrc/client/hud/panel/timer.qc b/qcsrc/client/hud/panel/timer.qc index 00a231b7cf..aa0c73b5bf 100644 --- a/qcsrc/client/hud/panel/timer.qc +++ b/qcsrc/client/hud/panel/timer.qc @@ -62,8 +62,8 @@ void HUD_Timer() mySize -= '2 2 0' * panel_bg_padding; } - string timer; - string subtimer = string_null; + string timer_str = string_null; + string subtimer_str = string_null; string subtext = string_null; float curtime, timelimit, timeleft; vector timer_size, subtext_size, subtimer_size; @@ -73,10 +73,7 @@ void HUD_Timer() // Use real or frozen time and get the time limit curtime = (intermission_time ? intermission_time : time); - if(warmup_stage) - timelimit = STAT(WARMUP_TIMELIMIT); - else - timelimit = STAT(TIMELIMIT) * 60; + timelimit = (warmup_stage ? STAT(WARMUP_TIMELIMIT) : STAT(TIMELIMIT) * 60); // Calculate time left timeleft = HUD_Timer_TimeLeft(curtime, STAT(GAMESTARTTIME), timelimit); @@ -87,16 +84,16 @@ void HUD_Timer() // Timer text if (autocvar_hud_panel_timer_increment || timelimit <= 0) - timer = seconds_tostring(HUD_Timer_TimeElapsed(curtime, STAT(GAMESTARTTIME))); + timer = HUD_Timer_TimeElapsed(curtime, STAT(GAMESTARTTIME)); else - timer = seconds_tostring(timeleft); + timer = timeleft; // Secondary timer for round-based game modes if(STAT(ROUNDSTARTTIME) && autocvar_hud_panel_timer_secondary) { if(STAT(ROUNDSTARTTIME) == -1) { // Round can't start - subtimer = "--:--"; + subtimer_str = "--:--"; subtimer_color = '1 0 0'; } else { float round_curtime, round_timelimit, round_timeleft; @@ -114,9 +111,9 @@ void HUD_Timer() // Subtimer text if (autocvar_hud_panel_timer_increment || round_timelimit <= 0) - subtimer = seconds_tostring(HUD_Timer_TimeElapsed(round_curtime, STAT(ROUNDSTARTTIME))); + subtimer_str = seconds_tostring(HUD_Timer_TimeElapsed(round_curtime, STAT(ROUNDSTARTTIME))); else - subtimer = seconds_tostring(round_timeleft); + subtimer_str = seconds_tostring(round_timeleft); } } @@ -142,17 +139,18 @@ void HUD_Timer() subtext_size = vec2(mySize.x, mySize.y / 3); timer_size = vec2(mySize.x, mySize.y - subtext_size.y); subtimer_size = vec2(mySize.x / 3, mySize.y - subtext_size.y); + timer_str = seconds_tostring(timer); panel_size.y -= subtext_size.y; HUD_Panel_DrawBg(); - if(subtimer) { + if(subtimer_str) { float subtimer_padding = subtimer_size.y / 5; timer_size.x -= subtimer_size.x; - drawstring_aspect(pos + eX * timer_size.x + eY * subtimer_padding, (swap ? timer : subtimer), subtimer_size - eY * subtimer_padding * 2, (swap ? timer_color : subtimer_color), panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(pos + eX * timer_size.x + eY * subtimer_padding, (swap ? timer_str : subtimer_str), subtimer_size - eY * subtimer_padding * 2, (swap ? timer_color : subtimer_color), panel_fg_alpha, DRAWFLAG_NORMAL); } - drawstring_aspect(pos, (swap ? subtimer : timer), timer_size, (swap ? subtimer_color : timer_color), panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring_aspect(pos, (swap ? subtimer_str : timer_str), timer_size, (swap ? subtimer_color : timer_color), panel_fg_alpha, DRAWFLAG_NORMAL); if(subtext) drawstring_aspect(pos + eY * timer_size.y, subtext, subtext_size, '0 1 0', panel_fg_alpha, DRAWFLAG_NORMAL); diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index a60a9de13f..e0c17a7a12 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -17,6 +17,7 @@ const int SERVERFLAG_ALLOW_FULLBRIGHT = BIT(0); const int SERVERFLAG_TEAMPLAY = BIT(1); const int SERVERFLAG_PLAYERSTATS = BIT(2); const int SERVERFLAG_PLAYERSTATS_CUSTOM = BIT(3); +const int SERVERFLAG_FORBID_PICKUPTIMER = BIT(4); const int SPECIES_HUMAN = 0; const int SPECIES_ROBOT_SOLID = 1; diff --git a/qcsrc/common/items/inventory.qh b/qcsrc/common/items/inventory.qh index 22a4d94c38..6f6ebdc452 100644 --- a/qcsrc/common/items/inventory.qh +++ b/qcsrc/common/items/inventory.qh @@ -37,7 +37,10 @@ STATIC_INIT(Inventory) #endif #ifdef CSQC +#include + Inventory g_inventory; + void Inventory_remove(entity this) { if(g_inventory == this) @@ -63,11 +66,20 @@ NET_HANDLE(ENT_CLIENT_INVENTORY, bool isnew) .int fld = inv_items[it.m_id]; int prev = this.(fld); int next = this.(fld) = ReadByte(); + + Pickup_Update(it, next - prev); LOG_DEBUGF("%s: %.0f -> %.0f", it.m_name, prev, next); } } return true; } + +NET_HANDLE(TE_CSQC_WEAPONPICKUP, bool isnew) +{ + const Weapon it = REGISTRY_GET(Weapons, ReadByte()); + Pickup_Update(it, 1); + return true; +} #endif #ifdef SVQC diff --git a/qcsrc/common/items/item/ammo.qh b/qcsrc/common/items/item/ammo.qh index 802922cc49..179cc9a1d7 100644 --- a/qcsrc/common/items/item/ammo.qh +++ b/qcsrc/common/items/item/ammo.qh @@ -53,7 +53,7 @@ REGISTER_ITEM(Shells, Shells) { this.m_model = MDL_Shells_ITEM; #endif this.netname = "shells"; - this.m_name = _("shells"); + this.m_name = _("Shells"); this.m_icon = "ammo_shells"; #ifdef SVQC this.m_botvalue = 1000; @@ -89,7 +89,7 @@ REGISTER_ITEM(Bullets, Bullets) { this.m_model = MDL_Bullets_ITEM; #endif this.netname = "bullets"; - this.m_name = _("bullets"); + this.m_name = _("Bullets"); this.m_icon = "ammo_bullets"; #ifdef SVQC this.m_botvalue = 1500; @@ -121,7 +121,7 @@ REGISTER_ITEM(Rockets, Ammo) { this.m_model = MDL_Rockets_ITEM; #endif this.netname = "rockets"; - this.m_name = _("rockets"); + this.m_name = _("Rockets"); this.m_icon = "ammo_rockets"; #ifdef SVQC this.m_botvalue = 1500; @@ -153,7 +153,7 @@ REGISTER_ITEM(Cells, Ammo) { this.m_model = MDL_Cells_ITEM; #endif this.netname = "cells"; - this.m_name = _("cells"); + this.m_name = _("Cells"); this.m_icon = "ammo_cells"; #ifdef SVQC this.m_botvalue = 1500; @@ -185,7 +185,7 @@ REGISTER_ITEM(Plasma, Ammo) { this.m_model = MDL_Plasma_ITEM; #endif this.netname = "plasma"; - this.m_name = _("plasma"); + this.m_name = _("Plasma"); this.m_icon = "ammo_plasma"; #ifdef SVQC this.m_botvalue = 1500; diff --git a/qcsrc/common/items/item/jetpack.qh b/qcsrc/common/items/item/jetpack.qh index e9c5627c84..0ece1bf32c 100644 --- a/qcsrc/common/items/item/jetpack.qh +++ b/qcsrc/common/items/item/jetpack.qh @@ -68,7 +68,7 @@ REGISTER_ITEM(JetpackFuel, Ammo) { this.m_model = MDL_JetpackFuel_ITEM; #endif this.netname = "fuel"; - this.m_name = _("fuel"); + this.m_name = _("Fuel"); this.m_icon = "ammo_fuel"; #ifdef SVQC this.m_botvalue = 2000; diff --git a/qcsrc/common/net_linked.qh b/qcsrc/common/net_linked.qh index e1586c2034..f9e40965b8 100644 --- a/qcsrc/common/net_linked.qh +++ b/qcsrc/common/net_linked.qh @@ -7,6 +7,7 @@ REGISTER_NET_TEMP(TE_CSQC_PINGPLREPORT) REGISTER_NET_TEMP(TE_CSQC_WEAPONCOMPLAIN) REGISTER_NET_TEMP(TE_CSQC_SERVERWELCOME) REGISTER_NET_TEMP(TE_CSQC_VEHICLESETUP) +REGISTER_NET_TEMP(TE_CSQC_WEAPONPICKUP) const int RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder const int RACE_NET_CHECKPOINT_CLEAR = 1; diff --git a/qcsrc/common/notifications/all.qh b/qcsrc/common/notifications/all.qh index 2a7e68ad82..9d39c21991 100644 --- a/qcsrc/common/notifications/all.qh +++ b/qcsrc/common/notifications/all.qh @@ -656,7 +656,7 @@ string notif_arg_item_wepammo(float f1, float f2) case RES_FUEL: ammoitems = ITEM_JetpackFuel.m_name; break; default: return ""; // doesn't use ammo } - return sprintf(_(" with %d %s"), f2, ammoitems); + return sprintf(_(" with %d %s"), f2, strtolower(ammoitems)); } diff --git a/qcsrc/menu/xonotic/_mod.inc b/qcsrc/menu/xonotic/_mod.inc index 2ee34aef81..524c659153 100644 --- a/qcsrc/menu/xonotic/_mod.inc +++ b/qcsrc/menu/xonotic/_mod.inc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/menu/xonotic/_mod.qh b/qcsrc/menu/xonotic/_mod.qh index 64475f6a18..b4fe3d836c 100644 --- a/qcsrc/menu/xonotic/_mod.qh +++ b/qcsrc/menu/xonotic/_mod.qh @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_pickup.qc b/qcsrc/menu/xonotic/dialog_hudpanel_pickup.qc new file mode 100644 index 0000000000..95cb5fe3ee --- /dev/null +++ b/qcsrc/menu/xonotic/dialog_hudpanel_pickup.qc @@ -0,0 +1,39 @@ +#include "dialog_hudpanel_pickup.qh" + +#include "checkbox.qh" +#include "textlabel.qh" +#include "slider.qh" +#include "textslider.qh" + +void XonoticHUDPickupDialog_fill(entity me) +{ + entity e; + string panelname = "pickup"; + + dialog_hudpanel_main_checkbox(me, panelname); + + dialog_hudpanel_main_settings(me, panelname); + + me.TR(me); + me.TD(me, 1, 4, e = makeXonoticTextLabel(0, _("Pickup messages:"))); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Message duration:"))); + me.TD(me, 1, 2.6, e = makeXonoticSlider(1, 5, 1, "hud_panel_pickup_time")); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Fade time:"))); + me.TD(me, 1, 2.6, e = makeXonoticSlider(0, 1, 0.05, "hud_panel_pickup_fade_out")); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Show timer:"))); + me.TD(me, 1, 2, e = makeXonoticTextSlider("hud_panel_pickup_showtimer")); + e.addValue(e, _("Never"), "0"); + e.addValue(e, _("Always"), "1"); + e.addValue(e, _("Spectating"), "2"); + e.configureXonoticTextSliderValues(e); + me.TR(me); + me.TDempty(me, 0.2); + me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, _("Icon size scale:"))); + me.TD(me, 1, 2.6, e = makeXonoticSlider(1, 3, 0.1, "hud_panel_pickup_iconsize")); +} diff --git a/qcsrc/menu/xonotic/dialog_hudpanel_pickup.qh b/qcsrc/menu/xonotic/dialog_hudpanel_pickup.qh new file mode 100644 index 0000000000..2ceb89d62b --- /dev/null +++ b/qcsrc/menu/xonotic/dialog_hudpanel_pickup.qh @@ -0,0 +1,13 @@ +#pragma once + +#include "rootdialog.qh" +CLASS(XonoticHUDPickupDialog, XonoticRootDialog) + METHOD(XonoticHUDPickupDialog, fill, void(entity)); + ATTRIB(XonoticHUDPickupDialog, title, string, _("Pickup Panel")); + ATTRIB(XonoticHUDPickupDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT); + ATTRIB(XonoticHUDPickupDialog, intendedWidth, float, 0.4); + ATTRIB(XonoticHUDPickupDialog, rows, float, 15.5); + ATTRIB(XonoticHUDPickupDialog, columns, float, 4); + ATTRIB(XonoticHUDPickupDialog, name, string, "HUDpickup"); + ATTRIB(XonoticHUDPickupDialog, requiresConnection, float, true); +ENDCLASS(XonoticHUDPickupDialog) diff --git a/qcsrc/menu/xonotic/mainwindow.qc b/qcsrc/menu/xonotic/mainwindow.qc index e215e5080b..039d3452fd 100644 --- a/qcsrc/menu/xonotic/mainwindow.qc +++ b/qcsrc/menu/xonotic/mainwindow.qc @@ -20,6 +20,7 @@ #include "dialog_hudpanel_timer.qh" #include "dialog_hudpanel_vote.qh" #include "dialog_hudpanel_weapons.qh" +#include "dialog_hudpanel_pickup.qh" #include "dialog_hudpanel_engineinfo.qh" #include "dialog_hudpanel_infomessages.qh" #include "dialog_hudpanel_physics.qh" @@ -158,6 +159,10 @@ void MainWindow_configureMainWindow(entity me) i.configureDialog(i); me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); + i = NEW(XonoticHUDPickupDialog); + i.configureDialog(i); + me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); + i = NEW(XonoticHUDInfoMessagesDialog); i.configureDialog(i); me.addItemRightCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); diff --git a/qcsrc/server/items/items.qc b/qcsrc/server/items/items.qc index 347e956a3e..e68d858a8e 100644 --- a/qcsrc/server/items/items.qc +++ b/qcsrc/server/items/items.qc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -475,6 +476,15 @@ bool Item_GiveAmmoTo(entity item, entity player, Resource res_type, float ammoma return true; } +void Item_NotifyWeapon(entity player, int wep) +{ + FOREACH_CLIENT(IS_REAL_CLIENT(it) && (it == player || (IS_SPEC(it) && it.enemy == player)), { + msg_entity = it; + WriteHeader(MSG_ONE, TE_CSQC_WEAPONPICKUP); + WriteByte(MSG_ONE, wep); + }); +} + bool Item_GiveTo(entity item, entity player) { // if nothing happens to player, just return without taking the item @@ -509,15 +519,18 @@ bool Item_GiveTo(entity item, entity player) pickedup |= Item_GiveAmmoTo(item, player, RES_FUEL, g_pickup_fuel_max); if (item.itemdef.instanceOfWeaponPickup) { - WepSet w; + WepSet w, wp; w = STAT(WEAPONS, item); - w &= ~STAT(WEAPONS, player); + wp = w & ~STAT(WEAPONS, player); - if (w || (item.spawnshieldtime && item.pickup_anyway > 0)) + if (wp || (item.spawnshieldtime && item.pickup_anyway > 0)) { pickedup = true; FOREACH(Weapons, it != WEP_Null, { if(w & (it.m_wepset)) + Item_NotifyWeapon(player, it.m_id); + + if(wp & (it.m_wepset)) { for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { diff --git a/qcsrc/server/weapons/common.qc b/qcsrc/server/weapons/common.qc index ff6f8ea4cb..a0dd86f519 100644 --- a/qcsrc/server/weapons/common.qc +++ b/qcsrc/server/weapons/common.qc @@ -35,10 +35,6 @@ void W_GiveWeapon(entity e, int wep) if (!wep) return; STAT(WEAPONS, e) |= WepSet_FromWeapon(REGISTRY_GET(Weapons, wep)); - - if (IS_PLAYER(e)) { - Send_Notification(NOTIF_ONE, e, MSG_MULTI, ITEM_WEAPON_GOT, wep); - } } void W_PlayStrengthSound(entity player) diff --git a/qcsrc/server/world.qc b/qcsrc/server/world.qc index cdc7d31698..47198b7d98 100644 --- a/qcsrc/server/world.qc +++ b/qcsrc/server/world.qc @@ -2100,6 +2100,10 @@ void readlevelcvars() if(cvar("sv_allow_fullbright")) serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT; + serverflags &= ~SERVERFLAG_FORBID_PICKUPTIMER; + if(cvar("sv_forbid_pickuptimer")) + serverflags |= SERVERFLAG_FORBID_PICKUPTIMER; + sv_ready_restart_after_countdown = cvar("sv_ready_restart_after_countdown"); warmup_stage = cvar("g_warmup"); diff --git a/ruleset-XPM.cfg b/ruleset-XPM.cfg index 2629ceb7ad..10bad91b2e 100644 --- a/ruleset-XPM.cfg +++ b/ruleset-XPM.cfg @@ -27,4 +27,5 @@ g_vehicles 0 sv_showspectators 0 sv_taunt 0 sv_maxidle_playertospectator 0 +sv_forbid_pickuptimer 1 // we don't want people seeing their pickup times in competitive matches g_ca_spectate_enemies -1 // block freeroam camera in CA matches diff --git a/xonotic-server.cfg b/xonotic-server.cfg index 76fca62699..cf7544a081 100644 --- a/xonotic-server.cfg +++ b/xonotic-server.cfg @@ -529,6 +529,9 @@ set sv_db_saveasdump 0 "write server.db in dump format (loads slower, easier to // allow fullbright set sv_allow_fullbright 1 "when set, clients may use r_fullbright on this server without getting a night vision effect overlay" +// forbid pickup timer +set sv_forbid_pickuptimer 0 "when set, clients won't be able to see the time they picked up an item" + // auto-teams (team selection by player ID) // any player not listed is forced to spectate set g_forced_team_red "" "list of player IDs for red team" -- 2.39.2