]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Change server's player sorting algorithm to work as the scoreboard's one, so it doesn...
authorterencehill <piuntn@gmail.com>
Fri, 27 May 2022 20:49:13 +0000 (22:49 +0200)
committerterencehill <piuntn@gmail.com>
Sat, 28 May 2022 12:06:04 +0000 (14:06 +0200)
Remove hardcoded priority list (sb_extra_sorting_field) from scoreboard's algorithm, score registration order can be used now.

qcsrc/client/hud/panel/scoreboard.qc
qcsrc/common/scores.qh
qcsrc/server/scores.qc

index 393e15c13feb92b91601915fafa1355248a66e35..3f6fced99e76de0fca4308f67fc891ed27f16fe4 100644 (file)
@@ -167,8 +167,6 @@ string Label_getInfo(string label, int mode)
 void PrintScoresLabels() { Label_getInfo(string_null, 1); }
 string TranslateScoresLabel(string label) { return Label_getInfo(label, 0); }
 
-#define SB_EXTRA_SORTING_FIELDS 5
-PlayerScoreField sb_extra_sorting_field[SB_EXTRA_SORTING_FIELDS];
 void Scoreboard_InitScores()
 {
        int i, f;
@@ -183,13 +181,6 @@ void Scoreboard_InitScores()
                        ps_primary = it;
                if(f == SFL_SORT_PRIO_SECONDARY)
                        ps_secondary = it;
-               if(ps_primary == it || ps_secondary == it)
-                       continue;
-               if (scores_label(it) == "kills")      sb_extra_sorting_field[0] = it;
-               if (scores_label(it) == "deaths")     sb_extra_sorting_field[1] = it;
-               if (scores_label(it) == "suicides")   sb_extra_sorting_field[2] = it;
-               if (scores_label(it) == "dmg")        sb_extra_sorting_field[3] = it;
-               if (scores_label(it) == "dmgtaken")   sb_extra_sorting_field[4] = it;
        });
        if(ps_secondary == NULL)
                ps_secondary = ps_primary;
@@ -275,27 +266,20 @@ float Scoreboard_ComparePlayerScores(entity left, entity right)
                return false;
        }
 
-       entity fld = NULL;
-       int r;
-       for (int i = -2; i < SB_EXTRA_SORTING_FIELDS; ++i)
-       {
-               if (i < 0)
-               {
-                       if (!fld) fld = ps_primary;
-                       else if (ps_secondary == ps_primary) continue;
-                       else fld = ps_secondary;
-               }
-               else
-               {
-                       fld = sb_extra_sorting_field[i];
-                       if (fld == ps_primary || fld == ps_secondary) continue;
-               }
-               if (!fld) continue;
+       int res = Scoreboard_CompareScore(left.scores(ps_primary), right.scores(ps_primary), scores_flags(ps_primary));
+       if (res >= 0) return res;
 
-               r = Scoreboard_CompareScore(left.scores(fld), right.scores(fld), scores_flags(fld));
-               if (r >= 0) return r;
+       if (ps_secondary && ps_secondary != ps_primary)
+       {
+               res = Scoreboard_CompareScore(left.scores(ps_secondary), right.scores(ps_secondary), scores_flags(ps_secondary));
+               if (res >= 0) return res;
        }
 
+       FOREACH(Scores, (it != ps_primary && it != ps_secondary), {
+               res = Scoreboard_CompareScore(left.scores(it), right.scores(it), scores_flags(it));
+               if (res >= 0) return res;
+       });
+
        if (left.sv_entnum < right.sv_entnum)
                return true;
 
index 28d6ad57637f6cbfac4f713893308e62faad2bef..630df90c2bcbec26941760e264d5867abaed0759 100644 (file)
@@ -5,7 +5,8 @@
 #define REGISTER_SP(id) REGISTER(Scores, SP, id, m_id, new_pure(PlayerScoreField))
 REGISTRY(Scores, MAX_SCORE);
 REGISTER_REGISTRY(Scores)
-REGISTRY_SORT(Scores);
+// do not sort alphabetically, player sort priority is based on score registration order
+//REGISTRY_SORT(Scores);
 REGISTRY_CHECK(Scores);
 
 REGISTRY_DEFINE_GET(Scores, NULL)
@@ -14,70 +15,41 @@ STATIC_INIT(Scores_renumber) { FOREACH(Scores, true, it.m_id = i); }
 /*
  * Score indices
  */
-
 #ifdef GAMEQC
-// fields not networked via the score system
-REGISTER_SP(END);
-
-REGISTER_SP(PING);
-REGISTER_SP(PL);
-REGISTER_SP(NAME);
-REGISTER_SP(SEPARATOR);
-
-REGISTER_SP(KDRATIO); // kills / deaths
-REGISTER_SP(SUM); // kills - deaths
-REGISTER_SP(FRAGS); // kills - suicides
-
 // networked fields
+// NOTE: score registration order is used as player sort priority (after primary and secondary)
 
-REGISTER_SP(SCORE);
-
-REGISTER_SP(DMG);
-REGISTER_SP(DMGTAKEN);
+// TODO: move gamemode scores to gamemode files
+// TODO: allow gamemodes to fully customize player sorting priority, even the common ones
 
-REGISTER_SP(KILLS);
-REGISTER_SP(DEATHS);
-REGISTER_SP(SUICIDES);
-REGISTER_SP(TEAMKILLS);
-
-REGISTER_SP(ELO);
-
-REGISTER_SP(FPS);
-
-// TODO: move to common mutators
-
-REGISTER_SP(RACE_TIME);
 REGISTER_SP(RACE_LAPS);
+REGISTER_SP(RACE_TIME);
 REGISTER_SP(RACE_FASTEST);
 
-//REGISTER_SP(CTS_TIME);
-//REGISTER_SP(CTS_LAPS);
-//REGISTER_SP(CTS_FASTEST);
-
 REGISTER_SP(ASSAULT_OBJECTIVES);
 
-REGISTER_SP(CTF_PICKUPS);
+REGISTER_SP(CTF_CAPS);
 REGISTER_SP(CTF_FCKILLS);
 REGISTER_SP(CTF_RETURNS);
-REGISTER_SP(CTF_CAPS);
-REGISTER_SP(CTF_CAPTIME);
 REGISTER_SP(CTF_DROPS);
+REGISTER_SP(CTF_PICKUPS);
+REGISTER_SP(CTF_CAPTIME);
 
 REGISTER_SP(DOM_TAKES);
 REGISTER_SP(DOM_TICKS);
 
 REGISTER_SP(FREEZETAG_REVIVALS);
 
+REGISTER_SP(KEEPAWAY_CARRIERKILLS);
 REGISTER_SP(KEEPAWAY_PICKUPS);
 REGISTER_SP(KEEPAWAY_BCTIME);
-REGISTER_SP(KEEPAWAY_CARRIERKILLS);
 
-REGISTER_SP(KH_PICKUPS);
 REGISTER_SP(KH_CAPS);
 REGISTER_SP(KH_KCKILLS);
-REGISTER_SP(KH_PUSHES);
-REGISTER_SP(KH_DESTROYS);
 REGISTER_SP(KH_LOSSES);
+REGISTER_SP(KH_DESTROYS);
+REGISTER_SP(KH_PUSHES);
+REGISTER_SP(KH_PICKUPS);
 
 REGISTER_SP(LMS_RANK);
 REGISTER_SP(LMS_LIVES);
@@ -85,8 +57,31 @@ REGISTER_SP(LMS_LIVES);
 REGISTER_SP(NEXBALL_GOALS);
 REGISTER_SP(NEXBALL_FAULTS);
 
-REGISTER_SP(ONS_TAKES);
 REGISTER_SP(ONS_CAPS);
+REGISTER_SP(ONS_TAKES);
+
+REGISTER_SP(SCORE);
+REGISTER_SP(KILLS);
+REGISTER_SP(DEATHS);
+REGISTER_SP(TEAMKILLS);
+REGISTER_SP(SUICIDES);
+REGISTER_SP(DMG);
+REGISTER_SP(DMGTAKEN);
+
+REGISTER_SP(ELO); // not sortable
+REGISTER_SP(FPS); // not sortable
+
+// fields not networked via the score system
+REGISTER_SP(END);
+
+REGISTER_SP(PING);
+REGISTER_SP(PL);
+REGISTER_SP(NAME);
+REGISTER_SP(SEPARATOR);
+
+REGISTER_SP(KDRATIO); // kills / deaths
+REGISTER_SP(SUM); // kills - deaths
+REGISTER_SP(FRAGS); // kills - suicides
 #endif
 
 
@@ -124,6 +119,7 @@ const int SFL_NOT_SORTABLE = BIT(7); // don't sort by this field
 
 /**
  * Scoring priority (NOTE: PRIMARY is used for fraglimit)
+ * NOTE: SFL_SORT_PRIO_SECONDARY value must be lower than SFL_SORT_PRIO_PRIMARY's
  */
 const int SFL_SORT_PRIO_SECONDARY = BIT(2);
 const int SFL_SORT_PRIO_PRIMARY = BIT(3);
index bc4d8947c293b32f20f6f338b3f13b854c8c42ab..5bac7240faa7bfb37be24541a8ab0a4957a3d74f 100644 (file)
@@ -23,6 +23,8 @@ var .float scores_primary;
 var .float teamscores_primary;
 float scores_flags_primary;
 float teamscores_flags_primary;
+var .float scores_secondary;
+float scores_flags_secondary;
 
 vector ScoreField_Compare(entity t1, entity t2, .float field, float fieldflags, vector previous, bool strict) // returns: cmp value, best prio
 {
@@ -145,13 +147,18 @@ float TeamScore_Compare(entity t1, entity t2, bool strict)
 {
        if(!t1 || !t2) return (!t2) - !t1;
 
+       // supporting MAX_TEAMSCORE > 2 requires keeping track of primary and secondary teamscore
+       if (MAX_TEAMSCORE > 2)
+               error("MAX_TEAMSCORE > 2 not supported");
+
+       // first compare primary, then others (don't check secondary flag since there are only 2 teamscores)
        vector result = '0 0 0';
-       float i;
-       for(i = 0; i < MAX_TEAMSCORE; ++i)
+       int i = boolean(teamscores_primary && teamscores_primary == teamscores(1));
+       result = ScoreField_Compare(t1, t2, teamscores(i), teamscores_flags(i), result, strict);
+       if (result.x == 0)
        {
-               var .float f;
-               f = teamscores(i);
-               result = ScoreField_Compare(t1, t2, f, teamscores_flags(i), result, strict);
+               i = (i + 1) % MAX_TEAMSCORE;
+               result = ScoreField_Compare(t1, t2, teamscores(i), teamscores_flags(i), result, strict);
        }
 
        if (result.x == 0 && strict)
@@ -173,6 +180,11 @@ void ScoreInfo_SetLabel_PlayerScore(PlayerScoreField i, string label, float scor
                scores_primary = scores(i);
                scores_flags_primary = scoreflags;
        }
+       else if((scoreflags & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
+       {
+               scores_secondary = scores(i);
+               scores_flags_secondary = scoreflags;
+       }
        if(label != "")
        {
                PlayerStats_GameReport_AddEvent(strcat(PLAYERSTATS_TOTAL, label));
@@ -410,10 +422,22 @@ float PlayerScore_Compare(entity t1, entity t2, bool strict)
        if(!t1 || !t2) return (!t2) - !t1;
 
        vector result = '0 0 0';
-       FOREACH(Scores, true, {
-               var .float f = scores(it);
-               result = ScoreField_Compare(t1, t2, f, scores_flags(it), result, strict);
-       });
+
+       result = ScoreField_Compare(t1, t2, scores_primary, scores_flags_primary, result, strict);
+       // NOTE: if (scores_secondary) doesn't work because it's a field pointer
+       if (result.x == 0 && scores_flags_secondary)
+               result = ScoreField_Compare(t1, t2, scores_secondary, scores_flags_secondary, result, strict);
+
+       if (result.x == 0)
+               FOREACH(Scores, true, {
+                       if (scores_flags(it) & SFL_SORT_PRIO_MASK)
+                               continue;
+                       if (scores_label(it) == "")
+                               continue;
+                       var .float f = scores(it);
+                       result = ScoreField_Compare(t1, t2, f, scores_flags(it), result, strict);
+                       if (result.x) break;
+               });
 
        if (result.x == 0 && strict)
                result.x = t1.owner.playerid - t2.owner.playerid;