From c8f9f31a9d55097aab4282cd8ffc5e36aa2ef1af Mon Sep 17 00:00:00 2001 From: terencehill Date: Wed, 10 May 2023 16:55:31 +0000 Subject: [PATCH] Scoreboard: allow showing average scores per round --- .gitlab-ci.yml | 2 +- _hud_common.cfg | 1 + qcsrc/client/hud/panel/scoreboard.qc | 58 +++++++++++++++++++++++----- qcsrc/common/scores.qh | 2 + qcsrc/common/util.qc | 4 +- qcsrc/common/util.qh | 2 +- qcsrc/server/round_handler.qc | 4 ++ qcsrc/server/scores.qc | 4 +- qcsrc/server/scores_rules.qc | 2 + 9 files changed, 64 insertions(+), 15 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8ba5c1806..478613507 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -75,7 +75,7 @@ test_sv_game: - wget -nv -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints - wget -nv -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache - - EXPECT=fe5dec36cb304c55acee73afd1e09c0a + - EXPECT=f2226bf353b6ff3dd3c489a742ce4e6a - HASH=$(${ENGINE} +timestamps 1 +exec serverbench.cfg | tee /dev/stderr | sed -e 's,^\[[^]]*\] ,,' diff --git a/_hud_common.cfg b/_hud_common.cfg index 6339895ea..c96c90bb9 100644 --- a/_hud_common.cfg +++ b/_hud_common.cfg @@ -145,6 +145,7 @@ seta hud_panel_scoreboard_team_size_position 0 "where to show the team size (0 = seta hud_panel_scoreboard_playerid 0 "show player id (server entity number) next to player's name" seta hud_panel_scoreboard_playerid_prefix "#" "player id prefix" seta hud_panel_scoreboard_playerid_suffix " " "player id suffix" +seta hud_panel_scoreboard_scores_per_round "0" "show average scores per round" seta hud_panel_scoreboard_accuracy_showdelay 2 "how long to delay displaying accuracy below the scoreboard if it's too far down" seta hud_panel_scoreboard_accuracy_showdelay_minpos 0.75 "delay displaying the accuracy panel only if its position is lower than this percentage of the screen height from the top" diff --git a/qcsrc/client/hud/panel/scoreboard.qc b/qcsrc/client/hud/panel/scoreboard.qc index 484968a9c..566f5a695 100644 --- a/qcsrc/client/hud/panel/scoreboard.qc +++ b/qcsrc/client/hud/panel/scoreboard.qc @@ -106,9 +106,16 @@ float autocvar_hud_panel_scoreboard_minwidth = 0.4; bool autocvar_hud_panel_scoreboard_playerid = false; string autocvar_hud_panel_scoreboard_playerid_prefix = "#"; string autocvar_hud_panel_scoreboard_playerid_suffix = " "; +bool autocvar_hud_panel_scoreboard_scores_per_round; float scoreboard_time; +SHUTDOWN(scoreboard) +{ + if(autocvar_hud_panel_scoreboard_scores_per_round) + cvar_set("hud_panel_scoreboard_scores_per_round", "0"); +} + // mode 0: returns translated label // mode 1: prints name and description of all the labels string Label_getInfo(string label, int mode) @@ -153,6 +160,7 @@ string Label_getInfo(string label, int mode) case "returns": if (!mode) return CTX(_("SCO^returns")); else LOG_HELP(strcat("^3", "returns", " ^7", _("Number of flag returns"))); case "revivals": if (!mode) return CTX(_("SCO^revivals")); else LOG_HELP(strcat("^3", "revivals", " ^7", _("Number of revivals"))); case "rounds": if (!mode) return CTX(_("SCO^rounds won")); else LOG_HELP(strcat("^3", "rounds", " ^7", _("Number of rounds won"))); + case "rounds_pl": if (!mode) return CTX(_("SCO^rounds played"));else LOG_HELP(strcat("^3", "rounds_pl", " ^7", _("Number of rounds played"))); case "score": if (!mode) return CTX(_("SCO^score")); else LOG_HELP(strcat("^3", "score", " ^7", _("Total score"))); case "suicides": if (!mode) return CTX(_("SCO^suicides")); else LOG_HELP(strcat("^3", "suicides", " ^7", _("Number of suicides"))); case "sum": if (!mode) return CTX(_("SCO^sum")); else LOG_HELP(strcat("^3", "sum", " ^7", _("Number of kills minus deaths"))); @@ -467,6 +475,13 @@ float HUD_Scoreboard_InputEvent(float bInputType, float nPrimary, float nSeconda } } } + else if(nPrimary == 'r' && (hudShiftState & S_CTRL)) + { + if (!key_pressed) + return true; + if (scoreboard_selected_panel == SB_PANEL_SCOREBOARD) + localcmd("toggle hud_panel_scoreboard_scores_per_round\n"); + } else if(nPrimary == 't' && (hudShiftState & S_CTRL)) { if (!key_pressed) @@ -967,7 +982,7 @@ string Scoreboard_GetName(entity pl) return entcs_GetName(pl.sv_entnum); } -string Scoreboard_GetField(entity pl, PlayerScoreField field) +string Scoreboard_GetField(entity pl, PlayerScoreField field, bool per_round) { float tmp, num, denom; int f; @@ -979,6 +994,9 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field) sbt_field_icon0_rgb = '1 1 1'; sbt_field_icon1_rgb = '1 1 1'; sbt_field_icon2_rgb = '1 1 1'; + int rounds_played = 0; + if (per_round) + rounds_played = pl.(scores(SP_ROUNDS_PL)); switch(field) { case SP_PING: @@ -1015,6 +1033,8 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field) case SP_FRAGS: f = pl.(scores(SP_KILLS)); f -= pl.(scores(SP_SUICIDES)); + if (rounds_played) + return sprintf("%.1f", f / rounds_played); return ftos(f); case SP_KDRATIO: @@ -1023,12 +1043,23 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field) if(denom == 0) { sbt_field_rgb = '0 1 0'; - str = sprintf("%d", num); + if (rounds_played) + str = sprintf("%.1f", num / rounds_played); + else + str = sprintf("%d", num); } else if(num <= 0) { sbt_field_rgb = '1 0 0'; - str = sprintf("%.1f", num/denom); + if (rounds_played) + str = sprintf("%.2f", num / (denom * rounds_played)); + else + str = sprintf("%.1f", num / denom); } else - str = sprintf("%.1f", num/denom); + { + if (rounds_played) + str = sprintf("%.2f", num / (denom * rounds_played)); + else + str = sprintf("%.1f", num / denom); + } return str; case SP_SUM: @@ -1042,6 +1073,8 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field) } else { sbt_field_rgb = '1 0 0'; } + if (rounds_played) + return sprintf("%.1f", f / rounds_played); return ftos(f); case SP_ELO: @@ -1067,7 +1100,12 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field) return ftos(fps); } + case SP_ROUNDS_PL: + return ftos(pl.(scores(field))); + case SP_DMG: case SP_DMGTAKEN: + if (rounds_played) + return sprintf("%.2f k", pl.(scores(field)) / (1000 * rounds_played)); return sprintf("%.1f k", pl.(scores(field)) / 1000); default: case SP_SCORE: @@ -1079,7 +1117,7 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field) sbt_field_rgb = '0 1 1'; else sbt_field_rgb = '1 1 1'; - return ScoreString(f, tmp); + return ScoreString(f, tmp, rounds_played); } //return "error"; } @@ -1253,7 +1291,7 @@ void Scoreboard_DrawItem(vector item_pos, vector rgb, entity pl, bool is_self, i pos.x += sbt_field_size[i] + hud_fontsize.x; continue; } - str = Scoreboard_GetField(pl, field); + str = Scoreboard_GetField(pl, field, autocvar_hud_panel_scoreboard_scores_per_round); str = Scoreboard_FixColumnWidth(i, str); pos.x += sbt_field_size[i] + hud_fontsize.x; @@ -1289,7 +1327,7 @@ void Scoreboard_DrawItem(vector item_pos, vector rgb, entity pl, bool is_self, i continue; } - str = Scoreboard_GetField(pl, field); + str = Scoreboard_GetField(pl, field, autocvar_hud_panel_scoreboard_scores_per_round); str = Scoreboard_FixColumnWidth(i, str); if(field == SP_NAME) { @@ -1358,10 +1396,10 @@ vector Scoreboard_DrawOthers(vector item_pos, vector rgb, int this_team, entity if(this_team == NUM_SPECTATOR) { if(autocvar_hud_panel_scoreboard_spectators_showping) - field = Scoreboard_GetField(pl, SP_PING); + field = Scoreboard_GetField(pl, SP_PING, autocvar_hud_panel_scoreboard_scores_per_round); } else if(autocvar_hud_panel_scoreboard_others_showscore) - field = Scoreboard_GetField(pl, SP_SCORE); + field = Scoreboard_GetField(pl, SP_SCORE, autocvar_hud_panel_scoreboard_scores_per_round); string str = entcs_GetName(pl.sv_entnum); if (autocvar_hud_panel_scoreboard_playerid) @@ -2156,7 +2194,7 @@ string Scoreboard_Fraglimit_Draw(float limit, bool is_leadlimit) { string s_label = (teamplay) ? teamscores_label(ts_primary) : scores_label(ps_primary); int s_flags = (teamplay) ? teamscores_flags(ts_primary) : scores_flags(ps_primary); - return sprintf((is_leadlimit ? _("^2+%s %s") : _("^5%s %s")), ScoreString(s_flags, limit), + return sprintf((is_leadlimit ? _("^2+%s %s") : _("^5%s %s")), ScoreString(s_flags, limit, 0), (s_label == "score") ? CTX(_("SCO^points")) : (s_label == "fastest") ? "" : TranslateScoresLabel(s_label)); } diff --git a/qcsrc/common/scores.qh b/qcsrc/common/scores.qh index 3449f2b53..e13d3030c 100644 --- a/qcsrc/common/scores.qh +++ b/qcsrc/common/scores.qh @@ -68,6 +68,8 @@ REGISTER_SP(SUICIDES); REGISTER_SP(DMG); REGISTER_SP(DMGTAKEN); +REGISTER_SP(ROUNDS_PL); + REGISTER_SP(ELO); // not sortable REGISTER_SP(FPS); // not sortable diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc index 98418767a..df54e3536 100644 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@ -372,7 +372,7 @@ void depthfirst(entity start, .entity up, .entity downleft, .entity right, void( } #ifdef GAMEQC -string ScoreString(int pFlags, float pValue) +string ScoreString(int pFlags, float pValue, int rounds_played) { string valstr; float l; @@ -385,6 +385,8 @@ string ScoreString(int pFlags, float pValue) valstr = (pValue < 256 ? count_ordinal(pValue) : _("N/A")); else if(pFlags & SFL_TIME) valstr = TIME_ENCODED_TOSTRING(pValue, true); + else if (rounds_played) + valstr = sprintf("%.1f", pValue / rounds_played); else valstr = ftos(pValue); diff --git a/qcsrc/common/util.qh b/qcsrc/common/util.qh index 4d011ce97..01933cb34 100644 --- a/qcsrc/common/util.qh +++ b/qcsrc/common/util.qh @@ -96,7 +96,7 @@ const float TIME_FACTOR = 100; #define TIME_DECODE(n) ((n) / TIME_FACTOR) #ifdef GAMEQC -string ScoreString(float vflags, float value); +string ScoreString(float vflags, float value, int rounds_played); #endif vector decompressShortVector(float data); diff --git a/qcsrc/server/round_handler.qc b/qcsrc/server/round_handler.qc index b22ba178d..bb890e980 100644 --- a/qcsrc/server/round_handler.qc +++ b/qcsrc/server/round_handler.qc @@ -1,6 +1,7 @@ #include "round_handler.qh" #include +#include #include #include #include @@ -39,6 +40,9 @@ void round_handler_Think(entity this) int f = this.cnt - 1; if (f == 0) { + FOREACH_CLIENT((IS_PLAYER(it) || INGAME(it)), { + GameRules_scoring_add(it, ROUNDS_PL, 1); + }); this.cnt = 0; this.round_endtime = (this.round_timelimit) ? time + this.round_timelimit : 0; this.nextthink = time; diff --git a/qcsrc/server/scores.qc b/qcsrc/server/scores.qc index 2cedc4ade..5e1c8d9db 100644 --- a/qcsrc/server/scores.qc +++ b/qcsrc/server/scores.qc @@ -864,7 +864,7 @@ void Score_NicePrint_Team(entity to, float t, float w) { fl = teamscores_flags(i); sc = sk.(teamscores(i)); - s = strcat(s, " ", Score_NicePrint_ItemColor(fl), ScoreString(fl, sc)); + s = strcat(s, " ", Score_NicePrint_ItemColor(fl), ScoreString(fl, sc, 0)); } } else @@ -912,7 +912,7 @@ void Score_NicePrint_Player(entity to, entity p, float w) { fl = scores_flags(it); sc = sk.(scores(it)); - s = strcat(s, " ", Score_NicePrint_ItemColor(fl), strpad(-w, ScoreString(fl, sc))); + s = strcat(s, " ", Score_NicePrint_ItemColor(fl), strpad(-w, ScoreString(fl, sc, 0))); } }); diff --git a/qcsrc/server/scores_rules.qc b/qcsrc/server/scores_rules.qc index 95f8b482e..2db5ae705 100644 --- a/qcsrc/server/scores_rules.qc +++ b/qcsrc/server/scores_rules.qc @@ -58,6 +58,8 @@ void ScoreRules_basics(int teams, float sprio, float stprio, float score_enabled ScoreInfo_SetLabel_PlayerScore(SP_ELO, "elo", SFL_NOT_SORTABLE); } + ScoreInfo_SetLabel_PlayerScore(SP_ROUNDS_PL, "rounds_pl", 0); + if(STAT(SHOWFPS)) ScoreInfo_SetLabel_PlayerScore(SP_FPS, "fps", SFL_NOT_SORTABLE); } -- 2.39.2