]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/hud/panel/scoreboard.qc
Added new column of country flags in the scoreboard (for the sake of z411's request)
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud / panel / scoreboard.qc
index 08a1a73bb0977148aa8174f48ef67d836aad4ded..39740b8c4bdfbfd4c543cbc27763e392b7549e04 100644 (file)
@@ -1,21 +1,41 @@
 #include "scoreboard.qh"
 
-#include <client/autocvars.qh>
-#include <client/defs.qh>
-#include <client/main.qh>
-#include <client/miscfunctions.qh>
-#include "quickmenu.qh"
-#include <common/ent_cs.qh>
+#include <client/draw.qh>
+#include <client/hud/panel/chat.qh>
+#include <client/hud/panel/quickmenu.qh>
+#include <client/hud/panel/racetimer.qh>
+#include <client/hud/panel/weapons.qh>
 #include <common/constants.qh>
-#include <common/net_linked.qh>
+#include <common/ent_cs.qh>
 #include <common/mapinfo.qh>
 #include <common/minigames/cl_minigames.qh>
+#include <common/net_linked.qh>
 #include <common/scores.qh>
 #include <common/stats.qh>
 #include <common/teams.qh>
+#include <common/items/inventory.qh>
 
 // Scoreboard (#24)
 
+void Scoreboard_Draw_Export(int fh)
+{
+       // allow saving cvars that aesthetically change the panel into hud skin files
+       HUD_Write_Cvar("hud_panel_scoreboard_fadeinspeed");
+       HUD_Write_Cvar("hud_panel_scoreboard_fadeoutspeed");
+       HUD_Write_Cvar("hud_panel_scoreboard_respawntime_decimals");
+       HUD_Write_Cvar("hud_panel_scoreboard_table_bg_alpha");
+       HUD_Write_Cvar("hud_panel_scoreboard_table_bg_scale");
+       HUD_Write_Cvar("hud_panel_scoreboard_table_fg_alpha");
+       HUD_Write_Cvar("hud_panel_scoreboard_table_fg_alpha_self");
+       HUD_Write_Cvar("hud_panel_scoreboard_table_highlight");
+       HUD_Write_Cvar("hud_panel_scoreboard_table_highlight_alpha");
+       HUD_Write_Cvar("hud_panel_scoreboard_table_highlight_alpha_self");
+       HUD_Write_Cvar("hud_panel_scoreboard_table_highlight_alpha_eliminated");
+       HUD_Write_Cvar("hud_panel_scoreboard_bg_teams_color_team");
+       HUD_Write_Cvar("hud_panel_scoreboard_accuracy_doublerows");
+       HUD_Write_Cvar("hud_panel_scoreboard_accuracy_nocolors");
+}
+
 const int MAX_SBT_FIELDS = MAX_SCORE;
 
 PlayerScoreField sbt_field[MAX_SBT_FIELDS + 1];
@@ -27,12 +47,21 @@ string autocvar_hud_fontsize;
 string hud_fontsize_str;
 float max_namesize;
 
+vector duel_score_fontsize;
+vector duel_name_fontsize;
+vector duel_score_size;
+vector team_score_fontsize;
+vector team_name_fontsize;
+vector team_score_size;
+int total_medals;
+
 float sbt_bg_alpha;
 float sbt_fg_alpha;
 float sbt_fg_alpha_self;
 bool sbt_highlight;
 float sbt_highlight_alpha;
 float sbt_highlight_alpha_self;
+float sbt_highlight_alpha_eliminated;
 
 // provide basic panel cvars to old clients
 // TODO remove them after a future release (0.8.2+)
@@ -55,6 +84,7 @@ float autocvar_hud_panel_scoreboard_table_fg_alpha_self = 1;
 bool autocvar_hud_panel_scoreboard_table_highlight = true;
 float autocvar_hud_panel_scoreboard_table_highlight_alpha = 0.2;
 float autocvar_hud_panel_scoreboard_table_highlight_alpha_self = 0.4;
+float autocvar_hud_panel_scoreboard_table_highlight_alpha_eliminated = 0.6;
 float autocvar_hud_panel_scoreboard_bg_teams_color_team = 0;
 float autocvar_hud_panel_scoreboard_namesize = 15;
 float autocvar_hud_panel_scoreboard_team_size_position = 0;
@@ -65,7 +95,11 @@ bool autocvar_hud_panel_scoreboard_accuracy_nocolors = false;
 float autocvar_hud_panel_scoreboard_accuracy_showdelay = 2;
 float autocvar_hud_panel_scoreboard_accuracy_showdelay_minpos = 0.75;
 
-bool autocvar_hud_panel_scoreboard_ctf_leaderboard = true;
+bool autocvar_hud_panel_scoreboard_itemstats = true;
+bool autocvar_hud_panel_scoreboard_itemstats_doublerows = false;
+bool autocvar_hud_panel_scoreboard_itemstats_filter = true;
+float autocvar_hud_panel_scoreboard_itemstats_showdelay = 2.2; // slightly more delayed than accuracy
+float autocvar_hud_panel_scoreboard_itemstats_showdelay_minpos = 0.75;
 
 bool autocvar_hud_panel_scoreboard_dynamichud = false;
 
@@ -74,6 +108,11 @@ bool autocvar_hud_panel_scoreboard_others_showscore = true;
 bool autocvar_hud_panel_scoreboard_spectators_showping = true;
 bool autocvar_hud_panel_scoreboard_spectators_aligned = false;
 float autocvar_hud_panel_scoreboard_minwidth = 0.4;
+bool autocvar_hud_panel_scoreboard_playerid = false;
+string autocvar_hud_panel_scoreboard_playerid_prefix = "#";
+string autocvar_hud_panel_scoreboard_playerid_suffix = " ";
+
+int average_ping[NUM_TEAMS];
 
 // mode 0: returns translated label
 // mode 1: prints name and description of all the labels
@@ -84,48 +123,49 @@ string Label_getInfo(string label, int mode)
 
        switch(label)
        {
-               case "bckills":      if (!mode) return CTX(_("SCO^bckills"));      else LOG_INFO(strcat("^3", "bckills", "            ^7", _("Number of ball carrier kills")));
-               case "bctime":       if (!mode) return CTX(_("SCO^bctime"));       else LOG_INFO(strcat("^3", "bctime", "             ^7", _("Total amount of time holding the ball in Keepaway")));
-               case "caps":         if (!mode) return CTX(_("SCO^caps"));         else LOG_INFO(strcat("^3", "caps", "               ^7", _("How often a flag (CTF) or a key (KeyHunt) was captured")));
-               case "captime":      if (!mode) return CTX(_("SCO^captime"));      else LOG_INFO(strcat("^3", "captime", "            ^7", _("Time of fastest capture (CTF)")));
-               case "deaths":       if (!mode) return CTX(_("SCO^deaths"));       else LOG_INFO(strcat("^3", "deaths", "             ^7", _("Number of deaths")));
-               case "destroyed":    if (!mode) return CTX(_("SCO^destroyed"));    else LOG_INFO(strcat("^3", "destroyed", "          ^7", _("Number of keys destroyed by pushing them into void")));
-               case "dmg":          if (!mode) return CTX(_("SCO^damage"));       else LOG_INFO(strcat("^3", "dmg", "                ^7", _("The total damage done")));
-               case "dmgtaken":     if (!mode) return CTX(_("SCO^dmgtaken"));     else LOG_INFO(strcat("^3", "dmgtaken", "           ^7", _("The total damage taken")));
-               case "drops":        if (!mode) return CTX(_("SCO^drops"));        else LOG_INFO(strcat("^3", "drops", "              ^7", _("Number of flag drops")));
-               case "elo":          if (!mode) return CTX(_("SCO^elo"));          else LOG_INFO(strcat("^3", "elo", "                ^7", _("Player ELO")));
-               case "fastest":      if (!mode) return CTX(_("SCO^fastest"));      else LOG_INFO(strcat("^3", "fastest", "            ^7", _("Time of fastest lap (Race/CTS)")));
-               case "faults":       if (!mode) return CTX(_("SCO^faults"));       else LOG_INFO(strcat("^3", "faults", "             ^7", _("Number of faults committed")));
-               case "fckills":      if (!mode) return CTX(_("SCO^fckills"));      else LOG_INFO(strcat("^3", "fckills", "            ^7", _("Number of flag carrier kills")));
-               case "fps":          if (!mode) return CTX(_("SCO^fps"));          else LOG_INFO(strcat("^3", "fps", "                ^7", _("FPS")));
-               case "frags":        if (!mode) return CTX(_("SCO^frags"));        else LOG_INFO(strcat("^3", "frags", "              ^7", _("Number of kills minus suicides")));
-               case "goals":        if (!mode) return CTX(_("SCO^goals"));        else LOG_INFO(strcat("^3", "goals", "              ^7", _("Number of goals scored")));
-               case "kckills":      if (!mode) return CTX(_("SCO^kckills"));      else LOG_INFO(strcat("^3", "kckills", "            ^7", _("Number of keys carrier kills")));
-               case "kd":           if (!mode) return CTX(_("SCO^k/d"));          else LOG_INFO(strcat("^3", "kd", "                 ^7", _("The kill-death ratio")));
-               case "kdr":          if (!mode) return CTX(_("SCO^kdr"));          else LOG_INFO(strcat("^3", "kdr", "                ^7", _("The kill-death ratio")));
-               case "kdratio":      if (!mode) return CTX(_("SCO^kdratio"));      else LOG_INFO(strcat("^3", "kdratio", "            ^7", _("The kill-death ratio")));
-               case "kills":        if (!mode) return CTX(_("SCO^kills"));        else LOG_INFO(strcat("^3", "kills", "              ^7", _("Number of kills")));
-               case "laps":         if (!mode) return CTX(_("SCO^laps"));         else LOG_INFO(strcat("^3", "laps", "               ^7", _("Number of laps finished (Race/CTS)")));
-               case "lives":        if (!mode) return CTX(_("SCO^lives"));        else LOG_INFO(strcat("^3", "lives", "              ^7", _("Number of lives (LMS)")));
-               case "losses":       if (!mode) return CTX(_("SCO^losses"));       else LOG_INFO(strcat("^3", "losses", "             ^7", _("Number of times a key was lost")));
-               case "name":         if (!mode) return CTX(_("SCO^name"));         else LOG_INFO(strcat("^3", "name", "               ^7", _("Player name")));
-               case "nick":         if (!mode) return CTX(_("SCO^nick"));         else LOG_INFO(strcat("^3", "nick", "               ^7", _("Player name")));
-               case "objectives":   if (!mode) return CTX(_("SCO^objectives"));   else LOG_INFO(strcat("^3", "objectives", "         ^7", _("Number of objectives destroyed")));
-               case "pickups":      if (!mode) return CTX(_("SCO^pickups"));      else LOG_INFO(strcat("^3", "pickups", "            ^7", _("How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up")));
-               case "ping":         if (!mode) return CTX(_("SCO^ping"));         else LOG_INFO(strcat("^3", "ping", "               ^7", _("Ping time")));
-               case "pl":           if (!mode) return CTX(_("SCO^pl"));           else LOG_INFO(strcat("^3", "pl", "                 ^7", _("Packet loss")));
-               case "pushes":       if (!mode) return CTX(_("SCO^pushes"));       else LOG_INFO(strcat("^3", "pushes", "             ^7", _("Number of players pushed into void")));
-               case "rank":         if (!mode) return CTX(_("SCO^rank"));         else LOG_INFO(strcat("^3", "rank", "               ^7", _("Player rank")));
-               case "returns":      if (!mode) return CTX(_("SCO^returns"));      else LOG_INFO(strcat("^3", "returns", "            ^7", _("Number of flag returns")));
-               case "revivals":     if (!mode) return CTX(_("SCO^revivals"));     else LOG_INFO(strcat("^3", "revivals", "           ^7", _("Number of revivals")));
-               case "rounds":       if (!mode) return CTX(_("SCO^rounds won"));   else LOG_INFO(strcat("^3", "rounds", "             ^7", _("Number of rounds won")));
-               case "score":        if (!mode) return CTX(_("SCO^score"));        else LOG_INFO(strcat("^3", "score", "              ^7", _("Total score")));
-               case "suicides":     if (!mode) return CTX(_("SCO^suicides"));     else LOG_INFO(strcat("^3", "suicides", "           ^7", _("Number of suicides")));
-               case "sum":          if (!mode) return CTX(_("SCO^sum"));          else LOG_INFO(strcat("^3", "sum", "                ^7", _("Number of kills minus deaths")));
-               case "takes":        if (!mode) return CTX(_("SCO^takes"));        else LOG_INFO(strcat("^3", "takes", "              ^7", _("Number of domination points taken (Domination)")));
-               case "teamkills":    if (!mode) return CTX(_("SCO^teamkills"));    else LOG_INFO(strcat("^3", "teamkills", "          ^7", _("Number of teamkills")));
-               case "ticks":        if (!mode) return CTX(_("SCO^ticks"));        else LOG_INFO(strcat("^3", "ticks", "              ^7", _("Number of ticks (Domination)")));
-               case "time":         if (!mode) return CTX(_("SCO^time"));         else LOG_INFO(strcat("^3", "time", "               ^7", _("Total time raced (Race/CTS)")));
+               case "bckills":      if (!mode) return CTX(_("SCO^bckills"));      else LOG_HELP(strcat("^3", "bckills", "            ^7", _("Number of ball carrier kills")));
+               case "bctime":       if (!mode) return CTX(_("SCO^bctime"));       else LOG_HELP(strcat("^3", "bctime", "             ^7", _("Total amount of time holding the ball in Keepaway")));
+               case "caps":         if (!mode) return CTX(_("SCO^caps"));         else LOG_HELP(strcat("^3", "caps", "               ^7", _("How often a flag (CTF) or a key (KeyHunt) was captured")));
+               case "captime":      if (!mode) return CTX(_("SCO^captime"));      else LOG_HELP(strcat("^3", "captime", "            ^7", _("Time of fastest capture (CTF)")));
+               case "cn":               if (!mode) return CTX(_("SCO^cn"));               else LOG_HELP(strcat("^3", "cn", "                     ^7", _("Player country"))); //LegendGuard adds cn for Country column 05-04-2021
+               case "deaths":       if (!mode) return CTX(_("SCO^deaths"));       else LOG_HELP(strcat("^3", "deaths", "             ^7", _("Number of deaths")));
+               case "destroyed":    if (!mode) return CTX(_("SCO^destroyed"));    else LOG_HELP(strcat("^3", "destroyed", "          ^7", _("Number of keys destroyed by pushing them into void")));
+               case "dmg":          if (!mode) return CTX(_("SCO^damage"));       else LOG_HELP(strcat("^3", "dmg", "                ^7", _("The total damage done")));
+               case "dmgtaken":     if (!mode) return CTX(_("SCO^dmgtaken"));     else LOG_HELP(strcat("^3", "dmgtaken", "           ^7", _("The total damage taken")));
+               case "drops":        if (!mode) return CTX(_("SCO^drops"));        else LOG_HELP(strcat("^3", "drops", "              ^7", _("Number of flag drops")));
+               case "elo":          if (!mode) return CTX(_("SCO^elo"));          else LOG_HELP(strcat("^3", "elo", "                ^7", _("Player ELO")));
+               case "fastest":      if (!mode) return CTX(_("SCO^fastest"));      else LOG_HELP(strcat("^3", "fastest", "            ^7", _("Time of fastest lap (Race/CTS)")));
+               case "faults":       if (!mode) return CTX(_("SCO^faults"));       else LOG_HELP(strcat("^3", "faults", "             ^7", _("Number of faults committed")));
+               case "fckills":      if (!mode) return CTX(_("SCO^fckills"));      else LOG_HELP(strcat("^3", "fckills", "            ^7", _("Number of flag carrier kills")));
+               case "fps":          if (!mode) return CTX(_("SCO^fps"));          else LOG_HELP(strcat("^3", "fps", "                ^7", _("FPS")));
+               case "frags":        if (!mode) return CTX(_("SCO^frags"));        else LOG_HELP(strcat("^3", "frags", "              ^7", _("Number of kills minus suicides")));
+               case "goals":        if (!mode) return CTX(_("SCO^goals"));        else LOG_HELP(strcat("^3", "goals", "              ^7", _("Number of goals scored")));
+               case "kckills":      if (!mode) return CTX(_("SCO^kckills"));      else LOG_HELP(strcat("^3", "kckills", "            ^7", _("Number of keys carrier kills")));
+               case "kd":           if (!mode) return CTX(_("SCO^k/d"));          else LOG_HELP(strcat("^3", "kd", "                 ^7", _("The kill-death ratio")));
+               case "kdr":          if (!mode) return CTX(_("SCO^kdr"));          else LOG_HELP(strcat("^3", "kdr", "                ^7", _("The kill-death ratio")));
+               case "kdratio":      if (!mode) return CTX(_("SCO^kdratio"));      else LOG_HELP(strcat("^3", "kdratio", "            ^7", _("The kill-death ratio")));
+               case "kills":        if (!mode) return CTX(_("SCO^kills"));        else LOG_HELP(strcat("^3", "kills", "              ^7", _("Number of kills")));
+               case "laps":         if (!mode) return CTX(_("SCO^laps"));         else LOG_HELP(strcat("^3", "laps", "               ^7", _("Number of laps finished (Race/CTS)")));
+               case "lives":        if (!mode) return CTX(_("SCO^lives"));        else LOG_HELP(strcat("^3", "lives", "              ^7", _("Number of lives (LMS)")));
+               case "losses":       if (!mode) return CTX(_("SCO^losses"));       else LOG_HELP(strcat("^3", "losses", "             ^7", _("Number of times a key was lost")));
+               case "name":         if (!mode) return CTX(_("SCO^name"));         else LOG_HELP(strcat("^3", "name", "               ^7", _("Player name")));
+               case "nick":         if (!mode) return CTX(_("SCO^nick"));         else LOG_HELP(strcat("^3", "nick", "               ^7", _("Player name")));
+               case "objectives":   if (!mode) return CTX(_("SCO^objectives"));   else LOG_HELP(strcat("^3", "objectives", "         ^7", _("Number of objectives destroyed")));
+               case "pickups":      if (!mode) return CTX(_("SCO^pickups"));      else LOG_HELP(strcat("^3", "pickups", "            ^7", _("How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up")));
+               case "ping":         if (!mode) return CTX(_("SCO^ping"));         else LOG_HELP(strcat("^3", "ping", "               ^7", _("Ping time")));
+               case "pl":           if (!mode) return CTX(_("SCO^pl"));           else LOG_HELP(strcat("^3", "pl", "                 ^7", _("Packet loss")));
+               case "pushes":       if (!mode) return CTX(_("SCO^pushes"));       else LOG_HELP(strcat("^3", "pushes", "             ^7", _("Number of players pushed into void")));
+               case "rank":         if (!mode) return CTX(_("SCO^rank"));         else LOG_HELP(strcat("^3", "rank", "               ^7", _("Player rank")));
+               case "returns":      if (!mode) return CTX(_("SCO^returns"));      else LOG_HELP(strcat("^3", "returns", "            ^7", _("Number of flag returns")));
+               case "revivals":     if (!mode) return CTX(_("SCO^revivals"));     else LOG_HELP(strcat("^3", "revivals", "           ^7", _("Number of revivals")));
+               case "rounds":       if (!mode) return CTX(_("SCO^rounds won"));   else LOG_HELP(strcat("^3", "rounds", "             ^7", _("Number of rounds won")));
+               case "score":        if (!mode) return CTX(_("SCO^score"));        else LOG_HELP(strcat("^3", "score", "              ^7", _("Total score")));
+               case "suicides":     if (!mode) return CTX(_("SCO^suicides"));     else LOG_HELP(strcat("^3", "suicides", "           ^7", _("Number of suicides")));
+               case "sum":          if (!mode) return CTX(_("SCO^sum"));          else LOG_HELP(strcat("^3", "sum", "                ^7", _("Number of kills minus deaths")));
+               case "takes":        if (!mode) return CTX(_("SCO^takes"));        else LOG_HELP(strcat("^3", "takes", "              ^7", _("Number of domination points taken (Domination)")));
+               case "teamkills":    if (!mode) return CTX(_("SCO^teamkills"));    else LOG_HELP(strcat("^3", "teamkills", "          ^7", _("Number of teamkills")));
+               case "ticks":        if (!mode) return CTX(_("SCO^ticks"));        else LOG_HELP(strcat("^3", "ticks", "              ^7", _("Number of ticks (Domination)")));
+               case "time":         if (!mode) return CTX(_("SCO^time"));         else LOG_HELP(strcat("^3", "time", "               ^7", _("Total time raced (Race/CTS)")));
                default: return label;
        }
        return label;
@@ -309,34 +349,34 @@ void Scoreboard_UpdateTeamPos(entity Team)
 
 void Cmd_Scoreboard_Help()
 {
-       LOG_INFO(_("You can modify the scoreboard using the ^2scoreboard_columns_set command."));
-       LOG_INFO(_("Usage:"));
-       LOG_INFO("^2scoreboard_columns_set ^3default");
-       LOG_INFO(_("^2scoreboard_columns_set ^3field1 field2 ..."));
-       LOG_INFO(_("^2scoreboard_columns_set ^7without arguments reads the arguments from the cvar scoreboard_columns"));
-       LOG_INFO(_("  ^5Note: ^7scoreboard_columns_set without arguments is executed on every map start"));
-       LOG_INFO(_("^2scoreboard_columns_set ^3expand_default ^7loads default layout and expands it into the cvar scoreboard_columns so you can edit it"));
-       LOG_INFO(_("You can use a ^3|^7 to start the right-aligned fields."));
-       LOG_INFO(_("The following field names are recognized (case insensitive):"));
-       LOG_INFO("");
+       LOG_HELP(_("You can modify the scoreboard using the ^2scoreboard_columns_set command."));
+       LOG_HELP(_("Usage:"));
+       LOG_HELP("^2scoreboard_columns_set ^3default");
+       LOG_HELP(_("^2scoreboard_columns_set ^3field1 field2 ..."));
+       LOG_HELP(_("^2scoreboard_columns_set ^7without arguments reads the arguments from the cvar scoreboard_columns"));
+       LOG_HELP(_("  ^5Note: ^7scoreboard_columns_set without arguments is executed on every map start"));
+       LOG_HELP(_("^2scoreboard_columns_set ^3expand_default ^7loads default layout and expands it into the cvar scoreboard_columns so you can edit it"));
+       LOG_HELP(_("You can use a ^3|^7 to start the right-aligned fields."));
+       LOG_HELP(_("The following field names are recognized (case insensitive):"));
+       LOG_HELP("");
 
        PrintScoresLabels();
-       LOG_INFO("");
+       LOG_HELP("");
 
-       LOG_INFO(_("Before a field you can put a + or - sign, then a comma separated list\n"
+       LOG_HELP(_("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"
                "or in all but these game types. You can also specify 'all' as a\n"
                "field to show all fields available for the current game mode."));
-       LOG_INFO("");
+       LOG_HELP("");
 
-       LOG_INFO(_("The special game type names 'teams' and 'noteams' can be used to\n"
+       LOG_HELP(_("The special game type names 'teams' and 'noteams' can be used to\n"
                "include/exclude ALL teams/noteams game modes."));
-       LOG_INFO("");
+       LOG_HELP("");
 
-       LOG_INFO(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4"));
-       LOG_INFO(_("will display name, ping and pl aligned to the left, and the fields\n"
+       LOG_HELP(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4"));
+       LOG_HELP(_("will display name, ping and pl aligned to the left, and the fields\n"
                "right of the vertical bar aligned to the right."));
-       LOG_INFO(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
+       LOG_HELP(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
                        "other gamemodes except DM."));
 }
 
@@ -345,7 +385,7 @@ void Cmd_Scoreboard_Help()
 // otherwise the previous exclusive rule warns anyway
 // e.g. -teams,rc,cts,lms/kills ?+rc/kills
 #define SCOREBOARD_DEFAULT_COLUMNS \
-"ping pl fps name |" \
+"ping pl fps cn name |" \
 " -teams,rc,cts,inv,lms/kills +ft,tdm/kills ?+rc,inv/kills" \
 " -teams,lms/deaths +ft,tdm/deaths" \
 " +tdm/sum" \
@@ -395,7 +435,7 @@ void Cmd_Scoreboard_SetFields(int argc)
                }
                else if(argv(2) == "all")
                {
-                       string s = "ping pl name |"; // scores without a label
+                       string s = "ping pl cn name |"; // scores without a label
                        FOREACH(Scores, true, {
                                if(it != ps_primary)
                                if(it != ps_secondary)
@@ -413,6 +453,14 @@ void Cmd_Scoreboard_SetFields(int argc)
        sbt_num_fields = 0;
 
        hud_fontsize = HUD_GetFontsize("hud_fontsize");
+       
+       duel_score_fontsize = hud_fontsize * 3;
+       duel_name_fontsize = hud_fontsize * 1.5;
+       duel_score_size = vec2(duel_score_fontsize.x * 1.5, duel_score_fontsize.y * 1.25);
+       
+       team_score_fontsize = hud_fontsize * 2;
+       team_name_fontsize = hud_fontsize * 1.5;
+       team_score_size = vec2(team_score_fontsize.x * 1.5, team_score_fontsize.y * 1.25);
 
        for(i = 1; i < argc - 1; ++i)
        {
@@ -445,6 +493,7 @@ void Cmd_Scoreboard_SetFields(int argc)
                        case "pl": sbt_field[sbt_num_fields] = SP_PL; break;
                        case "kd": case "kdr": case "kdratio": sbt_field[sbt_num_fields] = SP_KDRATIO; break;
                        case "sum": case "diff": case "k-d": sbt_field[sbt_num_fields] = SP_SUM; break;
+                       case "cn": sbt_field[sbt_num_fields] = SP_COUNTRY; break; //LegendGuard adds cn label for Country column 05-04-2021
                        case "name": case "nick": sbt_field[sbt_num_fields] = SP_NAME; have_name = true; break;
                        case "|": sbt_field[sbt_num_fields] = SP_SEPARATOR; have_separator = true; break;
                        case "elo": sbt_field[sbt_num_fields] = SP_ELO; break;
@@ -552,11 +601,19 @@ LABEL(found)
        sbt_field[sbt_num_fields] = SP_END;
 }
 
+string Scoreboard_AddPlayerId(string pl_name, entity pl)
+{
+       string pref = autocvar_hud_panel_scoreboard_playerid_prefix;
+       string suf = autocvar_hud_panel_scoreboard_playerid_suffix;
+       return strcat(pref, itos(pl.sv_entnum + 1), suf, pl_name);
+}
+
 // MOVEUP::
 vector sbt_field_rgb;
 string sbt_field_icon0;
 string sbt_field_icon1;
 string sbt_field_icon2;
+string sbt_field_icon3; //LegendGuard adds for Country player flags 05-04-2021
 vector sbt_field_icon0_rgb;
 vector sbt_field_icon1_rgb;
 vector sbt_field_icon2_rgb;
@@ -577,9 +634,30 @@ string Scoreboard_GetName(entity pl)
                        sbt_field_icon2_rgb = colormapPaletteColor(f % 16, 1);
                }
        }
+       
        return entcs_GetName(pl.sv_entnum);
 }
 
+//LegendGuard adds GetCountrycode function 05-04-2021
+string Scoreboard_GetCountrycode(entity pl)
+{
+       int ccode = entcs_GetCountryCode(pl.sv_entnum);
+       if(ccode)
+               sbt_field_icon3 = strcat("gfx/flags/", ftos(ccode));
+
+       return ftos(entcs_GetCountryCode(pl.sv_entnum));
+}
+
+vector getPingColor(float f)
+{
+       if(f < 80) {
+               // 20-80 range is green
+               return '0 1 0' + '1 0 1' * max(0, min(60, f-20)) / 60;
+       } else {
+               // 80-300 range is red
+               return '1 1 1' - '0 1 1' * max(0, min(220, f-80)) / 220;
+       }
+}
 string Scoreboard_GetField(entity pl, PlayerScoreField field)
 {
        float tmp, num, denom;
@@ -589,6 +667,7 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field)
        sbt_field_icon0 = "";
        sbt_field_icon1 = "";
        sbt_field_icon2 = "";
+       sbt_field_icon3 = ""; //LegendGuard adds for Country column 05-04-2021
        sbt_field_icon0_rgb = '1 1 1';
        sbt_field_icon1_rgb = '1 1 1';
        sbt_field_icon2_rgb = '1 1 1';
@@ -601,9 +680,10 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field)
                        f = pl.ping;
                        if(f == 0)
                                return _("N/A");
-                       tmp = max(0, min(220, f-80)) / 220;
-                       sbt_field_rgb = '1 1 1' - '0 1 1' * tmp;
+                       sbt_field_rgb = getPingColor(f);
+                       
                        return ftos(f);
+                       //return ftos(pl.team);
 
                case SP_PL:
                        if (!pl.gotscores)
@@ -618,9 +698,19 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field)
                        tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
                        sbt_field_rgb = '1 0.5 0.5' - '0 0.5 0.5' * tmp;
                        return str;
+               
+               //LegendGuard adds Country REGISTER in the switch 05-04-2021
+               case SP_COUNTRY:
+               {
+                       str = Scoreboard_GetCountrycode(pl);
+                       return str;
+               }
 
                case SP_NAME:
-                       return Scoreboard_GetName(pl);
+                       str = Scoreboard_GetName(pl);
+                       if (autocvar_hud_panel_scoreboard_playerid)
+                               str = Scoreboard_AddPlayerId(str, pl);
+                       return str;
 
                case SP_FRAGS:
                        f = pl.(scores(SP_KILLS));
@@ -672,7 +762,8 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field)
                                sbt_field_rgb = '1 1 1';
                                return ((pl.ping == 0) ? _("N/A") : "..."); // if 0 ping, either connecting or bot (either case can't show proper score)
                        }
-                       //sbt_field_rgb = HUD_Get_Num_Color(fps, 200);
+
+                       //sbt_field_rgb = HUD_Get_Num_Color(fps, 200, true);
                        sbt_field_rgb = '1 0 0' + '0 1 1' * (bound(0, fps, 60) / 60);
                        return ftos(fps);
                }
@@ -730,6 +821,15 @@ string Scoreboard_FixColumnWidth(int i, string str)
                        sbt_fixcolumnwidth_iconlen = f;
        }
 
+       //LegendGuard adds conditional for Country column 05-04-2021
+       if(sbt_field_icon3 != "")
+       {
+               sz = draw_getimagesize(sbt_field_icon3);
+               f = sz.x / sz.y;
+               if(sbt_fixcolumnwidth_iconlen < f)
+                       sbt_fixcolumnwidth_iconlen = f;
+       }
+
        if(sbt_fixcolumnwidth_iconlen != 0)
        {
                sbt_fixcolumnwidth_iconlen *= hud_fontsize.y / hud_fontsize.x; // fix icon aspect
@@ -775,10 +875,13 @@ void Scoreboard_initFieldSizes()
        }
 }
 
-vector Scoreboard_DrawHeader(vector pos, vector rgb, bool other_players)
+vector Scoreboard_DrawHeader(vector pos, vector rgb, bool other_players, int team)
 {
        int i;
+       string title_str;
+       vector title_rgb;
        vector column_dim = eY * panel_size.y;
+       
        if(other_players)
                column_dim.y -= 1.25 * hud_fontsize.y;
        vector text_offset = eY * (1.25 - 1) / 2 * hud_fontsize.y;
@@ -787,11 +890,23 @@ vector Scoreboard_DrawHeader(vector pos, vector rgb, bool other_players)
        {
                if(sbt_field[i] == SP_SEPARATOR)
                        break;
+               
+               vector text_offset_center = '0 0 0';
+               
+               if(sbt_field[i] == SP_PING && teamplay) {
+                       title_str = sprintf("(%d)", average_ping[Team_TeamToIndex(team) - 1]);
+                       title_rgb = getPingColor(average_ping[Team_TeamToIndex(team) - 1]);
+                       text_offset_center.x = sbt_field_size[i] - stringwidth(title_str, false, hud_fontsize);
+               } else {
+                       title_str = sbt_field_title[i];
+                       title_rgb = rgb * 1.5;
+               }
+               
                column_dim.x = sbt_field_size[i] + hud_fontsize.x;
                if (sbt_highlight)
                        if (i % 2)
                                drawfill(pos - eX * hud_fontsize.x * 0.5, column_dim, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
-               drawstring(pos + text_offset, sbt_field_title[i], hud_fontsize, rgb * 1.5, sbt_fg_alpha, DRAWFLAG_NORMAL);
+               drawstring(pos + text_offset + text_offset_center, title_str, hud_fontsize, title_rgb, sbt_fg_alpha, DRAWFLAG_NORMAL);
                pos.x += column_dim.x;
        }
        if(sbt_field[i] == SP_SEPARATOR)
@@ -841,7 +956,7 @@ void Scoreboard_DrawItem(vector item_pos, vector rgb, entity pl, bool is_self, i
        vector pos = item_pos;
        // put a "self indicator" beside the self row, unicode U+25C0 (black left-pointing triangle)
        if (is_self)
-               drawstring(pos+eX*(panel_size.x+.5*hud_fontsize.x)+eY, "\xE2\x97\x80", vec2(hud_fontsize.x, hud_fontsize.y), rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawstring(pos + eX * (panel_size.x + 0.5 * hud_fontsize.x) + eY, "\xE2\x97\x80", hud_fontsize, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
 
        pos.x += hud_fontsize.x * 0.5;
        pos.y += (1.25 - 1) / 2 * hud_fontsize.y; // center text vertically
@@ -878,6 +993,8 @@ void Scoreboard_DrawItem(vector item_pos, vector rgb, entity pl, bool is_self, i
                        drawpic(pos - tmp, sbt_field_icon1, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon1_rgb, fg_alpha, DRAWFLAG_NORMAL);
                if(sbt_field_icon2 != "")
                        drawpic(pos - tmp, sbt_field_icon2, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon2_rgb, fg_alpha, DRAWFLAG_NORMAL);
+               if(sbt_field_icon3 != "") //LegendGuard adds conditional for Country column 05-04-2021
+                       drawpic(pos - tmp, sbt_field_icon3, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon1_rgb, fg_alpha, DRAWFLAG_NORMAL);
        }
 
        if(sbt_field[i] == SP_SEPARATOR)
@@ -912,12 +1029,14 @@ void Scoreboard_DrawItem(vector item_pos, vector rgb, entity pl, bool is_self, i
                                drawpic(pos - tmp, sbt_field_icon1, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon1_rgb, fg_alpha, DRAWFLAG_NORMAL);
                        if(sbt_field_icon2 != "")
                                drawpic(pos - tmp, sbt_field_icon2, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon2_rgb, fg_alpha, DRAWFLAG_NORMAL);
+                       if(sbt_field_icon3 != "") //LegendGuard adds conditional for Country column 05-04-2021
+                               drawpic(pos - tmp, sbt_field_icon3, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon1_rgb, fg_alpha, DRAWFLAG_NORMAL);
                        pos.x -= sbt_field_size[i] + hud_fontsize.x;
                }
        }
 
        if(pl.eliminated)
-               drawfill(h_pos, h_size, '0 0 0', 0.5 * panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawfill(h_pos, h_size, '0 0 0', sbt_highlight_alpha_eliminated, DRAWFLAG_NORMAL);
 }
 
 vector Scoreboard_DrawOthers(vector item_pos, vector rgb, int this_team, entity ignored_pl, entity pl, int pl_number)
@@ -968,7 +1087,10 @@ vector Scoreboard_DrawOthers(vector item_pos, vector rgb, int this_team, entity
                else if(autocvar_hud_panel_scoreboard_others_showscore)
                        field = Scoreboard_GetField(pl, SP_SCORE);
 
-               string str = textShortenToWidth(entcs_GetName(pl.sv_entnum), namesize, hud_fontsize, stringwidth_colors);
+               string str = entcs_GetName(pl.sv_entnum);
+               if (autocvar_hud_panel_scoreboard_playerid)
+                       str = Scoreboard_AddPlayerId(str, pl);
+               str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
                float column_width = stringwidth(str, true, hud_fontsize);
                if((this_team == NUM_SPECTATOR) && autocvar_hud_panel_scoreboard_spectators_aligned)
                {
@@ -1017,7 +1139,7 @@ vector Scoreboard_DrawOthers(vector item_pos, vector rgb, int this_team, entity
                {
                        h_size.x = column_width + hud_fontsize.x * 0.25;
                        h_size.y = hud_fontsize.y;
-                       drawfill(pos - hud_fontsize.x * 0.25 * eX, h_size, '0 0 0', 0.5 * panel_fg_alpha, DRAWFLAG_NORMAL);
+                       drawfill(pos - hud_fontsize.x * 0.25 * eX, h_size, '0 0 0', sbt_highlight_alpha_eliminated, DRAWFLAG_NORMAL);
                }
                pos.x += column_width;
                pos.x += hud_fontsize.x;
@@ -1025,6 +1147,300 @@ vector Scoreboard_DrawOthers(vector item_pos, vector rgb, int this_team, entity
        return vec2(item_pos.x, item_pos.y + i * hud_fontsize.y * 1.25);
 }
 
+vector Scoreboard_DrawMedal(vector pos, string icon, float height, float number)
+{
+       if(!number) return pos;
+       total_medals += number;
+       
+       vector tmp_sz, tmp_sz2;
+       tmp_sz = draw_getimagesize(icon);
+       tmp_sz2 = vec2(height*(tmp_sz.x/tmp_sz.y), height);
+       string val = ftos(number);
+       
+       drawpic(pos, icon, tmp_sz2, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       pos.x += tmp_sz2.x + hud_fontsize.x * 0.25;
+       drawstring(pos + eY * ((tmp_sz2.y - hud_fontsize.y) / 2), val, hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       pos.x += stringwidth(val, false, hud_fontsize) + hud_fontsize.x * 0.5;
+       return pos;
+}
+
+vector Scoreboard_Duel_DrawPickup(vector pos, bool skinned, string icon, vector sz, float number, bool invert)
+{
+       vector tmp_in = pos;
+       vector tmp_sz, tmp_sz2;
+       string picpath;
+       
+       // Icon
+       if(skinned) {
+               picpath = strcat(hud_skin_path, "/", icon);
+               if(precache_pic(picpath) == "")
+                       picpath = strcat("gfx/hud/default/", icon);
+       } else {
+               picpath = icon;
+       }
+               
+       tmp_sz = draw_getimagesize(picpath);
+       tmp_sz2 = vec2(sz.y*(tmp_sz.x/tmp_sz.y), sz.y);
+       
+       tmp_in.x = pos.x + ((sz.x - tmp_sz2.x) / 2);
+       drawpic(tmp_in, picpath, tmp_sz2, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       // Number
+       if(invert)
+               tmp_in.x += tmp_sz2.x + hud_fontsize.x * 0.25;
+       else
+               tmp_in.x -= hud_fontsize.x * 0.25 + hud_fontsize.x;
+       
+       tmp_in.y += (tmp_sz2.y - hud_fontsize.y) / 2;
+       drawstring(tmp_in,
+               ((number == -1) ? "?" : ftos(number)),
+               hud_fontsize, ((number > 0) ? '1 1 1' : '0.5 0.5 0.5'),
+               panel_fg_alpha,
+               DRAWFLAG_NORMAL);
+       
+       pos.y += sz.y * 1.1;
+       return pos;
+}
+
+void Scoreboard_Duel_DrawTable(vector pos, bool invert, entity pl, entity tm)
+{
+       vector tmp, tmp_in, tmp_sz, tmp_acc;
+       string tmp_str;
+       float sz;
+       float average_acc = 0;
+       
+       panel_pos = pos;
+       
+       HUD_Panel_DrawBg();
+       
+       // Stop here if there are no scores available
+       if(pl.team != tm.team) return;
+       
+       tmp = pos;
+       tmp.x += panel_bg_padding;
+       tmp.y += panel_bg_padding;
+       panel_size.x -= panel_bg_padding * 2;
+       
+       //if (sbt_bg_alpha)
+       //      drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", tmp, panel_size, rgb, sbt_bg_alpha, DRAWFLAG_NORMAL);
+
+       // Score: highlight
+       if(invert) { tmp.x += panel_size.x; tmp.x -= duel_score_size.x; }
+       drawfill(tmp, duel_score_size, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
+       
+       // Score: text
+       tmp_str = ftos(pl.(scores(SP_SCORE)));
+       tmp_in = tmp;
+       tmp_in.x += (duel_score_size.x / 2) - (stringwidth(tmp_str, true, duel_score_fontsize) / 2);
+       tmp_in.y += (duel_score_size.y / 2) - (duel_score_fontsize.y / 2);
+       
+       draw_beginBoldFont();
+       drawstring(tmp_in, tmp_str, duel_score_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       draw_endBoldFont();
+       
+       // Player name
+       tmp_str = Scoreboard_GetField(pl, SP_NAME);
+       tmp_in = tmp;
+       if(invert)
+               tmp_in.x -= stringwidth_colors(tmp_str, duel_name_fontsize) + duel_name_fontsize.x * 0.5;
+       else
+               tmp_in.x += duel_score_size.x + duel_name_fontsize.x * 0.5;
+       tmp_in.y += (duel_score_size.y - duel_name_fontsize.y) / 2;
+       drawcolorcodedstring(tmp_in, tmp_str, duel_name_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       // Player icon/flag
+       if(sbt_field_icon0 != "") {
+               vector rsz = draw_getimagesize(sbt_field_icon0);
+               sbt_fixcolumnwidth_iconlen = rsz.x / rsz.y;
+               if(invert)
+                       tmp_in.x -= hud_fontsize.x * sbt_fixcolumnwidth_iconlen + duel_name_fontsize.x * 0.5;
+               else
+                       tmp_in.x += stringwidth_colors(tmp_str, duel_name_fontsize) + duel_name_fontsize.x * 0.5;
+               tmp_in.y += (duel_name_fontsize.y - hud_fontsize.y) / 2;
+               drawpic(tmp_in, sbt_field_icon0, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon1_rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+       }
+
+       //LegendGuard adds a conditional sentence for country column 05-04-2021
+       // Player country icon/flag
+       if(sbt_field_icon3 != "") {
+               vector rsz = draw_getimagesize(sbt_field_icon3);
+               sbt_fixcolumnwidth_iconlen = rsz.x / rsz.y;
+               if(invert)
+                       tmp_in.x -= hud_fontsize.x * sbt_fixcolumnwidth_iconlen + duel_name_fontsize.x * 0.5;
+               else
+                       tmp_in.x += stringwidth_colors(tmp_str, duel_name_fontsize) + duel_name_fontsize.x * 0.5;
+               tmp_in.y += (duel_name_fontsize.y - hud_fontsize.y) / 2;
+               drawpic(tmp_in, sbt_field_icon3, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon1_rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+       }
+       
+       // Header
+       float column_width = panel_size.x / 5;
+       tmp.x = pos.x + panel_bg_padding;
+       tmp.y += hud_fontsize.y * 3 + hud_fontsize.y;
+       
+       vector column_dim;
+       int i;
+
+       i = (invert ? 4 : 0);
+       column_dim = vec2(column_width * 4, hud_fontsize.y);
+       
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("kills", false, hud_fontsize) / 2),
+               "kills", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("dmg", false, hud_fontsize) / 2),
+               "dmg", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("acc", false, hud_fontsize) / 2),
+               "acc", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("hits", false, hud_fontsize) / 2),
+               "hits", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("ping", false, hud_fontsize) / 2),
+               "ping", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       tmp.x = pos.x + panel_bg_padding;
+       tmp.y += hud_fontsize.y;
+       
+       // Main row
+       i = (invert ? 4 : 0);
+       
+       tmp_str = ftos(pl.(scores(SP_KILLS)));
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+               tmp_str, hud_fontsize  * 1.25, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       tmp_str = ftos(pl.(scores(SP_DMG)));
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+               tmp_str, hud_fontsize  * 1.25, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               
+       tmp_acc = tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2);
+               
+       if(invert)
+               i--;
+       else
+               i++;
+       
+       tmp_str = Scoreboard_GetField(pl, SP_PING);
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+               tmp_str, hud_fontsize * 1.25, sbt_field_rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       tmp.x = pos.x + panel_bg_padding;
+       tmp.y += hud_fontsize.y * 2;
+       
+       tmp_in = tmp;
+       
+       int total_weapons = 0;
+       
+       // Accuracy rows
+       WepSet weapons_inmap = WepSet_GetFromStat_InMap();
+       FOREACH(Weapons, it != WEP_Null, {
+               WepSet set = it.m_wepset;
+               if (!(weapons_inmap & set))
+                       continue;
+               if (it.spawnflags & WEP_TYPE_OTHER)
+                       continue;
+               
+               int weapon_cnt_fired = pl.accuracy_cnt_fired[i - WEP_FIRST];
+               int weapon_cnt_hit   = pl.accuracy_cnt_hit[i - WEP_FIRST];
+               int weapon_acc = 0;
+               if(weapon_cnt_fired)
+                       weapon_acc = floor((weapon_cnt_hit / weapon_cnt_fired) * 100);
+               average_acc += weapon_acc;
+               
+               string draw_str;
+               
+               // weapon stats
+               int c = (invert ? 4 : 0);
+               
+               drawfill(tmp_in + eX * column_width * (invert ? 1 : 0), column_dim, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
+               
+               draw_str = ftos(pl.accuracy_frags[i - WEP_FIRST]);
+               drawstring(tmp_in + eX * column_width * (invert ? c-- : c++) + eX * ((column_width - stringwidth(draw_str, false, hud_fontsize)) / 2),
+                       draw_str, hud_fontsize, (weapon_cnt_fired ? '1 1 1' : '0.5 0.5 0.5'), panel_fg_alpha, DRAWFLAG_NORMAL);
+               
+               draw_str = ftos(pl.accuracy_hit[i - WEP_FIRST]);
+               drawstring(tmp_in + eX * column_width * (invert ? c-- : c++) + eX * ((column_width - stringwidth(draw_str, false, hud_fontsize)) / 2),
+                       draw_str, hud_fontsize, (weapon_cnt_fired ? '1 1 1' : '0.5 0.5 0.5'), panel_fg_alpha, DRAWFLAG_NORMAL);
+                       
+               draw_str = sprintf("%d%%", weapon_acc);
+               drawstring(tmp_in + eX * column_width * (invert ? c-- : c++) + eX * ((column_width - stringwidth(draw_str, false, hud_fontsize)) / 2),
+                       draw_str, hud_fontsize, (weapon_cnt_fired ? '1 1 1' : '0.5 0.5 0.5'), panel_fg_alpha, DRAWFLAG_NORMAL);
+                       
+               draw_str = strcat(ftos(weapon_cnt_hit), " / ", ftos(weapon_cnt_fired));
+               drawstring(tmp_in + eX * column_width * (invert ? c-- : c++) + eX * (column_width / 2) - eX * stringwidth("36 /", false, hud_fontsize),
+                       draw_str,hud_fontsize, (weapon_cnt_fired ? '1 1 1' : '0.5 0.5 0.5'), panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+               // weapon icon
+               if(invert) {
+                       tmp_in.x = pos.x + panel_size.x - panel_bg_padding - hud_fontsize.x / 2;
+                       drawpic_aspect_skin(tmp_in, it.model2, vec2(50, hud_fontsize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               }
+               
+               tmp_in.x = pos.x + panel_bg_padding;
+               tmp_in.y += hud_fontsize.y * 1.25;
+               
+               if(weapon_cnt_fired)
+                       total_weapons++;
+       });
+       if(total_weapons)
+               average_acc = floor((average_acc / total_weapons) + 0.5);
+       
+       // draw total accuracy now
+       tmp_str = sprintf("%d%%", average_acc);
+       drawstring(tmp_acc - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+               tmp_str, hud_fontsize * 1.25, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       // Icon column
+       vector icon_sz = vec2(column_width, hud_fontsize.y*1.5);
+       
+       if(!invert)
+               tmp.x += column_width * 4;
+       // Medal rows
+       drawstring(tmp + eX * ((column_width - stringwidth("medals", false, hud_fontsize)) / 2),
+               "medals", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       tmp.y += hud_fontsize.y * 1.25;
+       
+       tmp = Scoreboard_Duel_DrawPickup(tmp, false, "gfx/medal/humiliation", icon_sz, pl.(scores(SP_MEDAL_HUMILIATION)), invert);
+       tmp = Scoreboard_Duel_DrawPickup(tmp, false, "gfx/medal/impressive", icon_sz, pl.(scores(SP_MEDAL_IMPRESSIVE)), invert);
+       tmp = Scoreboard_Duel_DrawPickup(tmp, false, "gfx/medal/excellent", icon_sz, pl.(scores(SP_MEDAL_EXCELLENT)), invert);
+       
+       // Item rows
+       drawstring(tmp + eX * ((column_width - stringwidth("items", false, hud_fontsize)) / 2),
+               "items", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       tmp.y += hud_fontsize.y * 1.25;
+       
+       float inv_num = -1;
+       FOREACH(Items,
+               it.m_id == ITEM_ArmorMega.m_id ||
+               it.m_id == ITEM_HealthMega.m_id ||
+               it.m_id == ITEM_ArmorBig.m_id, {
+               // If the match isn't over, Only show pickups if we're spectating or they're our own
+               if(intermission || warmup_stage || spectatee_status || pl.sv_entnum == current_player)
+                       inv_num = inventoryslots[pl.sv_entnum].inv_items[it.m_id];
+               tmp = Scoreboard_Duel_DrawPickup(tmp, true, it.m_icon, icon_sz, inv_num, invert);
+               
+               if(it.m_id == REGISTRY_MAX(Items))
+               break;
+       });
+}
+vector Scoreboard_MakeDuelTable(vector pos, entity tm, vector rgb, vector bg_size)
+{
+       vector end_pos = pos;
+       float screen_half = panel_size.x / 2;
+       float weapon_margin = hud_fontsize.x;
+       
+       panel_size.x = screen_half - weapon_margin;
+       panel_size.y = (duel_score_size.y * 5.5);
+       
+       entity pl_left = players.sort_next;
+       entity pl_right = pl_left.sort_next;
+       
+       Scoreboard_Duel_DrawTable(pos, true, pl_left, tm);
+       Scoreboard_Duel_DrawTable(pos + eX * screen_half + eX * weapon_margin, false, pl_right, tm);
+       
+       end_pos.y += panel_size.y + (panel_bg_padding * 2);
+       panel_size.x = screen_half * 2;
+       return end_pos;
+}
+
 vector Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
 {
        int max_players = 999;
@@ -1053,7 +1469,7 @@ vector Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
        panel_size.y += panel_bg_padding * 2;
        HUD_Panel_DrawBg();
 
-       vector end_pos = panel_pos + eY * (panel_size.y + 0.5* hud_fontsize.y);
+       vector end_pos = panel_pos + eY * (panel_size.y + 0.5 * hud_fontsize.y);
        if(panel.current_panel_bg != "0")
                end_pos.y += panel_bg_border * 2;
 
@@ -1079,12 +1495,14 @@ vector Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
 
 
        // print header row and highlight columns
-       pos = Scoreboard_DrawHeader(panel_pos, rgb, (max_players < tm.team_size));
+       pos = Scoreboard_DrawHeader(panel_pos, rgb, (max_players < tm.team_size), tm.team);
 
        // fill the table and draw the rows
        bool is_self = false;
        bool self_shown = false;
        int i = 0;
+       int with_ping = 0;
+       if(Team_IsValidTeam(tm.team)) average_ping[Team_TeamToIndex(tm.team) - 1] = 0;
        for(pl = players.sort_next; pl; pl = pl.sort_next)
        {
                if(pl.team != tm.team)
@@ -1106,11 +1524,17 @@ vector Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
                }
                is_self = (pl.sv_entnum == current_player);
                Scoreboard_DrawItem(pos, rgb, pl, is_self, i);
+               
+               if(Team_IsValidTeam(tm.team) && pl.ping) {
+                       average_ping[Team_TeamToIndex(tm.team) - 1] += pl.ping;
+                       ++with_ping;
+               }
                if(is_self)
                        self_shown = true;
                pos.y += 1.25 * hud_fontsize.y;
                ++i;
        }
+       if(with_ping) average_ping[Team_TeamToIndex(tm.team) - 1] /= with_ping;
 
        panel_size.x += panel_bg_padding * 2; // restore initial width
        return end_pos;
@@ -1130,27 +1554,63 @@ bool Scoreboard_WouldDraw()
                return true;
        else if (intermission == 2)
                return false;
-       else if (spectatee_status != -1 && STAT(HEALTH) <= 0 && autocvar_cl_deathscoreboard && !ISGAMETYPE(CTS)
+       else if (spectatee_status != -1 && STAT(HEALTH) <= 0 && autocvar_cl_deathscoreboard && !MUTATOR_CALLHOOK(DrawDeathScoreboard)
                && (!HUD_MinigameMenu_IsOpened() || !active_minigame))
        {
                return true;
        }
-       else if (scoreboard_showscores_force)
+       else if (scoreboard_showscores_force || MUTATOR_CALLHOOK(DrawScoreboard_Force))
                return true;
        return false;
 }
 
+vector Scoreboard_MedalStats_Draw(vector pos)
+{
+       vector orig = pos;
+       float height = hud_fontsize.y * 2;
+       
+       entity pl = playerslots[current_player];
+       
+       vector title_pos = pos;
+       pos.x += 0.5 * hud_fontsize.x + panel_bg_padding;
+       pos.y += 1.25 * hud_fontsize.y;
+       
+       total_medals = 0;
+       
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/airshot",            height, pl.(scores(SP_MEDAL_AIRSHOT)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/damage",             height, pl.(scores(SP_MEDAL_DAMAGE)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/electrobitch",       height, pl.(scores(SP_MEDAL_ELECTROBITCH)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/excellent",          height, pl.(scores(SP_MEDAL_EXCELLENT)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/firstblood",         height, pl.(scores(SP_MEDAL_FIRSTBLOOD)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/headshot",           height, pl.(scores(SP_MEDAL_HEADSHOT)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/humiliation",        height, pl.(scores(SP_MEDAL_HUMILIATION)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/impressive",         height, pl.(scores(SP_MEDAL_IMPRESSIVE)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/yoda",                       height, pl.(scores(SP_MEDAL_YODA)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/telefrag",           height, pl.(scores(SP_MEDAL_TELEFRAG)));
+       
+       if(total_medals)
+               pos.x += hud_fontsize.x;
+       
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/accuracy",           height, pl.(scores(SP_MEDAL_ACCURACY)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/assist",             height, pl.(scores(SP_MEDAL_ASSIST)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/capture",            height, pl.(scores(SP_MEDAL_CAPTURE)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/defense",            height, pl.(scores(SP_MEDAL_DEFENSE)));
+       pos = Scoreboard_DrawMedal(pos, "gfx/medal/perfect",            height, pl.(scores(SP_MEDAL_PERFECT)));
+       
+       if(!total_medals) return orig;
+       
+       drawstring(title_pos, sprintf(_("Medal stats (total %d)"), total_medals),
+               hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       pos.x = orig.x;
+       pos.y += height + hud_fontsize.y * 0.5;
+       return pos;
+}
+
 float average_accuracy;
 vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
 {
-       if (frametime)
-       {
-               if (scoreboard_fade_alpha == 1)
-                       scoreboard_acc_fade_alpha = min(1, scoreboard_acc_fade_alpha + frametime * 10);
-               else
-                       scoreboard_acc_fade_alpha = 1; // sync fading with the scoreboard
-       }
-       vector initial_pos = pos;
+       scoreboard_acc_fade_alpha = min(scoreboard_fade_alpha, scoreboard_acc_fade_alpha + frametime * 10);
 
        WepSet weapons_stat = WepSet_GetFromStat();
        WepSet weapons_inmap = WepSet_GetFromStat_InMap();
@@ -1174,11 +1634,11 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
                }
        });
 
-       int weapon_cnt = (Weapons_COUNT - 1) - disownedcnt - nHidden;
+       int weapon_cnt = (REGISTRY_COUNT(Weapons) - 1) - disownedcnt - nHidden;
        if (weapon_cnt <= 0) return pos;
 
        int rows = 1;
-       if (autocvar_hud_panel_scoreboard_accuracy_doublerows && weapon_cnt >= floor((Weapons_COUNT - nHidden - 1) * 0.5))
+       if (autocvar_hud_panel_scoreboard_accuracy_doublerows && weapon_cnt >= floor((REGISTRY_COUNT(Weapons) - nHidden - 1) * 0.5))
                rows = 2;
        int columnns = ceil(weapon_cnt / rows);
 
@@ -1199,7 +1659,7 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
        HUD_Panel_DrawBg();
        panel_bg_alpha = panel_bg_alpha_save;
 
-       vector end_pos = panel_pos + eY * (panel_size.y + hud_fontsize.y);
+       vector end_pos = panel_pos + eY * (panel_size.y + 0.5 * hud_fontsize.y);
        if(panel.current_panel_bg != "0")
                end_pos.y += panel_bg_border * 2;
 
@@ -1291,9 +1751,120 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
 
        panel_size.x += panel_bg_padding * 2; // restore initial width
 
-       if (scoreboard_acc_fade_alpha == 1)
-               return end_pos;
-       return initial_pos + (end_pos - initial_pos) * scoreboard_acc_fade_alpha;
+       return end_pos;
+}
+
+.bool uninteresting;
+STATIC_INIT(default_order_items_label)
+{
+       IL_EACH(default_order_items, true, {
+               if(!(it.instanceOfPowerup
+                       || it == ITEM_HealthMega || it == ITEM_HealthBig
+                       || it == ITEM_ArmorMega || it == ITEM_ArmorBig
+                       ))
+               {
+                       it.uninteresting = true;
+               }
+       });
+}
+
+vector Scoreboard_ItemStats_Draw(vector pos, vector rgb, vector bg_size)
+{
+       scoreboard_itemstats_fade_alpha = min(scoreboard_fade_alpha, scoreboard_itemstats_fade_alpha + frametime * 10);
+
+       int disowned_cnt = 0;
+       int uninteresting_cnt = 0;
+       IL_EACH(default_order_items, true, {
+               int q = g_inventory.inv_items[it.m_id];
+               //q = 1; // debug: display all items
+               if (autocvar_hud_panel_scoreboard_itemstats_filter && it.uninteresting)
+                       ++uninteresting_cnt;
+               else if (!q)
+                       ++disowned_cnt;
+       });
+       int items_cnt = REGISTRY_COUNT(Items) - uninteresting_cnt;
+       int n = items_cnt - disowned_cnt;
+       if (n <= 0) return pos;
+
+       int rows = (autocvar_hud_panel_scoreboard_itemstats_doublerows && n >= floor(REGISTRY_COUNT(Items) / 2)) ? 2 : 1;
+       int columnns = max(6, ceil(n / rows));
+
+       float height = 40;
+       float fontsize = height * 1/3;
+       float item_height = height * 2/3;
+
+       drawstring(pos + eX * panel_bg_padding, _("Item stats"), hud_fontsize, '1 1 1', panel_fg_alpha * scoreboard_itemstats_fade_alpha, DRAWFLAG_NORMAL);
+       pos.y += 1.25 * hud_fontsize.y;
+       if(panel.current_panel_bg != "0")
+               pos.y += panel_bg_border;
+
+       panel_pos = pos;
+       panel_size.y = height * rows;
+       panel_size.y += panel_bg_padding * 2;
+
+       float panel_bg_alpha_save = panel_bg_alpha;
+       panel_bg_alpha *= scoreboard_itemstats_fade_alpha;
+       HUD_Panel_DrawBg();
+       panel_bg_alpha = panel_bg_alpha_save;
+
+       vector end_pos = panel_pos + eY * (panel_size.y + 0.5 * hud_fontsize.y);
+       if(panel.current_panel_bg != "0")
+               end_pos.y += panel_bg_border * 2;
+
+       if(panel_bg_padding)
+       {
+               panel_pos += '1 1 0' * panel_bg_padding;
+               panel_size -= '2 2 0' * panel_bg_padding;
+       }
+
+       pos = panel_pos;
+       vector tmp = panel_size;
+
+       float item_width = tmp.x / columnns / rows;
+
+       if (sbt_bg_alpha)
+               drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, sbt_bg_alpha * scoreboard_itemstats_fade_alpha, DRAWFLAG_NORMAL);
+
+       if(sbt_highlight)
+       {
+               // column highlighting
+               for (int i = 0; i < columnns; ++i)
+                       if ((i % 2) == 0)
+                               drawfill(pos + '1 0 0' * item_width * rows * i, '0 1 0' * height * rows + '1 0 0' * item_width * rows, '0 0 0', sbt_highlight_alpha * scoreboard_itemstats_fade_alpha, DRAWFLAG_NORMAL);
+
+               // row highlighting
+               for (int i = 0; i < rows; ++i)
+                       drawfill(pos + '0 1 0' * item_height + '0 1 0' * height * i, '1 0 0' * panel_size.x + '0 1 0' * fontsize, rgb, sbt_highlight_alpha * scoreboard_itemstats_fade_alpha, DRAWFLAG_NORMAL);
+       }
+
+       if (rows == 2)
+               pos.x += item_width / 2;
+
+       float oldposx = pos.x;
+       vector tmpos = pos;
+
+       int column = 0;
+       IL_EACH(default_order_items, !(autocvar_hud_panel_scoreboard_itemstats_filter && it.uninteresting), {
+               int n = g_inventory.inv_items[it.m_id];
+               //n = 1 + floor(i * 3 + 4.8) % 7; // debug: display a value for each item
+               if (n <= 0) continue;
+               drawpic_aspect_skin(tmpos, it.m_icon, '1 0 0' * item_width + '0 1 0' * item_height, '1 1 1', panel_fg_alpha * scoreboard_itemstats_fade_alpha, DRAWFLAG_NORMAL);
+               string s = ftos(n);
+               float padding = (item_width - stringwidth(s, false, '1 0 0' * fontsize)) / 2; // center
+               drawstring(tmpos + '1 0 0' * padding + '0 1 0' * item_height, s, '1 1 0' * fontsize, '1 1 1', panel_fg_alpha * scoreboard_itemstats_fade_alpha, DRAWFLAG_NORMAL);
+               tmpos.x += item_width * rows;
+               pos.x += item_width * rows;
+               if (rows == 2 && column == columnns - 1) {
+                       tmpos.x = oldposx;
+                       tmpos.y += height;
+                       pos.y += height;
+               }
+               ++column;
+       });
+
+       panel_size.x += panel_bg_padding * 2; // restore initial width
+
+       return end_pos;
 }
 
 vector MapStats_DrawKeyValue(vector pos, string key, string value) {
@@ -1308,6 +1879,7 @@ vector MapStats_DrawKeyValue(vector pos, string key, string value) {
        return pos;
 }
 
+/*
 vector Scoreboard_MapStats_Draw(vector pos, vector rgb, vector bg_size) {
        float stat_secrets_found, stat_secrets_total;
        float stat_monsters_killed, stat_monsters_total;
@@ -1343,7 +1915,7 @@ vector Scoreboard_MapStats_Draw(vector pos, vector rgb, vector bg_size) {
        panel_size.y += panel_bg_padding * 2;
        HUD_Panel_DrawBg();
 
-       vector end_pos = panel_pos + eY * (panel_size.y + hud_fontsize.y);
+       vector end_pos = panel_pos + eY * (panel_size.y + 0.5 * hud_fontsize.y);
        if(panel.current_panel_bg != "0")
                end_pos.y += panel_bg_border * 2;
 
@@ -1376,9 +1948,9 @@ vector Scoreboard_MapStats_Draw(vector pos, vector rgb, vector bg_size) {
        panel_size.x += panel_bg_padding * 2; // restore initial width
        return end_pos;
 }
+*/
 
-
-vector Scoreboard_Rankings_Draw(vector pos, entity pl, vector rgb, vector bg_size)
+vector Scoreboard_Rankings_Draw(vector pos, string ranktitle, entity pl, vector rgb, vector bg_size)
 {
        int i;
        RANKINGS_RECEIVED_CNT = 0;
@@ -1392,7 +1964,7 @@ vector Scoreboard_Rankings_Draw(vector pos, entity pl, vector rgb, vector bg_siz
        vector hl_rgb = rgb + '0.5 0.5 0.5';
 
        pos.y += hud_fontsize.y;
-       drawstring(pos + eX * panel_bg_padding, ((ISGAMETYPE(CTF)) ? _("Capture time rankings") : _("Rankings")), hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawstring(pos + eX * panel_bg_padding, ranktitle, hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
        pos.y += 1.25 * hud_fontsize.y;
        if(panel.current_panel_bg != "0")
                pos.y += panel_bg_border;
@@ -1429,7 +2001,7 @@ vector Scoreboard_Rankings_Draw(vector pos, entity pl, vector rgb, vector bg_siz
 
        HUD_Panel_DrawBg();
 
-       vector end_pos = panel_pos + eY * (panel_size.y + hud_fontsize.y);
+       vector end_pos = panel_pos + eY * (panel_size.y + 0.5 * hud_fontsize.y);
        if(panel.current_panel_bg != "0")
                end_pos.y += panel_bg_border * 2;
 
@@ -1488,7 +2060,7 @@ float scoreboard_time;
 bool have_weapon_stats;
 bool Scoreboard_AccuracyStats_WouldDraw(float ypos)
 {
-       if (ISGAMETYPE(CTS) || ISGAMETYPE(RACE) || ISGAMETYPE(NEXBALL))
+       if (MUTATOR_CALLHOOK(DrawScoreboardAccuracy))
                return false;
        if (!autocvar_hud_panel_scoreboard_accuracy || warmup_stage || ypos > 0.91 * vid_conheight)
                return false;
@@ -1517,6 +2089,42 @@ bool Scoreboard_AccuracyStats_WouldDraw(float ypos)
        return true;
 }
 
+bool have_item_stats;
+bool Scoreboard_ItemStats_WouldDraw(float ypos)
+{
+       if (MUTATOR_CALLHOOK(DrawScoreboardItemStats))
+               return false;
+       if (!autocvar_hud_panel_scoreboard_itemstats || !g_inventory || warmup_stage || ypos > 0.91 * vid_conheight)
+               return false;
+
+       if (time < scoreboard_time + autocvar_hud_panel_scoreboard_itemstats_showdelay
+               && ypos > autocvar_hud_panel_scoreboard_itemstats_showdelay_minpos * vid_conheight
+               && !intermission)
+       {
+               return false;
+       }
+
+       if (!have_item_stats)
+       {
+               IL_EACH(default_order_items, true, {
+                       if (!(autocvar_hud_panel_scoreboard_itemstats_filter && it.uninteresting))
+                       {
+                               int q = g_inventory.inv_items[it.m_id];
+                               //q = 1; // debug: display all items
+                               if (q)
+                               {
+                                       have_item_stats = true;
+                                       break;
+                               }
+                       }
+               });
+               if (!have_item_stats)
+                       return false;
+       }
+
+       return true;
+}
+
 void Scoreboard_Draw()
 {
        if(!autocvar__hud_configure)
@@ -1525,7 +2133,7 @@ void Scoreboard_Draw()
 
                // frametime checks allow to toggle the scoreboard even when the game is paused
                if(scoreboard_active) {
-                       if (scoreboard_fade_alpha < 1)
+                       if (scoreboard_fade_alpha == 0)
                                scoreboard_time = time;
                        if(hud_configure_menu_open == 1)
                                scoreboard_fade_alpha = 1;
@@ -1552,6 +2160,7 @@ void Scoreboard_Draw()
                if (!scoreboard_fade_alpha)
                {
                        scoreboard_acc_fade_alpha = 0;
+                       scoreboard_itemstats_fade_alpha = 0;
                        return;
                }
        }
@@ -1572,6 +2181,7 @@ void Scoreboard_Draw()
        sbt_highlight = autocvar_hud_panel_scoreboard_table_highlight;
        sbt_highlight_alpha = autocvar_hud_panel_scoreboard_table_highlight_alpha * panel_fg_alpha;
        sbt_highlight_alpha_self = autocvar_hud_panel_scoreboard_table_highlight_alpha_self * panel_fg_alpha;
+       sbt_highlight_alpha_eliminated = autocvar_hud_panel_scoreboard_table_highlight_alpha_eliminated * panel_fg_alpha;
        sbt_fg_alpha = autocvar_hud_panel_scoreboard_table_fg_alpha * panel_fg_alpha;
        sbt_fg_alpha_self = autocvar_hud_panel_scoreboard_table_fg_alpha_self * panel_fg_alpha;
 
@@ -1586,6 +2196,7 @@ void Scoreboard_Draw()
 
        Scoreboard_UpdatePlayerTeams();
 
+       float initial_pos_y = panel_pos.y;
        vector pos = panel_pos;
        entity pl, tm;
        string str;
@@ -1597,12 +2208,32 @@ void Scoreboard_Draw()
        sb_gameinfo_type_fontsize = hud_fontsize * 2.5;
        sb_gameinfo_detail_fontsize = hud_fontsize * 1.3;
 
+       // z411 server name
+       //drawcolorcodedstring(pos, "bienvenidoainternet.org", sb_gameinfo_type_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+       //drawpic_aspect(pos + '1 0 0' * (panel_size.x - 150), "gfx/bai_logo", vec2(150, sb_gameinfo_type_fontsize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       //pos.y += sb_gameinfo_type_fontsize.y;
+       
        // Game Info: Game Type
        str = MapInfo_Type_ToText(gametype);
+       
        draw_beginBoldFont();
-       drawcolorcodedstring(pos + '0.5 0 0' * (panel_size.x - stringwidth(str, true, sb_gameinfo_type_fontsize)), str, sb_gameinfo_type_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+       //drawcolorcodedstring(pos + '0.5 0 0' * (panel_size.x - stringwidth(str, true, sb_gameinfo_type_fontsize)), str, sb_gameinfo_type_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawcolorcodedstring(pos, str, sb_gameinfo_type_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
        draw_endBoldFont();
+       
+       vector tmp_old_sz = draw_getimagesize("gfx/bai_logo");
+       float tmp_aspect = tmp_old_sz.x/tmp_old_sz.y;
+       vector tmp_new_sz = vec2(sb_gameinfo_type_fontsize.y * tmp_aspect, sb_gameinfo_type_fontsize.y);
 
+       drawpic(pos + '1 0 0' * (panel_size.x - tmp_new_sz.x), "gfx/bai_logo", tmp_new_sz, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       pos.y += sb_gameinfo_type_fontsize.y;
+       
+       // z411 servername
+       drawcolorcodedstring(pos + '0.5 0 0' * (panel_size.x - stringwidth_colors(hostname_full, sb_gameinfo_detail_fontsize)), hostname_full, sb_gameinfo_detail_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       pos.y += sb_gameinfo_detail_fontsize.y;
+       
        // Game Info: Game Detail
        float tl = STAT(TIMELIMIT);
        float fl = STAT(FRAGLIMIT);
@@ -1611,7 +2242,7 @@ void Scoreboard_Draw()
        str = "";
        if(tl > 0)
                str = strcat(str, sprintf(_("^3%1.0f minutes"), tl));
-       if(!ISGAMETYPE(LMS))
+       if(!gametype.m_hidelimits)
        {
                if(fl > 0)
                {
@@ -1660,7 +2291,6 @@ void Scoreboard_Draw()
                }
        }
 
-       pos.y += sb_gameinfo_type_fontsize.y;
        drawcolorcodedstring(pos + '1 0 0' * (panel_size.x - stringwidth(str, true, sb_gameinfo_detail_fontsize)), str, sb_gameinfo_detail_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL); // align right
        // map name
        str = sprintf(_("^7Map: ^2%s"), shortmapname);
@@ -1685,7 +2315,7 @@ void Scoreboard_Draw()
                if (autocvar_hud_panel_scoreboard_team_size_position != 1) // team size not on left
                {
                        // put team score to the left of scoreboard (and team size to the right)
-                       team_score_baseoffset = eY * hud_fontsize.y - eX * hud_fontsize.x * 0.5;
+                       team_score_baseoffset = eY * hud_fontsize.y - eX * hud_fontsize.x * 1.5;
                        team_size_baseoffset = eY * hud_fontsize.y + eX * hud_fontsize.x * 0.5;
                        if(panel.current_panel_bg != "0")
                        {
@@ -1696,7 +2326,7 @@ void Scoreboard_Draw()
                else
                {
                        // put team score to the right of scoreboard (and team size to the left)
-                       team_score_baseoffset = eY * hud_fontsize.y + eX * hud_fontsize.x * 0.5;
+                       team_score_baseoffset = eY * hud_fontsize.y + eX * hud_fontsize.x * 1.5;
                        team_size_baseoffset = eY * hud_fontsize.y - eX * hud_fontsize.x * 0.5;
                        if(panel.current_panel_bg != "0")
                        {
@@ -1721,20 +2351,20 @@ void Scoreboard_Draw()
                        if(!tm.team)
                                continue;
 
-                       draw_beginBoldFont();
                        vector rgb = Team_ColorRGB(tm.team);
+                       /*draw_beginBoldFont();
                        str = ftos(tm.(teamscores(ts_primary)));
                        if (autocvar_hud_panel_scoreboard_team_size_position != 1) // team size not on left
                        {
                                // team score on the left (default)
-                               str_pos = pos + team_score_baseoffset - eX * stringwidth(str, false, hud_fontsize * 1.5);
+                               str_pos = pos + team_score_baseoffset - eX * stringwidth(str, false, hud_fontsize * 3);
                        }
                        else
                        {
                                // team score on the right
-                               str_pos = pos + team_score_baseoffset + eX * (panel_size.x + hud_fontsize.x * 1.5);
+                               str_pos = pos + team_score_baseoffset + eX * (panel_size.x + hud_fontsize.x * 3);
                        }
-                       drawstring(str_pos, str, hud_fontsize * 1.5, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+                       drawstring(str_pos, str, hud_fontsize * 3, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
 
                        // team size (if set to show on the side)
                        if (autocvar_hud_panel_scoreboard_team_size_position != 0) // team size not off
@@ -1777,6 +2407,31 @@ void Scoreboard_Draw()
                                drawstring(str_pos, str, hud_fontsize, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
                        }
                        draw_endBoldFont();
+                       */
+                       
+                       // z411 My team header
+                       // Score: highlight
+                       drawfill(pos, team_score_size, rgb * 0.5, sbt_highlight_alpha, DRAWFLAG_NORMAL);
+                       
+                       // Score: text
+                       str = ftos(tm.(teamscores(ts_primary)));
+                       str_pos = pos;
+                       str_pos.x += (team_score_size.x / 2) - (stringwidth(str, true, team_score_fontsize) / 2);
+                       str_pos.y += (team_score_size.y / 2) - (team_score_fontsize.y / 2);
+                       
+                       draw_beginBoldFont();
+                       drawstring(str_pos, str, team_score_fontsize, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+                       draw_endBoldFont();
+                       
+                       // Team name
+                       str = Team_CustomName(tm.team);
+                       str_pos = pos;
+                       str_pos.x += team_score_size.x + team_name_fontsize.x * 0.5;
+                       str_pos.y += (team_score_size.y / 2) - (team_name_fontsize.y / 2);
+                       drawcolorcodedstring(str_pos, str, team_name_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+                       
+                       pos.y += team_score_size.y + (hud_fontsize.y * 0.5);
+                       
                        if(autocvar_hud_panel_scoreboard_bg_teams_color_team > 0)
                                panel_bg_color = rgb * autocvar_hud_panel_scoreboard_bg_teams_color_team;
                        else if(panel_bg_color_team > 0)
@@ -1787,6 +2442,15 @@ void Scoreboard_Draw()
                }
                panel_bg_color = panel_bg_color_save;
        }
+       else if(gametype == MAPINFO_TYPE_DUEL)
+       {
+               for(tm = teams.sort_next; tm; tm = tm.sort_next)
+                       if(tm.team != NUM_SPECTATOR)
+                               break;
+               
+               // z411 make DUEL TABLE
+               pos = Scoreboard_MakeDuelTable(pos, tm, panel_bg_color, bg_size);
+       }
        else
        {
                for(tm = teams.sort_next; tm; tm = tm.sort_next)
@@ -1797,10 +2461,15 @@ void Scoreboard_Draw()
                pos = Scoreboard_MakeTable(pos, tm, panel_bg_color, bg_size);
        }
 
+       pos = Scoreboard_MedalStats_Draw(pos);
+       
        if (Scoreboard_AccuracyStats_WouldDraw(pos.y))
                pos = Scoreboard_AccuracyStats_Draw(pos, panel_bg_color, bg_size);
+       if (Scoreboard_ItemStats_WouldDraw(pos.y))
+               pos = Scoreboard_ItemStats_Draw(pos, panel_bg_color, bg_size);
 
-       if(ISGAMETYPE(CTS) || ISGAMETYPE(RACE) || (autocvar_hud_panel_scoreboard_ctf_leaderboard && ISGAMETYPE(CTF) && STAT(CTF_SHOWLEADERBOARD))) {
+       if(MUTATOR_CALLHOOK(ShowRankings)) {
+               string ranktitle = M_ARGV(0, string);
                if(race_speedaward) {
                        drawcolorcodedstring(pos, sprintf(_("Speed award: %d%s ^7(%s^7)"), race_speedaward, race_speedaward_unit, ColorTranslateRGB(race_speedaward_holder)), hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
                        pos.y += 1.25 * hud_fontsize.y;
@@ -1809,10 +2478,10 @@ void Scoreboard_Draw()
                        drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d%s ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_unit, ColorTranslateRGB(race_speedaward_alltimebest_holder)), hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
                        pos.y += 1.25 * hud_fontsize.y;
                }
-               pos = Scoreboard_Rankings_Draw(pos, playerslots[player_localnum], panel_bg_color, bg_size);
+               pos = Scoreboard_Rankings_Draw(pos, ranktitle, playerslots[player_localnum], panel_bg_color, bg_size);
        }
 
-       pos = Scoreboard_MapStats_Draw(pos, panel_bg_color, bg_size);
+       //pos = Scoreboard_MapStats_Draw(pos, panel_bg_color, bg_size);
 
        // List spectators
        for(pl = players.sort_next; pl; pl = pl.sort_next)
@@ -1874,5 +2543,14 @@ void Scoreboard_Draw()
                drawcolorcodedstring(pos + '0.5 0 0' * (panel_size.x - stringwidth(str, true, hud_fontsize)), str, hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
        }
 
-       scoreboard_bottom = pos.y + 2 * hud_fontsize.y;
+       pos.y += 2 * hud_fontsize.y;
+       if (scoreboard_fade_alpha < 1)
+               scoreboard_bottom = initial_pos_y + (pos.y - initial_pos_y) * scoreboard_fade_alpha;
+       else if (pos.y != scoreboard_bottom)
+       {
+               if (pos.y > scoreboard_bottom)
+                       scoreboard_bottom = min(pos.y, scoreboard_bottom + frametime * 10 * (pos.y - initial_pos_y));
+               else
+                       scoreboard_bottom = max(pos.y, scoreboard_bottom - frametime * 10 * (pos.y - initial_pos_y));
+       }
 }