Merge branch 'TimePath/scoreboard_elo' into 'master'
authorTimePath <andrew.hardaker1995@gmail.com>
Sat, 6 Aug 2016 08:35:30 +0000 (08:35 +0000)
committerTimePath <andrew.hardaker1995@gmail.com>
Sat, 6 Aug 2016 08:35:30 +0000 (08:35 +0000)
Scoreboard elo

Cleans up registration of score fields (more to come?) and adds a (not shown by default) current gametype elo field parsed from xonstat

See merge request !309

32 files changed:
.gitlab-ci.yml
qcsrc/client/hud/hud.qh
qcsrc/client/hud/panel/infomessages.qc
qcsrc/client/hud/panel/modicons.qc
qcsrc/client/hud/panel/score.qc
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/client/scoreboard.qc
qcsrc/common/constants.qh
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc
qcsrc/common/playerstats.qc
qcsrc/common/state.qc
qcsrc/dpdefs/doc.md
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_damage.qh
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/mutator/gamemode_assault.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qh
qcsrc/server/mutators/mutator/gamemode_cts.qc
qcsrc/server/mutators/mutator/gamemode_domination.qc
qcsrc/server/mutators/mutator/gamemode_freezetag.qc
qcsrc/server/mutators/mutator/gamemode_keepaway.qc
qcsrc/server/mutators/mutator/gamemode_keyhunt.qc
qcsrc/server/mutators/mutator/gamemode_lms.qc
qcsrc/server/mutators/mutator/gamemode_race.qc
qcsrc/server/race.qh
qcsrc/server/scores.qc
qcsrc/server/scores.qh
qcsrc/server/scores_rules.qc

index db275cd39edfd04ef89f812477015dd701d2dfe5..f826484fe47d3f21861f142a09124d7754bb235a 100644 (file)
@@ -24,7 +24,7 @@ test_sv_game:
     - wget -O data/maps/g-23.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.waypoints.cache
     - wget -O data/maps/g-23.waypoints.hardwired https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.waypoints.hardwired
     - make
-    - EXPECT=56bf79831a0a35ab6a3a420e26b09945
+    - EXPECT=6f94374cbd7ebda9ac951f92562022d8
     - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
index 2a53444669b7829c9818ca342ae8bf6484f0fafa..65b715461431344557b57ea48b38879395c85c79 100644 (file)
@@ -88,7 +88,7 @@ int complain_weapon;
 float complain_weapon_type;
 float complain_weapon_time;
 
-int ps_primary, ps_secondary;
+PlayerScoreField ps_primary, ps_secondary;
 int ts_primary, ts_secondary;
 
 Weapon last_switchweapon;
index 31f7489bf453fb39633d0afe50333e029a1f8f86..c47a3d74e6444665bdb4a9181306132febfc26cd 100644 (file)
@@ -114,9 +114,9 @@ void HUD_InfoMessages()
                        {
                                entity sk;
                                sk = playerslots[player_localnum];
-                               if(sk.(scores[ps_primary]) >= 666)
+                               if(sk.(scores(ps_primary)) >= 666)
                                        s = _("^1Match has already begun");
-                               else if(sk.(scores[ps_primary]) > 0)
+                               else if(sk.(scores(ps_primary)) > 0)
                                        s = _("^1You have no more lives left");
                                else
                                        s = sprintf(_("^1Press ^3%s^1 to join"), getcommandkey(_("jump"), "+jump"));
index 5901a16326ca40047480f5e71d67ae7d783f7cfd..2d6774e2efce12d7a94b2f14ba160f7a5c2cc712 100644 (file)
@@ -532,9 +532,9 @@ void HUD_Mod_Race(vector pos, vector mySize)
        entity me;
        me = playerslots[player_localnum];
        float score;
-       score = me.(scores[ps_primary]);
+       score = me.(scores(ps_primary));
 
-       if(!(scores_flags[ps_primary] & SFL_TIME) || teamplay) // race/cts record display on HUD
+       if(!(scores_flags(ps_primary) & SFL_TIME) || teamplay) // race/cts record display on HUD
                return; // no records in the actual race
 
        // clientside personal record
index b07b84ed33f8001c34779cea4a7bddd9d4db5813..c2fc694d64b2f99b740f6ad4e4258bcb57c0c656 100644 (file)
@@ -84,7 +84,7 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
                                continue;
                        if (tm.team == myteam)
                                drawfill(pos + eX * score_size * i, eX * score_size + eY * fontsize.y, '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
-                       drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores[ts_primary])), eX * score_size + eY * fontsize.y, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
+                       drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores(ts_primary))), eX * score_size + eY * fontsize.y, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
                        ++i;
                }
                first_pl = 1;
@@ -124,7 +124,7 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me)
                        score_color = Team_ColorRGB(pl.team) * 0.8;
                s = textShortenToWidth(entcs_GetName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
                drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-               drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores[ps_primary])), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores(ps_primary))), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
                pos.y += fontsize.y;
                ++i;
        }
@@ -162,23 +162,23 @@ void HUD_Score()
 
        me = playerslots[current_player];
 
-       if((scores_flags[ps_primary] & SFL_TIME) && !teamplay) { // race/cts record display on HUD
+       if((scores_flags(ps_primary) & SFL_TIME) && !teamplay) { // race/cts record display on HUD
                string timer, distrtimer;
 
                pl = players.sort_next;
                if(pl == me)
                        pl = pl.sort_next;
-               if(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)
-                       if(pl.scores[ps_primary] == 0)
+               if(scores_flags(ps_primary) & SFL_ZERO_IS_WORST)
+                       if(pl.scores(ps_primary) == 0)
                                pl = NULL;
 
-               score = me.(scores[ps_primary]);
+               score = me.(scores(ps_primary));
                timer = TIME_ENCODED_TOSTRING(score);
 
                draw_beginBoldFont();
-               if (pl && ((!(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)) || score)) {
+               if (pl && ((!(scores_flags(ps_primary) & SFL_ZERO_IS_WORST)) || score)) {
                        // distribution display
-                       distribution = me.(scores[ps_primary]) - pl.(scores[ps_primary]);
+                       distribution = me.(scores(ps_primary)) - pl.(scores(ps_primary));
 
                        distrtimer = ftos_decimals(fabs(distribution/pow(10, TIME_DECIMALS)), TIME_DECIMALS);
 
@@ -211,11 +211,11 @@ void HUD_Score()
                if(autocvar__hud_configure)
                        distribution = 42;
                else if(pl)
-                       distribution = me.(scores[ps_primary]) - pl.(scores[ps_primary]);
+                       distribution = me.(scores(ps_primary)) - pl.(scores(ps_primary));
                else
                        distribution = 0;
 
-               score = me.(scores[ps_primary]);
+               score = me.(scores(ps_primary));
                if(autocvar__hud_configure)
                        score = 123;
 
@@ -283,7 +283,7 @@ void HUD_Score()
                                continue;
                        if(!tm.team && teamplay)
                                continue;
-                       score = tm.(teamscores[ts_primary]);
+                       score = tm.(teamscores(ts_primary));
                        if(autocvar__hud_configure)
                                score = 123;
 
index 2905b8b2da90e8ff51c6e135e6bac8206586a846..680e65ac05e50e33bd5b19832bb664cad6480b25 100644 (file)
@@ -385,23 +385,21 @@ void Ent_RemovePlayerScore(entity this)
        if(this.owner) {
                SetTeam(this.owner, -1);
                this.owner.gotscores = 0;
-               for(int i = 0; i < MAX_SCORE; ++i) {
-                       this.owner.(scores[i]) = 0; // clear all scores
-               }
+               FOREACH(Scores, true, {
+                       this.owner.(scores(it)) = 0; // clear all scores
+               });
        }
 }
 
 NET_HANDLE(ENT_CLIENT_SCORES, bool isnew)
 {
        make_pure(this);
-       int i, n;
-       bool isNew;
        entity o;
 
        // damnit -.- don't want to go change every single .sv_entnum in hud.qc AGAIN
        // (no I've never heard of M-x replace-string, sed, or anything like that)
-       isNew = !this.owner; // workaround for DP bug
-       n = ReadByte()-1;
+       bool isNew = !this.owner; // workaround for DP bug
+       int n = ReadByte()-1;
 
 #ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
        if(!isNew && n != this.sv_entnum)
@@ -429,22 +427,18 @@ NET_HANDLE(ENT_CLIENT_SCORES, bool isnew)
        //playerchecker will do this for us later, if it has not already done so
 
     int sf, lf;
-#if MAX_SCORE <= 8
-       sf = ReadByte();
-       lf = ReadByte();
-#else
        sf = ReadShort();
        lf = ReadShort();
-#endif
-    int p;
-       for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2)
-               if(sf & p)
+       FOREACH(Scores, true, {
+        int p = 1 << (i % 16);
+               if (sf & p)
                {
-                       if(lf & p)
-                               o.(scores[i]) = ReadInt24_t();
+                       if (lf & p)
+                               o.(scores(it)) = ReadInt24_t();
                        else
-                               o.(scores[i]) = ReadChar();
+                               o.(scores(it)) = ReadChar();
                }
+    });
 
        return = true;
 
@@ -476,9 +470,9 @@ NET_HANDLE(ENT_CLIENT_TEAMSCORES, bool isnew)
                if(sf & p)
                {
                        if(lf & p)
-                               o.(teamscores[i]) = ReadInt24_t();
+                               o.(teamscores(i)) = ReadInt24_t();
                        else
-                               o.(teamscores[i]) = ReadChar();
+                               o.(teamscores(i)) = ReadChar();
                }
 
        return = true;
@@ -958,17 +952,16 @@ NET_HANDLE(ENT_CLIENT_SCORES_INFO, bool isnew)
        make_pure(this);
        gametype = ReadInt24_t();
        HUD_ModIcons_SetFunc();
-       for (int i = 0; i < MAX_SCORE; ++i)
-       {
-               if (scores_label[i]) strunzone(scores_label[i]);
-               scores_label[i] = strzone(ReadString());
-               scores_flags[i] = ReadByte();
-       }
+       FOREACH(Scores, true, {
+               if (scores_label(it)) strunzone(scores_label(it));
+               scores_label(it) = strzone(ReadString());
+               scores_flags(it) = ReadByte();
+       });
        for (int i = 0; i < MAX_TEAMSCORE; ++i)
        {
-               if (teamscores_label[i]) strunzone(teamscores_label[i]);
-               teamscores_label[i] = strzone(ReadString());
-               teamscores_flags[i] = ReadByte();
+               if (teamscores_label(i)) strunzone(teamscores_label(i));
+               teamscores_label(i) = strzone(ReadString());
+               teamscores_flags(i) = ReadByte();
        }
        return = true;
        HUD_InitScores();
index b47836f23caca4f5ec4b3fb400d5f5e1034d5ee1..4822ffed29423b95cbad1a9ebb923dd16a825deb 100644 (file)
@@ -40,36 +40,13 @@ void LoadMenuSkinValues();
 // --------------------------------------------------------------------------
 // Scoreboard stuff
 
-const int MAX_HUD_FIELDS = 16;
+const int MAX_HUD_FIELDS = MAX_SCORE;
 
-const int SP_END = -1;
-
-const int SP_PING = -2;
-const int SP_NAME = -3;
-const int SP_KDRATIO = -4;
-const int SP_CLRATIO = -5;
-const int SP_PL = -6;
-const int SP_FRAGS = -7;
-const int SP_SUM = -8;
-
-const int SP_SEPARATOR = -100;
-
-float hud_field[MAX_HUD_FIELDS + 1];
+PlayerScoreField hud_field[MAX_HUD_FIELDS + 1];
 float hud_size[MAX_HUD_FIELDS + 1];
 string hud_title[MAX_HUD_FIELDS + 1];
 int hud_num_fields;
 
-string scores_label[MAX_SCORE];
-int scores_flags[MAX_SCORE];
-string teamscores_label[MAX_SCORE];
-int teamscores_flags[MAX_SCORE];
-.int scores[MAX_SCORE];
-.float teamscores[MAX_TEAMSCORE];
-
-#define IS_INCREASING(x) ( (x)&SFL_LOWER_IS_BETTER )
-#define IS_DECREASING(x) ( !((x)&SFL_LOWER_IS_BETTER) )
-
-
 vector hud_fontsize;
 
 float RANKINGS_RECEIVED_CNT;
index 5e51e9b7ffe7198921cbecac40cfa1dbcb0169b6..f32873cba740f67e933f2a630538d42e08bda92c 100644 (file)
@@ -72,21 +72,21 @@ void HUD_InitScores()
 {
        int i, f;
 
-       ps_primary = ps_secondary = ts_primary = ts_secondary = -1;
-       for(i = 0; i < MAX_SCORE; ++i)
-       {
-               f = (scores_flags[i] & SFL_SORT_PRIO_MASK);
+       ps_primary = ps_secondary = NULL;
+       ts_primary = ts_secondary = -1;
+       FOREACH(Scores, true, {
+               f = (scores_flags(it) & SFL_SORT_PRIO_MASK);
                if(f == SFL_SORT_PRIO_PRIMARY)
-                       ps_primary = i;
+                       ps_primary = it;
                if(f == SFL_SORT_PRIO_SECONDARY)
-                       ps_secondary = i;
-       }
-       if(ps_secondary == -1)
+                       ps_secondary = it;
+       });
+       if(ps_secondary == NULL)
                ps_secondary = ps_primary;
 
        for(i = 0; i < MAX_TEAMSCORE; ++i)
        {
-               f = (teamscores_flags[i] & SFL_SORT_PRIO_MASK);
+               f = (teamscores_flags(i) & SFL_SORT_PRIO_MASK);
                if(f == SFL_SORT_PRIO_PRIMARY)
                        ts_primary = i;
                if(f == SFL_SORT_PRIO_SECONDARY)
@@ -170,21 +170,18 @@ float HUD_ComparePlayerScores(entity left, entity right)
                return false;
        }
 
-       r = HUD_CompareScore(left.scores[ps_primary], right.scores[ps_primary], scores_flags[ps_primary]);
+       r = HUD_CompareScore(left.scores(ps_primary), right.scores(ps_primary), scores_flags(ps_primary));
        if (r >= 0)
                return r;
 
-       r = HUD_CompareScore(left.scores[ps_secondary], right.scores[ps_secondary], scores_flags[ps_secondary]);
+       r = HUD_CompareScore(left.scores(ps_secondary), right.scores(ps_secondary), scores_flags(ps_secondary));
        if (r >= 0)
                return r;
 
-       int i;
-       for(i = 0; i < MAX_SCORE; ++i)
-       {
-               r = HUD_CompareScore(left.scores[i], right.scores[i], scores_flags[i]);
-               if (r >= 0)
-                       return r;
-       }
+       FOREACH(Scores, true, {
+               r = HUD_CompareScore(left.scores(it), right.scores(it), scores_flags(it));
+               if (r >= 0) return r;
+       });
 
        if (left.sv_entnum < right.sv_entnum)
                return true;
@@ -214,17 +211,17 @@ float HUD_CompareTeamScores(entity left, entity right)
        if(right.team == NUM_SPECTATOR)
                return 0;
 
-       r = HUD_CompareScore(left.teamscores[ts_primary], right.teamscores[ts_primary], teamscores_flags[ts_primary]);
+       r = HUD_CompareScore(left.teamscores(ts_primary), right.teamscores(ts_primary), teamscores_flags(ts_primary));
        if (r >= 0)
                return r;
 
-       r = HUD_CompareScore(left.teamscores[ts_secondary], right.teamscores[ts_secondary], teamscores_flags[ts_secondary]);
+       r = HUD_CompareScore(left.teamscores(ts_secondary), right.teamscores(ts_secondary), teamscores_flags(ts_secondary));
        if (r >= 0)
                return r;
 
-       for(i = 0; i < MAX_SCORE; ++i)
+       for(i = 0; i < MAX_TEAMSCORE; ++i)
        {
-               r = HUD_CompareScore(left.teamscores[i], right.teamscores[i], teamscores_flags[i]);
+               r = HUD_CompareScore(left.teamscores(i), right.teamscores(i), teamscores_flags(i));
                if (r >= 0)
                        return r;
        }
@@ -256,11 +253,13 @@ void Cmd_HUD_Help()
        LOG_INFO(_("^2scoreboard_columns_set default\n"));
        LOG_INFO(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
        LOG_INFO(_("The following field names are recognized (case insensitive):\n"));
-       LOG_INFO(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
+       LOG_INFO(_("You can use a ^3|^7 to start the right-aligned fields.\n"));
+       LOG_INFO("\n");
 
        LOG_INFO(_("^3name^7 or ^3nick^7             Name of a player\n"));
        LOG_INFO(_("^3ping^7                     Ping time\n"));
        LOG_INFO(_("^3pl^7                       Packet loss\n"));
+       LOG_INFO(_("^3elo^7                      Player ELO\n"));
        LOG_INFO(_("^3kills^7                    Number of kills\n"));
        LOG_INFO(_("^3deaths^7                   Number of deaths\n"));
        LOG_INFO(_("^3suicides^7                 Number of suicides\n"));
@@ -288,7 +287,8 @@ void Cmd_HUD_Help()
        LOG_INFO(_("^3takes^7                    Number of domination points taken (DOM)\n"));
        LOG_INFO(_("^3bckills^7                  Number of ball carrier kills\n"));
        LOG_INFO(_("^3bctime^7                   Total amount of time holding the ball in Keepaway\n"));
-       LOG_INFO(_("^3score^7                    Total score\n\n"));
+       LOG_INFO(_("^3score^7                    Total score\n"));
+       LOG_INFO("\n");
 
        LOG_INFO(_("Before a field you can put a + or - sign, then a comma separated list\n"
                "of game types, then a slash, to make the field show up only in these\n"
@@ -327,7 +327,7 @@ void Cmd_HUD_Help()
 void Cmd_HUD_SetFields(int argc)
 {
     TC(int, argc);
-       int i, j, slash;
+       int i, slash;
        string str, pattern;
        float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
        float missing;
@@ -337,9 +337,9 @@ void Cmd_HUD_SetFields(int argc)
                // set up a temporary scoreboard layout
                // no layout can be properly set up until score_info data haven't been received
                argc = tokenizebyseparator("0 1 ping pl name | score", " ");
-               ps_primary = 0;
-               scores_label[ps_primary] = strzone("score");
-               scores_flags[ps_primary] = SFL_ALLOW_HIDE;
+               ps_primary = SP_SCORE;
+               scores_label(ps_primary) = strzone("score");
+               scores_flags(ps_primary) = SFL_ALLOW_HIDE;
        }
 
        // TODO: re enable with gametype dependant cvars?
@@ -357,16 +357,15 @@ void Cmd_HUD_SetFields(int argc)
                {
                        string s;
                        s = "ping pl name |";
-                       for(i = 0; i < MAX_SCORE; ++i)
-                       {
-                               if(i != ps_primary)
-                               if(i != ps_secondary)
-                               if(scores_label[i] != "")
-                                       s = strcat(s, " ", scores_label[i]);
-                       }
+                       FOREACH(Scores, true, {
+                               if(it != ps_primary)
+                               if(it != ps_secondary)
+                               if(scores_label(it) != "")
+                                       s = strcat(s, " ", scores_label(it));
+                       });
                        if(ps_secondary != ps_primary)
-                               s = strcat(s, " ", scores_label[ps_secondary]);
-                       s = strcat(s, " ", scores_label[ps_primary]);
+                               s = strcat(s, " ", scores_label(ps_secondary));
+                       s = strcat(s, " ", scores_label(ps_primary));
                        argc = tokenizebyseparator(strcat("0 1 ", s), " ");
                }
        }
@@ -403,6 +402,7 @@ void Cmd_HUD_SetFields(int argc)
                hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], false, hud_fontsize);
                str = strtolower(str);
 
+        PlayerScoreField j;
                switch(str)
                {
                        case "ping": hud_field[hud_num_fields] = SP_PING; break;
@@ -411,13 +411,17 @@ void Cmd_HUD_SetFields(int argc)
                        case "sum": case "diff": case "k-d": hud_field[hud_num_fields] = SP_SUM; break;
                        case "name": case "nick": hud_field[hud_num_fields] = SP_NAME; have_name = true; break;
                        case "|": hud_field[hud_num_fields] = SP_SEPARATOR; have_separator = true; break;
+                       case "elo": hud_field[hud_num_fields] = SP_ELO; break;
                        case "dmg": hud_field[hud_num_fields] = SP_DMG; break;
                        case "dmgtaken": hud_field[hud_num_fields] = SP_DMGTAKEN; break;
                        default:
                        {
-                               for(j = 0; j < MAX_SCORE; ++j)
-                                       if(str == strtolower(scores_label[j]))
+                               FOREACH(Scores, true, {
+                                       if (str == strtolower(scores_label(it))) {
+                                           j = it;
                                                goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
+                    }
+                });
 
 LABEL(notfound)
                                if(str == "frags")
@@ -442,9 +446,9 @@ LABEL(found)
                        break;
        }
 
-       if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
+       if(scores_flags(ps_primary) & SFL_ALLOW_HIDE)
                have_primary = 1;
-       if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
+       if(scores_flags(ps_secondary) & SFL_ALLOW_HIDE)
                have_secondary = 1;
        if(ps_primary == ps_secondary)
                have_secondary = 1;
@@ -494,20 +498,20 @@ LABEL(found)
                if(!have_secondary)
                {
                        strunzone(hud_title[hud_num_fields]);
-                       hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
+                       hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label(ps_secondary)));
                        hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], false, hud_fontsize);
                        hud_field[hud_num_fields] = ps_secondary;
                        ++hud_num_fields;
-                       LOG_INFOF("fixed missing field '%s'\n", scores_label[ps_secondary]);
+                       LOG_INFOF("fixed missing field '%s'\n", scores_label(ps_secondary));
                }
                if(!have_primary)
                {
                        strunzone(hud_title[hud_num_fields]);
-                       hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
+                       hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label(ps_primary)));
                        hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], false, hud_fontsize);
                        hud_field[hud_num_fields] = ps_primary;
                        ++hud_num_fields;
-                       LOG_INFOF("fixed missing field '%s'\n", scores_label[ps_primary]);
+                       LOG_INFOF("fixed missing field '%s'\n", scores_label(ps_primary));
                }
        }
 
@@ -525,9 +529,8 @@ vector hud_field_icon2_rgb;
 float hud_field_icon0_alpha;
 float hud_field_icon1_alpha;
 float hud_field_icon2_alpha;
-string HUD_GetField(entity pl, int field)
+string HUD_GetField(entity pl, PlayerScoreField field)
 {
-    TC(int, field);
        float tmp, num, denom;
        int f;
        string str;
@@ -587,13 +590,13 @@ string HUD_GetField(entity pl, int field)
                        return entcs_GetName(pl.sv_entnum);
 
                case SP_FRAGS:
-                       f = pl.(scores[SP_KILLS]);
-                       f -= pl.(scores[SP_SUICIDES]);
+                       f = pl.(scores(SP_KILLS));
+                       f -= pl.(scores(SP_SUICIDES));
                        return ftos(f);
 
                case SP_KDRATIO:
-                       num = pl.(scores[SP_KILLS]);
-                       denom = pl.(scores[SP_DEATHS]);
+                       num = pl.(scores(SP_KILLS));
+                       denom = pl.(scores(SP_DEATHS));
 
                        if(denom == 0) {
                                hud_field_rgb = '0 1 0';
@@ -606,8 +609,8 @@ string HUD_GetField(entity pl, int field)
                        return str;
 
                case SP_SUM:
-                       f = pl.(scores[SP_KILLS]);
-                       f -= pl.(scores[SP_DEATHS]);
+                       f = pl.(scores(SP_KILLS));
+                       f -= pl.(scores(SP_DEATHS));
 
                        if(f > 0) {
                                hud_field_rgb = '0 1 0';
@@ -618,23 +621,33 @@ string HUD_GetField(entity pl, int field)
                        }
                        return ftos(f);
 
+               case SP_ELO:
+               {
+                       float elo = pl.(scores(SP_ELO));
+                       switch (elo) {
+                               case -1: return "...";
+                               case -2: return _("N/A");
+                               default: return ftos(elo);
+                       }
+               }
+
                case SP_DMG:
-                       num = pl.(scores[SP_DMG]);
+                       num = pl.(scores(SP_DMG));
                        denom = 1000;
 
                        str = sprintf("%.1f k", num/denom);
                        return str;
 
                case SP_DMGTAKEN:
-                       num = pl.(scores[SP_DMGTAKEN]);
+                       num = pl.(scores(SP_DMGTAKEN));
                        denom = 1000;
 
                        str = sprintf("%.1f k", num/denom);
                        return str;
 
                default:
-                       tmp = pl.(scores[field]);
-                       f = scores_flags[field];
+                       tmp = pl.(scores(field));
+                       f = scores_flags(field);
                        if(field == ps_primary)
                                hud_field_rgb = '1 1 0';
                        else if(field == ps_secondary)
@@ -653,9 +666,9 @@ float hud_fixscoreboardcolumnwidth_marginlen;
 string HUD_FixScoreboardColumnWidth(int i, string str)
 {
     TC(int, i);
-       float field, f;
+       float f;
        vector sz;
-       field = hud_field[i];
+       PlayerScoreField field = hud_field[i];
 
        hud_fixscoreboardcolumnwidth_iconlen = 0;
 
@@ -720,12 +733,10 @@ string HUD_FixScoreboardColumnWidth(int i, string str)
 void HUD_PrintScoreboardItem(vector pos, vector item_size, entity pl, bool is_self, int pl_number)
 {
     TC(bool, is_self); TC(int, pl_number);
-       vector tmp, rgb;
-       rgb = Team_ColorRGB(pl.team);
+       vector tmp;
+       vector rgb = Team_ColorRGB(pl.team);
        string str;
-       int field;
-       float is_spec;
-       is_spec = (entcs_GetTeam(pl.sv_entnum) == NUM_SPECTATOR);
+       bool is_spec = (entcs_GetTeam(pl.sv_entnum) == NUM_SPECTATOR);
 
        if((rgb == '1 1 1') && (!is_spec)) {
                rgb.x = autocvar_scoreboard_color_bg_r + 0.5;
@@ -744,6 +755,7 @@ void HUD_PrintScoreboardItem(vector pos, vector item_size, entity pl, bool is_se
        tmp.y = 0;
        tmp.z = 0;
        int i;
+    PlayerScoreField field;
        for(i = 0; i < hud_num_fields; ++i)
        {
                field = hud_field[i];
@@ -1337,12 +1349,12 @@ void HUD_DrawScoreboard()
 
                        draw_beginBoldFont();
                        rgb = Team_ColorRGB(tm.team);
-                       str = ftos(tm.(teamscores[ts_primary]));
+                       str = ftos(tm.(teamscores(ts_primary)));
                        drawstring(pos + team_score_baseoffset - eX * stringwidth(str, false, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
 
                        if(ts_primary != ts_secondary)
                        {
-                               str = ftos(tm.(teamscores[ts_secondary]));
+                               str = ftos(tm.(teamscores(ts_secondary)));
                                drawstring(pos + team_score_baseoffset - eX * stringwidth(str, false, hud_fontsize) + eY * hud_fontsize.y * 1.5, str, hud_fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
                        }
                        draw_endBoldFont();
@@ -1440,17 +1452,17 @@ void HUD_DrawScoreboard()
                                str = strcat(str, _(" or"));
                        if(teamplay)
                        {
-                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
-                                       (teamscores_label[ts_primary] == "score")   ? CTX(_("SCO^points")) :
-                                       (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
-                                       TranslateScoresLabel(teamscores_label[ts_primary])));
+                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags(ts_primary), fl),
+                                       (teamscores_label(ts_primary) == "score")   ? CTX(_("SCO^points")) :
+                                       (teamscores_label(ts_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       TranslateScoresLabel(teamscores_label(ts_primary))));
                        }
                        else
                        {
-                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
-                                       (scores_label[ps_primary] == "score")   ? CTX(_("SCO^points")) :
-                                       (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
-                                       TranslateScoresLabel(scores_label[ps_primary])));
+                               str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags(ps_primary), fl),
+                                       (scores_label(ps_primary) == "score")   ? CTX(_("SCO^points")) :
+                                       (scores_label(ps_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       TranslateScoresLabel(scores_label(ps_primary))));
                        }
                }
                if(ll > 0)
@@ -1459,17 +1471,17 @@ void HUD_DrawScoreboard()
                                str = strcat(str, _(" or"));
                        if(teamplay)
                        {
-                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
-                                       (teamscores_label[ts_primary] == "score")   ? CTX(_("SCO^points")) :
-                                       (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
-                                       TranslateScoresLabel(teamscores_label[ts_primary])));
+                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags(ts_primary), ll),
+                                       (teamscores_label(ts_primary) == "score")   ? CTX(_("SCO^points")) :
+                                       (teamscores_label(ts_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       TranslateScoresLabel(teamscores_label(ts_primary))));
                        }
                        else
                        {
-                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
-                                       (scores_label[ps_primary] == "score")   ? CTX(_("SCO^points")) :
-                                       (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
-                                       TranslateScoresLabel(scores_label[ps_primary])));
+                               str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags(ps_primary), ll),
+                                       (scores_label(ps_primary) == "score")   ? CTX(_("SCO^points")) :
+                                       (scores_label(ps_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       TranslateScoresLabel(scores_label(ps_primary))));
                        }
                }
        }
index 28db23dc11a13fd08b5365a30ca670e2b8638701..e6e5596939dc38b5f7269af128c87fe4d0820ace 100644 (file)
@@ -123,19 +123,115 @@ const int SFL_SORT_PRIO_SECONDARY = 4;
 const int SFL_SORT_PRIO_PRIMARY = 8;
 const int SFL_SORT_PRIO_MASK = 12;
 
-/**
+/*
  * Score indices
  */
-#define MAX_SCORE 12
+
+#ifndef MENUQC
+
+#define IS_INCREASING(x) ( (x) & SFL_LOWER_IS_BETTER )
+#define IS_DECREASING(x) ( !((x) & SFL_LOWER_IS_BETTER) )
+
+
+#define MAX_SCORE 64
+
+#define REGISTER_SP(id) REGISTER(Scores, SP, id, m_id, new_pure(PlayerScoreField))
+REGISTRY(Scores, MAX_SCORE);
+#define Scores_from(i) _Scores_from(i, NULL)
+REGISTER_REGISTRY(Scores)
+REGISTRY_SORT(Scores);
+REGISTRY_CHECK(Scores);
+STATIC_INIT(Scores_renumber) { FOREACH(Scores, true, it.m_id = i); }
+
+USING(PlayerScoreField, entity);
+.int _scores[MAX_SCORE];
+.string m_name;
+.int m_flags;
+
+#define scores(this) _scores[(this).m_id]
+#define scores_label(this) ((this).m_name)
+#define scores_flags(this) ((this).m_flags)
+
+REGISTER_SP(END);
+
+REGISTER_SP(PING);
+REGISTER_SP(NAME);
+REGISTER_SP(KDRATIO);
+REGISTER_SP(CLRATIO);
+REGISTER_SP(PL);
+REGISTER_SP(SUM);
+
+REGISTER_SP(SEPARATOR);
+
+REGISTER_SP(SCORE);
+
+REGISTER_SP(DMG);
+REGISTER_SP(DMGTAKEN);
+
+REGISTER_SP(KILLS);
+REGISTER_SP(DEATHS);
+REGISTER_SP(SUICIDES);
+REGISTER_SP(FRAGS);
+
+REGISTER_SP(ELO);
+
+// TODO: move to common mutators
+
+REGISTER_SP(RACE_TIME);
+REGISTER_SP(RACE_LAPS);
+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_FCKILLS);
+REGISTER_SP(CTF_RETURNS);
+REGISTER_SP(CTF_CAPS);
+REGISTER_SP(CTF_CAPTIME);
+REGISTER_SP(CTF_DROPS);
+
+REGISTER_SP(DOM_TAKES);
+REGISTER_SP(DOM_TICKS);
+
+REGISTER_SP(FREEZETAG_REVIVALS);
+
+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(LMS_RANK);
+REGISTER_SP(LMS_LIVES);
+
+REGISTER_SP(NEXBALL_GOALS);
+REGISTER_SP(NEXBALL_FAULTS);
+
+REGISTER_SP(ONS_TAKES);
+REGISTER_SP(ONS_CAPS);
+
 #define MAX_TEAMSCORE 2
+USING(ScoreTeam, string);
+.int _teamscores[MAX_TEAMSCORE];
+#define teamscores(i) _teamscores[i]
+string _teamscores_label[MAX_TEAMSCORE];
+#define teamscores_label(i) _teamscores_label[i]
+int _teamscores_flags[MAX_TEAMSCORE];
+#define teamscores_flags(i) _teamscores_flags[i]
+
+#endif
 
 const int ST_SCORE = 0;
-const int SP_KILLS = 0;
-const int SP_DEATHS = 1;
-const int SP_SUICIDES = 2;
-const int SP_SCORE = 3;
-const int SP_DMG = 10;
-const int SP_DMGTAKEN = 11;
+
 // game mode specific indices are not in common/, but in server/scores_rules.qc!
 
 // WEAPONTODO: move this into separate/new projectile handling code // this sets sounds and other properties of the projectiles in csqc
index b65b558fdb1027352b45ab0bca37dc1a104b6b23..b50013ff7bd7c31fde8701588f285b1813c10855 100644 (file)
@@ -70,8 +70,6 @@ float OtherTeam(float t)  //works only if there are two teams on the map!
 }
 
 const float ST_NEXBALL_GOALS = 1;
-const float SP_NEXBALL_GOALS = 4;
-const float SP_NEXBALL_FAULTS = 5;
 void nb_ScoreRules(int teams)
 {
        ScoreRules_basics(teams, 0, 0, true);
index d3c52e04b21290b08dc80cf2b7eab74165e0f28a..14ee4eceb9acc1bca5b7930c426b18aa033e1bee 100644 (file)
@@ -120,8 +120,6 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org
 
 // score rule declarations
 const int ST_ONS_CAPS = 1;
-const int SP_ONS_CAPS = 4;
-const int SP_ONS_TAKES = 6;
 
 #endif
 #endif
@@ -2236,7 +2234,7 @@ void ons_ScoreRules()
        if(c4 >= 0) teams |= BIT(3);
        ScoreRules_basics(teams, SFL_SORT_PRIO_PRIMARY, 0, true);
        ScoreInfo_SetLabel_TeamScore  (ST_ONS_CAPS,     "destroyed", SFL_SORT_PRIO_PRIMARY);
-       ScoreInfo_SetLabel_PlayerScore(SP_ONS_CAPS,     "caps",      SFL_SORT_PRIO_SECONDARY);
+       ScoreInfo_SetLabel_PlayerScore(SP_ONS_CAPS,    "caps",      SFL_SORT_PRIO_SECONDARY);
        ScoreInfo_SetLabel_PlayerScore(SP_ONS_TAKES,    "takes",     0);
        ScoreRules_basics_end();
 }
index 7e99bebea7480cfe32a9e32e670b3e58945f2a5e..b00bdcf8d55c7ee5df9522fa69d3e03e689b4884 100644 (file)
@@ -416,12 +416,14 @@ void PlayerStats_GameReport_Handler(entity fh, entity pass, float status)
 
 void PlayerStats_PlayerBasic(entity joiningplayer, float newrequest)
 {
+       PlayerScore_Add(joiningplayer, SP_ELO, -1);
        // http://stats.xonotic.org/player/GgXRw6piDtFIbMArMuiAi8JG4tiin8VLjZgsKB60Uds=/elo.txt
        if(autocvar_g_playerstats_playerbasic_uri != "")
        {
                string uri = autocvar_g_playerstats_playerbasic_uri;
-               if(joiningplayer.crypto_idfp != "")
-               {
+               if (joiningplayer.crypto_idfp == "") {
+                       PlayerScore_Add(joiningplayer, SP_ELO, -1);
+               } else {
                        // create the database if it doesn't already exist
                        if(PS_B_IN_DB < 0)
                                PS_B_IN_DB = db_create();
@@ -452,6 +454,7 @@ void PlayerStats_PlayerBasic(entity joiningplayer, float newrequest)
        else
        {
                // server has this disabled, kill the DB and set status to idle
+               PlayerScore_Add(joiningplayer, SP_ELO, -1);
                if(PS_B_IN_DB >= 0)
                {
                        db_close(PS_B_IN_DB);
@@ -466,12 +469,10 @@ void PlayerStats_PlayerBasic_CheckUpdate(entity joiningplayer)
 {
        // determine whether we should retrieve playerbasic information again
 
-       #if 0
-       LOG_INFOF("PlayerStats_PlayerBasic_CheckUpdate('%s'): %f\n",
+       LOG_TRACEF("PlayerStats_PlayerBasic_CheckUpdate('%s'): %f\n",
                joiningplayer.netname,
                time
        );
-       #endif
 
        // TODO: check to see if this playerid is inside the database already somehow...
        // for now we'll just check the field, but this won't work for players who disconnect and reconnect properly
@@ -503,76 +504,76 @@ void PlayerStats_PlayerBasic_Handler(entity fh, entity p, float status)
                        url_fputs(fh, sprintf("m %s %s\n", cvar_string("_cl_playermodel"), cvar_string("_cl_playerskin"))); // model/skin
                        */url_fputs(fh, "\n");
                        url_fclose(fh);
-                       break;
+                       return;
                }
 
                case URL_READY_CANREAD:
                {
-                       string s = "";
-                       LOG_TRACE("-- Got response from player stats server:\n");
-                       //string gametype = string_null;
-                       while((s = url_fgets(fh)))
-                       {
-                               LOG_TRACE("  ", s, "\n");
-                               /*
+                       bool handled = false;
+                       string gt = string_null;
+                       for (string s = ""; (s = url_fgets(fh)); ) {
+                               int n = tokenizebyseparator(s, " "); // key value? data
+                               if (n == 1) continue;
                                string key = "", value = "", data = "";
-
-                               n = tokenizebyseparator(s, " "); // key (value) data
-                               if (n == 1)
-                                       continue;
-                               else if (n == 2)
-                               {
-                               key = argv(0);
-                               data = argv(1);
-                               }
-                               else if (n >= 3)
-                               {
-                                                               key = argv(0);
-                                                               value = argv(1);
-                                                               data = argv(2);
-                               }
-
-                               if (data == "")
-                               continue;
-
-                               if (key == "#")
-                               continue;
-                               else if (key == "V")
-                               PlayerInfo_AddItem(p, "_version", data);
-                               else if (key == "R")
-                               PlayerInfo_AddItem(p, "_release", data);
-                               else if (key == "T")
-                               PlayerInfo_AddItem(p, "_time", data);
-                               else if (key == "S")
-                               PlayerInfo_AddItem(p, "_statsurl", data);
-                               else if (key == "P")
-                               PlayerInfo_AddItem(p, "_hashkey", data);
-                               else if (key == "n")
-                               PlayerInfo_AddItem(p, "_playernick", data);
-                               else if (key == "i")
-                               PlayerInfo_AddItem(p, "_playerid", data);
-                               else if (key == "G")
-                               gametype = data;
-                               else if (key == "e" && value != "")
-                               {
-                               if (gametype == "")
-                               PlayerInfo_AddItem(p, value, data);
-                               else
-                               PlayerInfo_AddItem(p, sprintf("%s/%s", gametype, value), data);
+                               if (n == 2) {
+                    key = argv(0);
+                    data = argv(1);
+                               } else if (n >= 3) {
+                    key = argv(0);
+                    value = argv(1);
+                    data = argv(2);
                                }
-                               else
-                               continue;
-                               */
+                switch (key) {
+                    case "V":
+                        // PlayerInfo_AddItem(p, "_version", data);
+                        break;
+                    case "R":
+                        // PlayerInfo_AddItem(p, "_release", data);
+                        break;
+                    case "T":
+                        // PlayerInfo_AddItem(p, "_time", data);
+                        break;
+                    case "S":
+                        // PlayerInfo_AddItem(p, "_statsurl", data);
+                        break;
+                    case "P":
+                        // PlayerInfo_AddItem(p, "_hashkey", data);
+                        break;
+                    case "n":
+                        // PlayerInfo_AddItem(p, "_playernick", data);
+                        break;
+                    case "i":
+                        // PlayerInfo_AddItem(p, "_playerid", data);
+                        // p.xonstat_id = stof(data);
+                        break;
+                    case "G":
+                        gt = data;
+                        break;
+                    case "e":
+                        LOG_TRACE("G: ", gt);
+                        LOG_TRACE("e: ", data);
+                        if (gt == GetGametype()) {
+                            handled = true;
+                            float e = stof(data);
+                            PlayerScore_Add(p, SP_ELO, +1 + e);
+                        }
+                        if (gt == "") {
+                            // PlayerInfo_AddItem(p, value, data);
+                        } else {
+                            // PlayerInfo_AddItem(p, sprintf("%s/%s", gt, value), data);
+                        }
+                        break;
+                }
                        }
-                       LOG_TRACE("-- End of response.\n");
                        url_fclose(fh);
+                       if (handled) return;
                        break;
                }
                case URL_READY_CLOSED:
                {
                        // url_fclose has finished
                        LOG_INFO("Player stats synchronized with server\n");
-                       break;
+                       return;
                }
 
                case URL_READY_ERROR:
@@ -582,6 +583,7 @@ void PlayerStats_PlayerBasic_Handler(entity fh, entity p, float status)
                        break;
                }
        }
+       PlayerScore_Add(p, SP_ELO, -1);
 }
 #endif // SVQC
 
index e73bfa24fd481eacec76cc216f84f3693c9a25e7..eaa96892f64aba3e9e1cb38f5b2e34af51358ed3 100644 (file)
@@ -45,13 +45,12 @@ void ClientState_attach(entity this)
 
     GetCvars(this, 0);  // get other cvars from player
 
-       if (IS_REAL_CLIENT(this)) { PlayerStats_PlayerBasic_CheckUpdate(this); }
-
        // TODO: fold all of these into ClientState
 
        DecodeLevelParms(this);
 
        PlayerScore_Attach(this);
+       PlayerStats_PlayerBasic_CheckUpdate(this);
        ClientData_Attach(this);
        accuracy_init(this);
        entcs_attach(this);
index 01fa43aaf28d2669bdc0132b2ecc5df5ad503c80..b49bb6f57ad72e7ab0ff6bed1b20925d6e26362a 100644 (file)
@@ -214,6 +214,10 @@ void SV_PlayerPhysics();
 //   self
 void SV_ParseClientCommand(string cmd);
 
+// qcstatus server field
+string worldstatus;
+.string clientstatus;
+
 ```
 
 # MENUQC
index 109f3ad0219ccd83349b077186df1500a4580cd2..53aa317e6874c97cba35cde6a7f3276284a9de3b 100644 (file)
@@ -35,7 +35,7 @@ float player_count;
 float currentbots;
 float bots_would_leave;
 
-void UpdateFrags(entity player, float f);
+void UpdateFrags(entity player, int f);
 .float totalfrags;
 
 float team1_score, team2_score, team3_score, team4_score;
index ef1e78802efbe4ca679530fb5cbda2198d4e4fb5..debc54743275b0e1bfc64e9f6c5a2a4e21ef05f9 100644 (file)
@@ -25,7 +25,7 @@
 #include "../lib/csqcmodel/sv_model.qh"
 #include "../lib/warpzone/common.qh"
 
-void UpdateFrags(entity player, float f)
+void UpdateFrags(entity player, int f)
 {
        PlayerTeamScore_AddScore(player, f);
 }
index e2c5ea2b35d7a3f665df6a222cb9535e599c1c98..f11c82c84d2bd1c0019fa350322687ba60997eb4 100644 (file)
@@ -52,7 +52,7 @@ float damage_gooddamage;
 
 float IsFlying(entity a);
 
-void UpdateFrags(entity player, float f);
+void UpdateFrags(entity player, int f);
 
 // NOTE: f=0 means still count as a (positive) kill, but count no frags for it
 void W_SwitchWeapon_Force(Player this, Weapon w);
index 257416538f52a5b1c3a9b5c0e09edf81c1dea250..0d53e054f48513fbdd716e289f5ad402f3c679be 100644 (file)
@@ -748,7 +748,7 @@ MUTATOR_HOOKABLE(CheckRules_World, EV_CheckRules_World);
 MUTATOR_HOOKABLE(WantWeapon, EV_WantWeapon);
 
 #define EV_AddPlayerScore(i, o) \
-    /** score field */  i(int, MUTATOR_ARGV_0_int) \
+    /** score field */  i(PlayerScoreField, MUTATOR_ARGV_0_entity) \
     /** score */        i(float, MUTATOR_ARGV_1_float) \
     /**/                o(float, MUTATOR_ARGV_1_float) \
     /** player */       i(entity, MUTATOR_ARGV_2_entity) \
index cace20ccf46fa9c1cfa2360a5056df842a01a79e..092e07b798be7518b135277dcc4c885bc5093224 100644 (file)
@@ -59,7 +59,6 @@ void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrat
 
 // scoreboard stuff
 const float ST_ASSAULT_OBJECTIVES = 1;
-const float SP_ASSAULT_OBJECTIVES = 4;
 
 // predefined spawnfuncs
 void target_objective_decrease_activate(entity this);
index 5274072cf1ff85e9f9e1a885a9430199db30f267..7f5b0ccbd1e4c61c5cd2ca9e415b380e7d4c7082 100644 (file)
@@ -260,7 +260,7 @@ bool ctf_CaptureShield_CheckStatus(entity p)
        if(ctf_captureshield_max_ratio <= 0)
                return false;
 
-       s = PlayerScore_Add(p, SP_CTF_CAPS, 0);
+       s  = PlayerScore_Add(p, SP_CTF_CAPS,    0);
        s2 = PlayerScore_Add(p, SP_CTF_PICKUPS, 0);
        s3 = PlayerScore_Add(p, SP_CTF_RETURNS, 0);
        s4 = PlayerScore_Add(p, SP_CTF_FCKILLS, 0);
@@ -274,7 +274,7 @@ bool ctf_CaptureShield_CheckStatus(entity p)
        FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
                if(DIFF_TEAM(it, p))
                        continue;
-               se = PlayerScore_Add(it, SP_CTF_CAPS, 0);
+               se  = PlayerScore_Add(it, SP_CTF_CAPS,    0);
                se2 = PlayerScore_Add(it, SP_CTF_PICKUPS, 0);
                se3 = PlayerScore_Add(it, SP_CTF_RETURNS, 0);
                se4 = PlayerScore_Add(it, SP_CTF_FCKILLS, 0);
@@ -2583,12 +2583,12 @@ void ctf_ScoreRules(int teams)
        CheckAllowedTeams(NULL);
        ScoreRules_basics(teams, SFL_SORT_PRIO_PRIMARY, 0, true);
        ScoreInfo_SetLabel_TeamScore  (ST_CTF_CAPS,     "caps",      SFL_SORT_PRIO_PRIMARY);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_CAPS,     "caps",      SFL_SORT_PRIO_SECONDARY);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_CAPTIME,  "captime",   SFL_LOWER_IS_BETTER | SFL_TIME);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_PICKUPS,  "pickups",   0);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_FCKILLS,  "fckills",   0);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_RETURNS,  "returns",   0);
-       ScoreInfo_SetLabel_PlayerScore(SP_CTF_DROPS,    "drops",     SFL_LOWER_IS_BETTER);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_CAPS,    "caps",      SFL_SORT_PRIO_SECONDARY);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_CAPTIME, "captime",   SFL_LOWER_IS_BETTER | SFL_TIME);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_PICKUPS, "pickups",   0);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_FCKILLS, "fckills",   0);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_RETURNS, "returns",   0);
+       ScoreInfo_SetLabel_PlayerScore(SP_CTF_DROPS,   "drops",     SFL_LOWER_IS_BETTER);
        ScoreRules_basics_end();
 }
 
index b4d2459c3e26ed078e84ff89a11afa0b5725939c..c9d5b5aedcce94b2a64755784f120131295c43af 100644 (file)
@@ -8,12 +8,6 @@ void ctf_RespawnFlag(entity flag);
 
 // score rule declarations
 const int ST_CTF_CAPS = 1;
-const int SP_CTF_CAPS = 4;
-const int SP_CTF_CAPTIME = 5;
-const int SP_CTF_PICKUPS = 6;
-const int SP_CTF_DROPS = 7;
-const int SP_CTF_FCKILLS = 8;
-const int SP_CTF_RETURNS = 9;
 
 CLASS(Flag, Pickup)
     ATTRIB(Flag, m_mins, vector, PL_MIN_CONST + '0 0 -13')
index 187b4aa951c46c8239bc86e5ffe8f89121ced3d0..8efa3a35dacf17aa9380de07a23976134946fac6 100644 (file)
@@ -38,9 +38,6 @@ REGISTER_MUTATOR(cts, false)
 
 // scores
 const float ST_CTS_LAPS = 1;
-const float SP_CTS_LAPS = 4;
-const float SP_CTS_TIME = 5;
-const float SP_CTS_FASTEST = 6;
 #endif
 
 #ifdef IMPLEMENTATION
index 7d36e3a622d12ae1c285e0190d8a374904155d88..16fa08c81627b49237ac3c908422f464fcc65307 100644 (file)
@@ -37,10 +37,7 @@ REGISTER_MUTATOR(dom, false)
 
 // score rule declarations
 const float ST_DOM_TICKS = 1;
-const float SP_DOM_TICKS = 4;
-const float SP_DOM_TAKES = 5;
 const float ST_DOM_CAPS = 1;
-const float SP_DOM_CAPS = 4;
 
 // pps: points per second
 .float dom_total_pps = _STAT(DOM_TOTAL_PPS);
index 93547989097eb43aad853fa417268146eb14d1e9..c64118cd61d56b461aaf8898688863bc1b8fb7ec 100644 (file)
@@ -61,7 +61,6 @@ int autocvar_g_freezetag_teams;
 int autocvar_g_freezetag_teams_override;
 float autocvar_g_freezetag_warmup;
 
-const float SP_FREEZETAG_REVIVALS = 4;
 void freezetag_ScoreRules(int teams)
 {
        ScoreRules_basics(teams, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, true); // SFL_SORT_PRIO_PRIMARY
index 1ce62672d8b6e5d9eaf6c5ffb0d608dcced47edf..407ac6c98bb7ed05a083c49b4db0801aea3aca5d 100644 (file)
@@ -32,10 +32,6 @@ REGISTER_MUTATOR(ka, false)
 
 entity ka_ball;
 
-const float SP_KEEPAWAY_PICKUPS = 4;
-const float SP_KEEPAWAY_CARRIERKILLS = 5;
-const float SP_KEEPAWAY_BCTIME = 6;
-
 void(entity this) havocbot_role_ka_carrier;
 void(entity this) havocbot_role_ka_collector;
 
@@ -506,9 +502,9 @@ void ka_SpawnBall() // loads various values for the ball, runs only once at star
 void ka_ScoreRules()
 {
        ScoreRules_basics(0, SFL_SORT_PRIO_PRIMARY, 0, true); // SFL_SORT_PRIO_PRIMARY
-       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_PICKUPS,                     "pickups",              0);
-       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_CARRIERKILLS,        "bckills",              0);
-       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_BCTIME,                      "bctime",               SFL_SORT_PRIO_SECONDARY);
+       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_PICKUPS,             "pickups",              0);
+       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_CARRIERKILLS,   "bckills",           0);
+       ScoreInfo_SetLabel_PlayerScore(SP_KEEPAWAY_BCTIME,                  "bctime",           SFL_SORT_PRIO_SECONDARY);
        ScoreRules_basics_end();
 }
 
index 64b0397aa957dacc47c49fc261c915e7d4060786..236db8aa86fad3dd93cafc3faf907a6901d5dd24 100644 (file)
@@ -138,12 +138,6 @@ float kh_interferemsg_time, kh_interferemsg_team;
 float kh_key_dropped, kh_key_carried;
 
 const float ST_KH_CAPS = 1;
-const float SP_KH_CAPS = 4;
-const float SP_KH_PUSHES = 5;
-const float SP_KH_DESTROYS = 6;
-const float SP_KH_PICKUPS = 7;
-const float SP_KH_KCKILLS = 8;
-const float SP_KH_LOSSES = 9;
 void kh_ScoreRules(int teams)
 {
        ScoreRules_basics(teams, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, true);
index adfd6eb6a76648b90ddb9f0b33413ec3dae01038..a869827937573d7d852e9b92680ad33f4e1b5831 100644 (file)
@@ -32,10 +32,6 @@ REGISTER_MUTATOR(lms, false)
        return 0;
 }
 
-// scoreboard stuff
-const float SP_LMS_LIVES = 4;
-const float SP_LMS_RANK = 5;
-
 // lives related defs
 float lms_lowest_lives;
 float lms_next_place;
@@ -392,7 +388,7 @@ MUTATOR_HOOKFUNCTION(lms, GetPlayerStatus)
 MUTATOR_HOOKFUNCTION(lms, AddPlayerScore)
 {
        if(gameover)
-       if(M_ARGV(0, int) == SP_LMS_RANK) // score field
+       if(M_ARGV(0, entity) == SP_LMS_RANK) // score field
                return true; // allow writing to this field in intermission as it is needed for newly joining players
 }
 
index 63fbd15a272476c1184fd26786daf3ce478b5d9c..a496ef2e221801637f7727c010eb2a90e96bb2a1 100644 (file)
@@ -78,7 +78,7 @@ void race_ScoreRules()
        ScoreRules_basics(race_teams, 0, 0, false);
        if(race_teams)
        {
-               ScoreInfo_SetLabel_TeamScore(  ST_RACE_LAPS,    "laps",      SFL_SORT_PRIO_PRIMARY);
+               ScoreInfo_SetLabel_TeamScore(  ST_RACE_LAPS,    "laps",       SFL_SORT_PRIO_PRIMARY);
                ScoreInfo_SetLabel_PlayerScore(SP_RACE_LAPS,    "laps",      SFL_SORT_PRIO_PRIMARY);
                ScoreInfo_SetLabel_PlayerScore(SP_RACE_TIME,    "time",      SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER | SFL_TIME);
                ScoreInfo_SetLabel_PlayerScore(SP_RACE_FASTEST, "fastest",   SFL_LOWER_IS_BETTER | SFL_TIME);
index b69b0006a96d1a8a1b381fd4a4aaaf785657fe8a..6360b0ae5aba535b3727c36110ac5a85e099cce1 100644 (file)
@@ -4,9 +4,6 @@ float race_teams;
 
 // scores
 const float ST_RACE_LAPS = 1;
-const float SP_RACE_LAPS = 4;
-const float SP_RACE_TIME = 5;
-const float SP_RACE_FASTEST = 6;
 
 bool g_race_qualifying;
 
index 1a51c803d5244b86207982ad712cf17ad53ebbfb..17c56fb543dd167e3f8302bf8155efb79e2323ab 100644 (file)
@@ -7,10 +7,6 @@
 
 .entity scorekeeper;
 entity teamscorekeepers[16];
-string scores_label[MAX_SCORE];
-float scores_flags[MAX_SCORE];
-string teamscores_label[MAX_TEAMSCORE];
-float teamscores_flags[MAX_TEAMSCORE];
 float teamscores_entities_count;
 var .float scores_primary;
 var .float teamscores_primary;
@@ -65,7 +61,7 @@ bool TeamScore_SendEntity(entity this, entity to, float sendflags)
 
        longflags = 0;
        for(i = 0, p = 1; i < MAX_TEAMSCORE; ++i, p *= 2)
-               if(this.(teamscores[i]) > 127 || this.(teamscores[i]) <= -128)
+               if(this.(teamscores(i)) > 127 || this.(teamscores(i)) <= -128)
                        longflags |= p;
 
 #if MAX_TEAMSCORE <= 8
@@ -79,9 +75,9 @@ bool TeamScore_SendEntity(entity this, entity to, float sendflags)
                if(sendflags & p)
                {
                        if(longflags & p)
-                               WriteInt24_t(MSG_ENTITY, this.(teamscores[i]));
+                               WriteInt24_t(MSG_ENTITY, this.(teamscores(i)));
                        else
-                               WriteChar(MSG_ENTITY, this.(teamscores[i]));
+                               WriteChar(MSG_ENTITY, this.(teamscores(i)));
                }
 
        return true;
@@ -120,9 +116,9 @@ float TeamScore_AddToTeam(float t, float scorefield, float score)
                error("Adding score to unknown team!");
        }
        if(score)
-               if(teamscores_label[scorefield] != "")
+               if(teamscores_label(scorefield) != "")
                        s.SendFlags |= pow(2, scorefield);
-       return (s.(teamscores[scorefield]) += score);
+       return (s.(teamscores(scorefield)) += score);
 }
 
 float TeamScore_Add(entity player, float scorefield, float score)
@@ -139,8 +135,8 @@ float TeamScore_Compare(entity t1, entity t2, float strict)
        for(i = 0; i < MAX_TEAMSCORE; ++i)
        {
                var .float f;
-               f = teamscores[i];
-               result = ScoreField_Compare(t1, t2, f, teamscores_flags[i], result, strict);
+               f = teamscores(i);
+               result = ScoreField_Compare(t1, t2, f, teamscores_flags(i), result, strict);
        }
 
        if (result.x == 0 && strict)
@@ -153,13 +149,13 @@ float TeamScore_Compare(entity t1, entity t2, float strict)
  * the scoreinfo entity
  */
 
-void ScoreInfo_SetLabel_PlayerScore(float i, string label, float scoreflags)
+void ScoreInfo_SetLabel_PlayerScore(PlayerScoreField i, string label, float scoreflags)
 {
-       scores_label[i] = label;
-       scores_flags[i] = scoreflags;
+       scores_label(i) = label;
+       scores_flags(i) = scoreflags;
        if((scoreflags & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
        {
-               scores_primary = scores[i];
+               scores_primary = scores(i);
                scores_flags_primary = scoreflags;
        }
        if(label != "")
@@ -171,11 +167,11 @@ void ScoreInfo_SetLabel_PlayerScore(float i, string label, float scoreflags)
 
 void ScoreInfo_SetLabel_TeamScore(float i, string label, float scoreflags)
 {
-       teamscores_label[i] = label;
-       teamscores_flags[i] = scoreflags;
+       teamscores_label(i) = label;
+       teamscores_flags(i) = scoreflags;
        if((scoreflags & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
        {
-               teamscores_primary = teamscores[i];
+               teamscores_primary = teamscores(i);
                teamscores_flags_primary = scoreflags;
        }
        if(label != "")
@@ -190,15 +186,14 @@ bool ScoreInfo_SendEntity(entity this, entity to, int sf)
        float i;
        WriteHeader(MSG_ENTITY, ENT_CLIENT_SCORES_INFO);
        WriteInt24_t(MSG_ENTITY, MapInfo_LoadedGametype);
-       for(i = 0; i < MAX_SCORE; ++i)
-       {
-               WriteString(MSG_ENTITY, scores_label[i]);
-               WriteByte(MSG_ENTITY, scores_flags[i]);
-       }
+       FOREACH(Scores, true, {
+               WriteString(MSG_ENTITY, scores_label(it));
+               WriteByte(MSG_ENTITY, scores_flags(it));
+       });
        for(i = 0; i < MAX_TEAMSCORE; ++i)
        {
-               WriteString(MSG_ENTITY, teamscores_label[i]);
-               WriteByte(MSG_ENTITY, teamscores_flags[i]);
+               WriteString(MSG_ENTITY, teamscores_label(i));
+               WriteByte(MSG_ENTITY, teamscores_flags(i));
        }
        return true;
 }
@@ -230,31 +225,28 @@ void ScoreInfo_Init(int teams)
 
 bool PlayerScore_SendEntity(entity this, entity to, float sendflags)
 {
-       float i, p, longflags;
-
        WriteHeader(MSG_ENTITY, ENT_CLIENT_SCORES);
        WriteByte(MSG_ENTITY, etof(this.owner));
 
-       longflags = 0;
-       for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2)
-               if(this.(scores[i]) > 127 || this.(scores[i]) <= -128)
+       int longflags = 0;
+       FOREACH(Scores, true, {
+           int p = 1 << (i % 16);
+               if (this.(scores(it)) > 127 || this.(scores(it)) <= -128)
                        longflags |= p;
+    });
 
-#if MAX_SCORE <= 8
-       WriteByte(MSG_ENTITY, sendflags);
-       WriteByte(MSG_ENTITY, longflags);
-#else
        WriteShort(MSG_ENTITY, sendflags);
        WriteShort(MSG_ENTITY, longflags);
-#endif
-       for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2)
-               if(sendflags & p)
+       FOREACH(Scores, true, {
+           int p = 1 << (i % 16);
+               if (sendflags & p)
                {
                        if(longflags & p)
-                               WriteInt24_t(MSG_ENTITY, this.(scores[i]));
+                               WriteInt24_t(MSG_ENTITY, this.(scores(it)));
                        else
-                               WriteChar(MSG_ENTITY, this.(scores[i]));
+                               WriteChar(MSG_ENTITY, this.(scores(it)));
                }
+    });
 
        return true;
 }
@@ -262,7 +254,6 @@ bool PlayerScore_SendEntity(entity this, entity to, float sendflags)
 float PlayerScore_Clear(entity player)
 {
        entity sk;
-       float i;
 
        if(teamscores_entities_count)
                return 0;
@@ -270,13 +261,12 @@ float PlayerScore_Clear(entity player)
        if(MUTATOR_CALLHOOK(ForbidPlayerScore_Clear)) return 0;
 
        sk = player.scorekeeper;
-       for(i = 0; i < MAX_SCORE; ++i)
-       {
-               if(sk.(scores[i]) != 0)
-                       if(scores_label[i] != "")
-                               sk.SendFlags |= pow(2, i);
-               sk.(scores[i]) = 0;
-       }
+       FOREACH(Scores, true, {
+               if(sk.(scores(it)) != 0)
+                       if(scores_label(it) != "")
+                               sk.SendFlags |= pow(2, i % 16);
+               sk.(scores(it)) = 0;
+       });
 
        return 1;
 }
@@ -285,18 +275,15 @@ void Score_ClearAll()
 {
        entity sk;
        float t;
-       FOREACH_CLIENTSLOT(true,
-       {
+       FOREACH_CLIENTSLOT(true, {
                sk = it.scorekeeper;
-               if(!sk)
-                       continue;
-               for(int j = 0; j < MAX_SCORE; ++j)
-               {
-                       if(sk.(scores[j]) != 0)
-                               if(scores_label[j] != "")
-                                       sk.SendFlags |= pow(2, j);
-                       sk.(scores[j]) = 0;
-               }
+               if (!sk) continue;
+               FOREACH(Scores, true, {
+                       if(sk.(scores(it)) != 0)
+                               if(scores_label(it) != "")
+                                       sk.SendFlags |= pow(2, i % 16);
+                       sk.(scores(it)) = 0;
+               });
        });
        for(t = 0; t < 16; ++t)
        {
@@ -305,10 +292,10 @@ void Score_ClearAll()
                        continue;
                for(int j = 0; j < MAX_TEAMSCORE; ++j)
                {
-                       if(sk.(teamscores[j]) != 0)
-                               if(teamscores_label[j] != "")
+                       if(sk.(teamscores(j)) != 0)
+                               if(teamscores_label(j) != "")
                                        sk.SendFlags |= pow(2, j);
-                       sk.(teamscores[j]) = 0;
+                       sk.(teamscores(j)) = 0;
                }
        }
 }
@@ -331,7 +318,7 @@ void PlayerScore_Detach(entity player)
        player.scorekeeper = NULL;
 }
 
-float PlayerScore_Add(entity player, float scorefield, float score)
+float PlayerScore_Add(entity player, PlayerScoreField scorefield, float score)
 {
        bool mutator_returnvalue = MUTATOR_CALLHOOK(AddPlayerScore, scorefield, score, player);
        score = M_ARGV(1, float);
@@ -350,14 +337,14 @@ float PlayerScore_Add(entity player, float scorefield, float score)
                return 0;
        }
        if(score)
-               if(scores_label[scorefield] != "")
-                       s.SendFlags |= pow(2, scorefield);
+               if(scores_label(scorefield) != "")
+                       s.SendFlags |= pow(2, scorefield.m_id % 16);
        if(!warmup_stage)
-               PS_GR_P_ADDVAL(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label[scorefield]), score);
-       return (s.(scores[scorefield]) += score);
+               PS_GR_P_ADDVAL(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label(scorefield)), score);
+       return (s.(scores(scorefield)) += score);
 }
 
-float PlayerTeamScore_Add(entity player, float pscorefield, float tscorefield, float score)
+float PlayerTeamScore_Add(entity player, PlayerScoreField pscorefield, float tscorefield, float score)
 {
        float r;
        r = PlayerScore_Add(player, pscorefield, score);
@@ -371,13 +358,10 @@ float PlayerScore_Compare(entity t1, entity t2, float strict)
        if(!t1 || !t2) return (!t2) - !t1;
 
        vector result = '0 0 0';
-       float i;
-       for(i = 0; i < MAX_SCORE; ++i)
-       {
-               var .float f;
-               f = scores[i];
-               result = ScoreField_Compare(t1, t2, f, scores_flags[i], result, strict);
-       }
+       FOREACH(Scores, true, {
+               var .float f = scores(it);
+               result = ScoreField_Compare(t1, t2, f, scores_flags(it), result, strict);
+       });
 
        if (result.x == 0 && strict)
                result.x = etof(t1.owner) - etof(t2.owner);
@@ -562,53 +546,59 @@ string GetPlayerScoreString(entity pl, float shortString)
 {
        string out;
        entity sk;
-       float i, f;
+       float f;
        string l;
 
        out = "";
        if(!pl)
        {
                // label
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
+               FOREACH(Scores, true, {
+                       if ((scores_flags(it) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
                        {
-                               f = scores_flags[i];
-                               l = scores_label[i];
+                               f = scores_flags(it);
+                               l = scores_label(it);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
+        });
                if(shortString < 2)
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
+               FOREACH(Scores, true, {
+                       if((scores_flags(it) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
                        {
-                               f = scores_flags[i];
-                               l = scores_label[i];
+                               f = scores_flags(it);
+                               l = scores_label(it);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
+        });
                if(shortString < 1)
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
+               FOREACH(Scores, true, {
+                       if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
+                       if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
                        {
-                               f = scores_flags[i];
-                               l = scores_label[i];
+                               f = scores_flags(it);
+                               l = scores_label(it);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
+        });
                out = substring(out, 0, strlen(out) - 1);
        }
        else if((sk = pl.scorekeeper))
        {
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
-                               out = strcat(out, ftos(sk.(scores[i])), ",");
+               FOREACH(Scores, true, {
+                       if ((scores_flags(it) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
+                               out = strcat(out, ftos(sk.(scores(it))), ",");
+        });
                if(shortString < 2)
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
-                               out = strcat(out, ftos(sk.(scores[i])), ",");
+               FOREACH(Scores, true, {
+                       if ((scores_flags(it) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
+                               out = strcat(out, ftos(sk.(scores(it))), ",");
+        });
                if(shortString < 1)
-               for(i = 0; i < MAX_SCORE; ++i)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
-                       if((scores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
-                               out = strcat(out, ftos(sk.(scores[i])), ",");
+               FOREACH(Scores, true, {
+                       if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
+                       if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
+                               out = strcat(out, ftos(sk.(scores(it))), ",");
+        });
                out = substring(out, 0, strlen(out) - 1);
        }
        return out;
@@ -626,27 +616,27 @@ string GetTeamScoreString(float tm, float shortString)
        {
                // label
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
                        {
-                               f = teamscores_flags[i];
-                               l = teamscores_label[i];
+                               f = teamscores_flags(i);
+                               l = teamscores_label(i);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
                if(shortString < 2)
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
                        {
-                               f = teamscores_flags[i];
-                               l = teamscores_label[i];
+                               f = teamscores_flags(i);
+                               l = teamscores_label(i);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
                if(shortString < 1)
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
                        {
-                               f = teamscores_flags[i];
-                               l = teamscores_label[i];
+                               f = teamscores_flags(i);
+                               l = teamscores_label(i);
                                out = strcat(out, GetScoreLogLabel(l, f), ",");
                        }
                out = substring(out, 0, strlen(out) - 1);
@@ -654,17 +644,17 @@ string GetTeamScoreString(float tm, float shortString)
        else if((sk = teamscorekeepers[tm - 1]))
        {
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
-                               out = strcat(out, ftos(sk.(teamscores[i])), ",");
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
+                               out = strcat(out, ftos(sk.(teamscores(i))), ",");
                if(shortString < 2)
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
-                               out = strcat(out, ftos(sk.(teamscores[i])), ",");
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
+                               out = strcat(out, ftos(sk.(teamscores(i))), ",");
                if(shortString < 1)
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
-                       if((teamscores_flags[i] & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
-                               out = strcat(out, ftos(sk.(teamscores[i])), ",");
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
+                       if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
+                               out = strcat(out, ftos(sk.(teamscores(i))), ",");
                out = substring(out, 0, strlen(out) - 1);
        }
        return out;
@@ -799,10 +789,10 @@ void Score_NicePrint_Team(entity to, float t, float w)
        {
                s = strcat(s, Team_ColoredFullName(t));
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if(teamscores_label[i] != "")
+                       if(teamscores_label(i) != "")
                        {
-                               fl = teamscores_flags[i];
-                               sc = sk.(teamscores[i]);
+                               fl = teamscores_flags(i);
+                               sc = sk.(teamscores(i));
                                s = strcat(s, " ", Score_NicePrint_ItemColor(fl), ScoreString(fl, sc));
                        }
        }
@@ -811,13 +801,14 @@ void Score_NicePrint_Team(entity to, float t, float w)
 
        s = strcat(s, strpad(max(0, NAMEWIDTH - strlennocol(s)), ""));
 
-       for(i = 0; i < MAX_SCORE; ++i)
-               if(scores_label[i] != "")
+       FOREACH(Scores, true, {
+               if(scores_label(it) != "")
                {
-                       fl = scores_flags[i];
-                       s2 = scores_label[i];
+                       fl = scores_flags(it);
+                       s2 = scores_label(it);
                        s = strcat(s, " ", Score_NicePrint_ItemColor(fl), strpad(-w, substring(s2, 0, w)));
                }
+    });
 
        print_to(to, s);
 }
@@ -845,13 +836,14 @@ void Score_NicePrint_Player(entity to, entity p, float w)
                }
        }
 
-       for(i = 0; i < MAX_SCORE; ++i)
-               if(scores_label[i] != "")
+       FOREACH(Scores, true, {
+               if(scores_label(it) != "")
                {
-                       fl = scores_flags[i];
-                       sc = sk.(scores[i]);
+                       fl = scores_flags(it);
+                       sc = sk.(scores(it));
                        s = strcat(s, " ", Score_NicePrint_ItemColor(fl), strpad(-w, ScoreString(fl, sc)));
                }
+    });
 
        print_to(to, s);
 }
@@ -870,13 +862,13 @@ void Score_NicePrint_Spectator(entity to, entity p)
 void Score_NicePrint(entity to)
 {
        entity p;
-       float i;
        float w;
 
        int t = 0;
-       for(i = 0; i < MAX_SCORE; ++i)
-               if(scores_label[i] != "")
+       FOREACH(Scores, true, {
+               if(scores_label(it) != "")
                        ++t;
+    });
        w = bound(6, floor(SCORESWIDTH / t - 1), 9);
 
        p = PlayerScore_Sort(score_dummyfield, 1, 1, 0);
@@ -905,14 +897,12 @@ void Score_NicePrint(entity to)
 
 void PlayerScore_PlayerStats(entity p)
 {
-       entity s;
-       float i;
-       s = p.scorekeeper;
-
-       for(i = 0; i < MAX_SCORE; ++i)
-               if(s.(scores[i]) != 0)
-                       if(scores_label[i] != "")
-                               PS_GR_P_ADDVAL(s.owner, strcat(PLAYERSTATS_SCOREBOARD, scores_label[i]), s.(scores[i]));
+       entity s = p.scorekeeper;
+       FOREACH(Scores, true, {
+               if(s.(scores(it)) != 0)
+                       if(scores_label(it) != "")
+                               PS_GR_P_ADDVAL(s.owner, strcat(PLAYERSTATS_SCOREBOARD, scores_label(it)), s.(scores(it)));
+    });
 }
 
 void PlayerScore_TeamStats()
@@ -925,9 +915,9 @@ void PlayerScore_TeamStats()
                if(!sk)
                        continue;
                for(i = 0; i < MAX_TEAMSCORE; ++i)
-                       if(sk.(teamscores[i]) != 0)
-                               if(teamscores_label[i] != "")
+                       if(sk.(teamscores(i)) != 0)
+                               if(teamscores_label(i) != "")
                                        // the +1 is important here!
-                                       PS_GR_T_ADDVAL(t+1, strcat(PLAYERSTATS_SCOREBOARD, teamscores_label[i]), sk.(teamscores[i]));
+                                       PS_GR_T_ADDVAL(t+1, strcat(PLAYERSTATS_SCOREBOARD, teamscores_label(i)), sk.(teamscores(i)));
        }
 }
index a462bde92c4bed31f706262a2314b43a5c3ff8f0..cf767659056d5f9cef2a39ae063d18a5923c8c5e 100644 (file)
@@ -3,8 +3,6 @@
 #include <common/constants.qh>
 
 entity scores_initialized; // non-NULL when scores labels/rules have been set
-.float scores[MAX_SCORE];
-.float teamscores[MAX_TEAMSCORE];
 .float scoreboard_pos;
 
 /**
@@ -24,7 +22,7 @@ void PlayerScore_Detach(entity player);
  * Means: FIXME make players unable to join the game when not called ClientConnect yet.
  * Returns the new score.
  */
-float PlayerScore_Add(entity player, float scorefield, float score);
+float PlayerScore_Add(entity player, PlayerScoreField scorefield, float score);
 
 /**
  * Initialize the score of this player if needed.
@@ -57,12 +55,12 @@ float TeamScore_GetCompareValue(float t);
  * Adds a score to both the player and the team. Returns the team score if
  * possible, otherwise the player score.
  */
-float PlayerTeamScore_Add(entity player, float pscorefield, float tscorefield, float score);
+float PlayerTeamScore_Add(entity player, PlayerScoreField pscorefield, float tscorefield, float score);
 
 /**
  * Adds to the generic score fields for both the player and the team.
  */
-#define PlayerTeamScore_AddScore(p,s) PlayerTeamScore_Add(p, SP_SCORE, ST_SCORE, s)
+#define PlayerTeamScore_AddScore(p, s) PlayerTeamScore_Add(p, SP_SCORE, ST_SCORE, s)
 
 /**
  * Set the label of a team score item, as well as the scoring flags.
@@ -72,7 +70,7 @@ void ScoreInfo_SetLabel_TeamScore(float i, string label, float scoreflags);
 /**
  * Set the label of a player score item, as well as the scoring flags.
  */
-void ScoreInfo_SetLabel_PlayerScore(float i, string label, float scoreflags);
+void ScoreInfo_SetLabel_PlayerScore(PlayerScoreField i, string label, float scoreflags);
 
 /**
  * Initialize the scores info for the given number of teams.
index b93c114c06eb40f1c18fa829d3196a93a32ac795..d3aceac50b2b28e8f2606d74ab4fe4713b12bba7 100644 (file)
@@ -19,14 +19,14 @@ int AvailableTeams()
        //return boolean(c1 >= 0) + boolean(c2 >= 0) + boolean(c3 >= 0) + boolean(c4 >= 0);
 }
 
-// NOTE: SP_ constants may not be >= MAX_SCORE; ST_constants may not be >= MAX_TEAMSCORE
+// NOTE: ST_constants may not be >= MAX_TEAMSCORE
 // scores that should be in all modes:
 void ScoreRules_basics(int teams, float sprio, float stprio, float score_enabled)
 {
-       float i;
-       for(i = 0; i < MAX_SCORE; ++i)
-               ScoreInfo_SetLabel_PlayerScore(i, "", 0);
-       for(i = 0; i < MAX_TEAMSCORE; ++i)
+       FOREACH(Scores, true, {
+               ScoreInfo_SetLabel_PlayerScore(it, "", 0);
+    });
+       for(int i = 0; i < MAX_TEAMSCORE; ++i)
                ScoreInfo_SetLabel_TeamScore(i, "", 0);
 
        ScoreRules_teams = teams;
@@ -47,6 +47,7 @@ void ScoreRules_basics(int teams, float sprio, float stprio, float score_enabled
 
        ScoreInfo_SetLabel_PlayerScore(SP_DMG, "damage", 0);
        ScoreInfo_SetLabel_PlayerScore(SP_DMGTAKEN, "damagetaken", SFL_LOWER_IS_BETTER);
+       ScoreInfo_SetLabel_PlayerScore(SP_ELO, "elo", 0);
 }
 void ScoreRules_basics_end()
 {