Remove hardcoded priority list (sb_extra_sorting_field) from scoreboard's algorithm, score registration order can be used now.
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;
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;
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;
#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)
/*
* 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);
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
/**
* 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);
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
{
{
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)
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));
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;