1 float scoreboard_alpha_bg;
2 float scoreboard_alpha_fg;
3 float scoreboard_highlight;
4 float scoreboard_highlight_alpha;
5 float scoreboard_highlight_alpha_self;
6 float scoreboard_alpha_name;
7 float scoreboard_alpha_name_self;
9 void drawstringright(vector, string, vector, vector, float, float);
10 void drawstringcenter(vector, string, vector, vector, float, float);
12 float SCOREBOARD_OFFSET = 50;
14 // wrapper to put all possible scores titles through gettext
15 string TranslateScoresLabel(string l)
19 case "bckills": return CTX(_("SCO^bckills"));
20 case "bctime": return CTX(_("SCO^bctime"));
21 case "caps": return CTX(_("SCO^caps"));
22 case "captime": return CTX(_("SCO^captime"));
23 case "deaths": return CTX(_("SCO^deaths"));
24 case "destroyed": return CTX(_("SCO^destroyed"));
25 case "drops": return CTX(_("SCO^drops"));
26 case "faults": return CTX(_("SCO^faults"));
27 case "fckills": return CTX(_("SCO^fckills"));
28 case "goals": return CTX(_("SCO^goals"));
29 case "kckills": return CTX(_("SCO^kckills"));
30 case "kdratio": return CTX(_("SCO^kdratio"));
31 case "k/d": return CTX(_("SCO^k/d"));
32 case "kd": return CTX(_("SCO^kd"));
33 case "kdr": return CTX(_("SCO^kdr"));
34 case "kills": return CTX(_("SCO^kills"));
35 case "laps": return CTX(_("SCO^laps"));
36 case "lives": return CTX(_("SCO^lives"));
37 case "losses": return CTX(_("SCO^losses"));
38 case "name": return CTX(_("SCO^name"));
39 case "nick": return CTX(_("SCO^nick"));
40 case "objectives": return CTX(_("SCO^objectives"));
41 case "pickups": return CTX(_("SCO^pickups"));
42 case "ping": return CTX(_("SCO^ping"));
43 case "pl": return CTX(_("SCO^pl"));
44 case "pushes": return CTX(_("SCO^pushes"));
45 case "rank": return CTX(_("SCO^rank"));
46 case "returns": return CTX(_("SCO^returns"));
47 case "revivals": return CTX(_("SCO^revivals"));
48 case "score": return CTX(_("SCO^score"));
49 case "suicides": return CTX(_("SCO^suicides"));
50 case "takes": return CTX(_("SCO^takes"));
51 case "ticks": return CTX(_("SCO^ticks"));
57 void HUD_FinaleOverlay()
60 pos_x = (vid_conwidth - 1)/2;
64 //drawpic(pos, "gfx/finale", '0 0 0', '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
66 //drawstring(pos, "END", hud_fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
70 void Cmd_HUD_SetFields(float argc);
75 ps_primary = ps_secondary = ts_primary = ts_secondary = -1;
76 for(i = 0; i < MAX_SCORE; ++i)
78 f = (scores_flags[i] & SFL_SORT_PRIO_MASK);
79 if(f == SFL_SORT_PRIO_PRIMARY)
81 if(f == SFL_SORT_PRIO_SECONDARY)
84 if(ps_secondary == -1)
85 ps_secondary = ps_primary;
87 for(i = 0; i < MAX_TEAMSCORE; ++i)
89 f = (teamscores_flags[i] & SFL_SORT_PRIO_MASK);
90 if(f == SFL_SORT_PRIO_PRIMARY)
92 if(f == SFL_SORT_PRIO_SECONDARY)
95 if(ts_secondary == -1)
96 ts_secondary = ts_primary;
101 void HUD_UpdatePlayerPos(entity pl);
102 float SetTeam(entity pl, float Team);
104 void HUD_UpdatePlayerTeams()
111 for(pl = players.sort_next; pl; pl = pl.sort_next)
114 Team = GetPlayerColor(pl.sv_entnum);
115 if(SetTeam(pl, Team))
118 HUD_UpdatePlayerPos(pl);
122 pl = players.sort_next;
127 print(strcat("PNUM: ", ftos(num), "\n"));
132 float HUD_CompareScore(float vl, float vr, float f)
134 if(f & SFL_ZERO_IS_WORST)
136 if(vl == 0 && vr != 0)
138 if(vl != 0 && vr == 0)
142 return IS_INCREASING(f);
144 return IS_DECREASING(f);
148 float HUD_ComparePlayerScores(entity left, entity right)
151 vl = GetPlayerColor(left.sv_entnum);
152 vr = GetPlayerColor(right.sv_entnum);
155 vl = COLOR_SPECTATOR;
157 vr = COLOR_SPECTATOR;
164 if(vl == COLOR_SPECTATOR)
166 // FIRST the one with scores (spectators), THEN the ones without (downloaders)
168 if(!left.gotscores && right.gotscores)
173 r = HUD_CompareScore(left.scores[ps_primary], right.scores[ps_primary], scores_flags[ps_primary]);
177 r = HUD_CompareScore(left.scores[ps_secondary], right.scores[ps_secondary], scores_flags[ps_secondary]);
181 for(i = 0; i < MAX_SCORE; ++i)
183 r = HUD_CompareScore(left.scores[i], right.scores[i], scores_flags[i]);
188 if (left.sv_entnum < right.sv_entnum)
194 void HUD_UpdatePlayerPos(entity player)
196 for(other = player.sort_next; other && HUD_ComparePlayerScores(player, other); other = player.sort_next)
198 SORT_SWAP(player, other);
200 for(other = player.sort_prev; other != players && HUD_ComparePlayerScores(other, player); other = player.sort_prev)
202 SORT_SWAP(other, player);
206 float HUD_CompareTeamScores(entity left, entity right)
210 if(left.team == COLOR_SPECTATOR)
212 if(right.team == COLOR_SPECTATOR)
215 r = HUD_CompareScore(left.teamscores[ts_primary], right.teamscores[ts_primary], teamscores_flags[ts_primary]);
219 r = HUD_CompareScore(left.teamscores[ts_secondary], right.teamscores[ts_secondary], teamscores_flags[ts_secondary]);
223 for(i = 0; i < MAX_SCORE; ++i)
225 r = HUD_CompareScore(left.teamscores[i], right.teamscores[i], teamscores_flags[i]);
230 if (left.team < right.team)
236 void HUD_UpdateTeamPos(entity Team)
238 for(other = Team.sort_next; other && HUD_CompareTeamScores(Team, other); other = Team.sort_next)
240 SORT_SWAP(Team, other);
242 for(other = Team.sort_prev; other != teams && HUD_CompareTeamScores(other, Team); other = Team.sort_prev)
244 SORT_SWAP(other, Team);
250 print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
251 print(_("^3|---------------------------------------------------------------|\n"));
252 print(_("Usage:\n"));
253 print(_("^2scoreboard_columns_set default\n"));
254 print(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
255 print(_("The following field names are recognized (case insensitive):\n"));
256 print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
258 print(_("^3name^7 or ^3nick^7 Name of a player\n"));
259 print(_("^3ping^7 Ping time\n"));
260 print(_("^3pl^7 Packet loss\n"));
261 print(_("^3kills^7 Number of kills\n"));
262 print(_("^3deaths^7 Number of deaths\n"));
263 print(_("^3suicides^7 Number of suicides\n"));
264 print(_("^3frags^7 kills - suicides\n"));
265 print(_("^3kd^7 The kill-death ratio\n"));
266 print(_("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n"));
267 print(_("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
268 print(_("^3captime^7 Time of fastest cap (CTF)\n"));
269 print(_("^3fckills^7 Number of flag carrier kills\n"));
270 print(_("^3returns^7 Number of flag returns\n"));
271 print(_("^3drops^7 Number of flag drops\n"));
272 print(_("^3lives^7 Number of lives (LMS)\n"));
273 print(_("^3rank^7 Player rank\n"));
274 print(_("^3pushes^7 Number of players pushed into void\n"));
275 print(_("^3destroyed^7 Number of keys destroyed by pushing them into void\n"));
276 print(_("^3kckills^7 Number of keys carrier kills\n"));
277 print(_("^3losses^7 Number of times a key was lost\n"));
278 print(_("^3laps^7 Number of laps finished (race/cts)\n"));
279 print(_("^3time^7 Total time raced (race/cts)\n"));
280 print(_("^3fastest^7 Time of fastest lap (race/cts)\n"));
281 print(_("^3ticks^7 Number of ticks (DOM)\n"));
282 print(_("^3takes^7 Number of domination points taken (DOM)\n"));
283 print(_("^3bckills^7 Number of ball carrier kills\n"));
284 print(_("^3bctime^7 Total amount of time holding the ball in Keepaway\n"));
285 print(_("^3score^7 Total score\n\n"));
287 print(_("Before a field you can put a + or - sign, then a comma separated list\n"
288 "of game types, then a slash, to make the field show up only in these\n"
289 "or in all but these game types. You can also specify 'all' as a\n"
290 "field to show all fields available for the current game mode.\n\n"));
292 print(_("The special game type names 'teams' and 'noteams' can be used to\n"
293 "include/exclude ALL teams/noteams game modes.\n\n"));
295 print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
296 print(_("will display name, ping and pl aligned to the left, and the fields\n"
297 "right of the vertical bar aligned to the right.\n"));
298 print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
299 "other gamemodes except DM.\n"));
302 string HUD_DefaultColumnLayout()
304 return strcat( // fteqcc sucks
306 "-teams,race,lms/kills +freezetag/kills -teams,lms/deaths +freezetag/deaths -teams,lms,race,ka/suicides +freezetag/suicides -race,dm,tdm,ka,freezetag/frags ", // tdm already has this in "score"
307 "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ",
308 "+lms/lives +lms/rank ",
309 "+kh/caps +kh/pushes +kh/destroyed ",
310 "?+race/laps ?+race/time ?+race/fastest ",
311 "+as/objectives +nexball/faults +nexball/goals +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ",
312 "-lms,race,nexball/score");
315 void Cmd_HUD_SetFields(float argc)
319 float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
322 // TODO: re enable with gametype dependant cvars?
323 if(argc < 3) // no arguments provided
324 argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
327 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
331 if(argv(2) == "default")
332 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
333 else if(argv(2) == "all")
336 s = "ping pl name |";
337 for(i = 0; i < MAX_SCORE; ++i)
340 if(i != ps_secondary)
341 if(scores_label[i] != "")
342 s = strcat(s, " ", scores_label[i]);
344 if(ps_secondary != ps_primary)
345 s = strcat(s, " ", scores_label[ps_secondary]);
346 s = strcat(s, " ", scores_label[ps_primary]);
347 argc = tokenizebyseparator(strcat("0 1 ", s), " ");
354 hud_fontsize = HUD_GetFontsize("hud_fontsize");
356 draw_beginBoldFont();
357 for(i = 1; i < argc - 1; ++i)
363 if(substring(str, 0, 1) == "?")
366 str = substring(str, 1, strlen(str) - 1);
369 slash = strstrofs(str, "/", 0);
372 pattern = substring(str, 0, slash);
373 str = substring(str, slash + 1, strlen(str) - (slash + 1));
375 if not(isGametypeInFilter(gametype, teamplay, FALSE, pattern))
379 strunzone(hud_title[hud_num_fields]);
380 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
381 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
382 str = strtolower(str);
385 hud_field[hud_num_fields] = SP_PING;
386 } else if(str == "pl") {
387 hud_field[hud_num_fields] = SP_PL;
388 } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
389 hud_field[hud_num_fields] = SP_KDRATIO;
390 } else if(str == "name" || str == "nick") {
391 hud_field[hud_num_fields] = SP_NAME;
393 } else if(str == "|") {
394 hud_field[hud_num_fields] = SP_SEPARATOR;
397 for(j = 0; j < MAX_SCORE; ++j)
398 if(str == strtolower(scores_label[j]))
399 goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
408 print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
412 hud_field[hud_num_fields] = j;
415 if(j == ps_secondary)
419 if(hud_num_fields >= MAX_HUD_FIELDS)
423 if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
425 if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
427 if(ps_primary == ps_secondary)
429 missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
431 if(hud_num_fields+missing < MAX_HUD_FIELDS)
435 strunzone(hud_title[hud_num_fields]);
436 for(i = hud_num_fields; i > 0; --i)
438 hud_title[i] = hud_title[i-1];
439 hud_size[i] = hud_size[i-1];
440 hud_field[i] = hud_field[i-1];
442 hud_title[0] = strzone(TranslateScoresLabel("name"));
443 hud_field[0] = SP_NAME;
445 print(sprintf(_("fixed missing field '%s'\n"), "name"));
449 strunzone(hud_title[hud_num_fields]);
450 for(i = hud_num_fields; i > 1; --i)
452 hud_title[i] = hud_title[i-1];
453 hud_size[i] = hud_size[i-1];
454 hud_field[i] = hud_field[i-1];
456 hud_title[1] = strzone("|");
457 hud_field[1] = SP_SEPARATOR;
458 hud_size[1] = stringwidth("|", FALSE, hud_fontsize);
460 print(sprintf(_("fixed missing field '%s'\n"), "|"));
463 else if(!have_separator)
465 strunzone(hud_title[hud_num_fields]);
466 hud_title[hud_num_fields] = strzone("|");
467 hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize);
468 hud_field[hud_num_fields] = SP_SEPARATOR;
470 print(sprintf(_("fixed missing field '%s'\n"), "|"));
474 strunzone(hud_title[hud_num_fields]);
475 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
476 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
477 hud_field[hud_num_fields] = ps_secondary;
479 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_secondary]));
483 strunzone(hud_title[hud_num_fields]);
484 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
485 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
486 hud_field[hud_num_fields] = ps_primary;
488 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_primary]));
492 hud_field[hud_num_fields] = SP_END;
497 vector hud_field_rgb;
498 string hud_field_icon0;
499 string hud_field_icon1;
500 string hud_field_icon2;
501 vector hud_field_icon0_rgb;
502 vector hud_field_icon1_rgb;
503 vector hud_field_icon2_rgb;
504 float hud_field_icon0_alpha;
505 float hud_field_icon1_alpha;
506 float hud_field_icon2_alpha;
507 string HUD_GetField(entity pl, float field)
509 float tmp, num, denom, f;
511 hud_field_rgb = '1 1 1';
512 hud_field_icon0 = "";
513 hud_field_icon1 = "";
514 hud_field_icon2 = "";
515 hud_field_icon0_rgb = '1 1 1';
516 hud_field_icon1_rgb = '1 1 1';
517 hud_field_icon2_rgb = '1 1 1';
518 hud_field_icon0_alpha = 1;
519 hud_field_icon1_alpha = 1;
520 hud_field_icon2_alpha = 1;
525 return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
526 //str = getplayerkeyvalue(pl.sv_entnum, "ping");
530 tmp = max(0, min(220, f-80)) / 220;
531 hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
537 f = pl.ping_packetloss;
538 tmp = pl.ping_movementloss;
539 if(f == 0 && tmp == 0)
541 str = ftos(ceil(f * 100));
543 str = strcat(str, "~", ftos(ceil(tmp * 100)));
544 tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
545 hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
549 if(ready_waiting && pl.ready)
551 hud_field_icon0 = "gfx/scoreboard/player_ready";
555 f = stof(getplayerkeyvalue(pl.sv_entnum, "colors"));
557 hud_field_icon0 = "gfx/scoreboard/playercolor_base";
558 hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
559 hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
560 hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
561 hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
564 return GetPlayerName(pl.sv_entnum);
567 f = pl.(scores[SP_KILLS]);
568 f -= pl.(scores[SP_SUICIDES]);
572 num = pl.(scores[SP_KILLS]);
573 denom = pl.(scores[SP_DEATHS]);
576 hud_field_rgb = '0 1 0';
577 str = sprintf("%d", num);
578 } else if(num <= 0) {
579 hud_field_rgb = '1 0 0';
580 str = sprintf("%.1f", num/denom);
582 str = sprintf("%.1f", num/denom);
586 tmp = pl.(scores[field]);
587 f = scores_flags[field];
588 if(field == ps_primary)
589 hud_field_rgb = '1 1 0';
590 else if(field == ps_secondary)
591 hud_field_rgb = '0 1 1';
593 hud_field_rgb = '1 1 1';
594 return ScoreString(f, tmp);
599 float xmin, xmax, ymin, ymax, sbwidth;
600 float hud_fixscoreboardcolumnwidth_len;
601 float hud_fixscoreboardcolumnwidth_iconlen;
602 float hud_fixscoreboardcolumnwidth_marginlen;
604 string HUD_FixScoreboardColumnWidth(float i, string str)
608 field = hud_field[i];
610 hud_fixscoreboardcolumnwidth_iconlen = 0;
612 if(hud_field_icon0 != "")
614 sz = draw_getimagesize(hud_field_icon0);
616 if(hud_fixscoreboardcolumnwidth_iconlen < f)
617 hud_fixscoreboardcolumnwidth_iconlen = f;
620 if(hud_field_icon1 != "")
622 sz = draw_getimagesize(hud_field_icon1);
624 if(hud_fixscoreboardcolumnwidth_iconlen < f)
625 hud_fixscoreboardcolumnwidth_iconlen = f;
628 if(hud_field_icon2 != "")
630 sz = draw_getimagesize(hud_field_icon2);
632 if(hud_fixscoreboardcolumnwidth_iconlen < f)
633 hud_fixscoreboardcolumnwidth_iconlen = f;
636 hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize_y / hud_fontsize_x; // fix icon aspect
638 if(hud_fixscoreboardcolumnwidth_iconlen != 0)
639 hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", FALSE, hud_fontsize);
641 hud_fixscoreboardcolumnwidth_marginlen = 0;
643 if(field == SP_NAME) // name gets all remaining space
646 namesize = sbwidth;// / hud_fontsize_x;
647 for(j = 0; j < hud_num_fields; ++j)
649 if (hud_field[i] != SP_SEPARATOR)
650 namesize -= hud_size[j] + hud_fontsize_x;
651 namesize += hud_fontsize_x;
652 hud_size[i] = namesize;
654 if (hud_fixscoreboardcolumnwidth_iconlen != 0)
655 namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
656 str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
657 hud_fixscoreboardcolumnwidth_len = stringwidth(str, TRUE, hud_fontsize);
660 hud_fixscoreboardcolumnwidth_len = stringwidth(str, FALSE, hud_fontsize);
662 f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
669 void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
672 rgb = GetTeamRGB(pl.team);
676 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
678 if((rgb == '1 1 1') && (!is_spec)) {
679 rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
680 rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
681 rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
685 tmp_y = hud_fontsize_y * 1.25;
688 // alternated rows highlighting
690 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
691 else if((scoreboard_highlight) && (!mod(pl_number,2)))
692 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
696 for(i = 0; i < hud_num_fields; ++i)
698 field = hud_field[i];
699 if(field == SP_SEPARATOR)
702 if(is_spec && field != SP_NAME && field != SP_PING) {
703 pos_x += hud_size[i] + hud_fontsize_x;
706 str = HUD_GetField(pl, field);
707 str = HUD_FixScoreboardColumnWidth(i, str);
709 pos_x += hud_size[i] + hud_fontsize_x;
711 if(field == SP_NAME) {
712 tmp_x = hud_size[i] - hud_fontsize_x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize_x;
714 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
716 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
718 tmp_x = hud_fixscoreboardcolumnwidth_len + hud_fontsize_x;
720 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
722 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
725 tmp_x = hud_size[i] + hud_fontsize_x;
726 if(hud_field_icon0 != "")
728 drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
730 drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
731 if(hud_field_icon1 != "")
733 drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
735 drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
736 if(hud_field_icon2 != "")
738 drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
740 drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
743 if(hud_field[i] == SP_SEPARATOR)
746 for(i = hud_num_fields-1; i > 0; --i)
748 field = hud_field[i];
749 if(field == SP_SEPARATOR)
752 if(is_spec && field != SP_NAME && field != SP_PING) {
753 pos_x -= hud_size[i] + hud_fontsize_x;
757 str = HUD_GetField(pl, field);
758 str = HUD_FixScoreboardColumnWidth(i, str);
760 if(field == SP_NAME) {
761 tmp_x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
763 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
765 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
767 tmp_x = hud_fixscoreboardcolumnwidth_len;
769 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
771 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
775 if(hud_field_icon0 != "")
777 drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
779 drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
780 if(hud_field_icon1 != "")
782 drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
784 drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
785 if(hud_field_icon2 != "")
787 drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
789 drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
790 pos_x -= hud_size[i] + hud_fontsize_x;
796 * HUD_Scoreboard_MakeTable
798 * Makes a table for a team (for all playing players in DM) and fills it
801 vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
803 float body_table_height, i;
804 vector tmp = '0 0 0', column_dim = '0 0 0';
807 body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
809 pos_y += autocvar_scoreboard_border_thickness;
813 tmp_y = 1.25 * hud_fontsize_y;
817 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
819 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
822 tmp_y += autocvar_scoreboard_border_thickness;
823 tmp_y += body_table_height;
824 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
826 // separator header/table
827 pos_y += 1.25 * hud_fontsize_y;
828 tmp_y = autocvar_scoreboard_border_thickness;
829 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
831 pos_y += autocvar_scoreboard_border_thickness;
834 tmp_y = body_table_height;
836 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
838 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
840 // anyway, apply some color
841 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
843 // go back to the top to make alternated columns highlighting and to print the strings
844 pos_y -= 1.25 * hud_fontsize_y;
845 pos_y -= autocvar_scoreboard_border_thickness;
849 if (scoreboard_highlight)
851 column_dim_y = 1.25 * hud_fontsize_y; // header
852 column_dim_y += autocvar_scoreboard_border_thickness;
853 column_dim_y += body_table_height;
856 // print the strings of the columns headers and draw the columns
857 draw_beginBoldFont();
858 for(i = 0; i < hud_num_fields; ++i)
860 if(hud_field[i] == SP_SEPARATOR)
862 column_dim_x = hud_size[i] + hud_fontsize_x;
863 if (scoreboard_highlight)
866 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
868 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
869 pos_x += column_dim_x;
871 if(hud_field[i] == SP_SEPARATOR)
875 for(i = hud_num_fields-1; i > 0; --i)
877 if(hud_field[i] == SP_SEPARATOR)
880 pos_x -= hud_size[i];
882 if (scoreboard_highlight)
886 if (i == hud_num_fields-1)
887 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
889 column_dim_x = hud_size[i] + hud_fontsize_x;
890 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
894 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
895 tmp_x = (hud_size[i] - tmp_x);
896 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
897 pos_x -= hud_fontsize_x;
903 pos_y += 1.25 * hud_fontsize_y; // skip the header
904 pos_y += autocvar_scoreboard_border_thickness;
906 // fill the table and draw the rows
909 for(pl = players.sort_next; pl; pl = pl.sort_next)
911 if(pl.team != tm.team)
913 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
914 pos_y += 1.25 * hud_fontsize_y;
918 for(pl = players.sort_next; pl; pl = pl.sort_next)
920 if(pl.team == COLOR_SPECTATOR)
922 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
923 pos_y += 1.25 * hud_fontsize_y;
928 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
929 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
934 float HUD_WouldDrawScoreboard() {
935 if (autocvar__hud_configure)
937 else if (scoreboard_showscores)
939 else if (intermission == 1)
941 else if (intermission == 2)
943 else if (spectatee_status != -1 && getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS)
945 else if (scoreboard_showscores_force)
951 float average_accuracy;
952 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
955 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
957 if(autocvar_scoreboard_accuracy_doublerows)
962 float fontsize = height * 1/3;
963 float weapon_height = height * 2/3;
964 float weapon_width = sbwidth / weapon_cnt;
966 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
967 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
968 vector tmp = '0 0 0';
970 tmp_y = height * rows;
973 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
975 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
976 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
978 // column highlighting
979 for(i = 0; i < weapon_cnt/rows; ++i)
982 drawfill(pos + '1 0 0' * weapon_width * rows * i, '0 1 0' * height * rows + '1 0 0' * weapon_width * rows, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
986 for(i = 0; i < rows; ++i)
988 drawfill(pos + '0 1 0' * weapon_height + '0 1 0' * height * i, '1 0 0' * sbwidth + '0 1 0' * fontsize, '1 1 1', scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
991 average_accuracy = 0;
992 float weapons_with_stats;
993 weapons_with_stats = 0;
995 pos_x += weapon_width / 2;
997 if(switchweapon == WEP_MINSTANEX)
998 g_minstagib = 1; // TODO: real detection for minstagib?
1002 Accuracy_LoadColors();
1004 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
1006 self = get_weaponinfo(i);
1009 if ((i == WEP_NEX && g_minstagib) || i == WEP_PORTO || (i == WEP_MINSTANEX && !g_minstagib) || i == WEP_TUBA) // skip port-o-launch, nex || minstanex and tuba
1011 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1014 if(weapon_stats >= 0)
1015 weapon_alpha = scoreboard_alpha_fg;
1017 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1020 drawpic_aspect_skin(pos, strcat("weapon", self.netname), '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
1022 if(weapon_stats >= 0) {
1023 weapons_with_stats += 1;
1024 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1027 s = sprintf(_("%d%%"), weapon_stats*100);
1030 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1032 rgb = Accuracy_GetColor(weapon_stats);
1034 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1036 pos_x += weapon_width * rows;
1037 if(rows == 2 && i == 6) {
1043 if(weapons_with_stats)
1044 average_accuracy = floor(average_accuracy / weapons_with_stats);
1047 pos_x -= weapon_width / 2;
1051 pos_y += 1.25 * hud_fontsize_y;
1055 vector HUD_DrawKeyValue(vector pos, string key, string value) {
1057 pos_x += hud_fontsize_x * 0.25;
1058 drawstring(pos, key, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1059 pos_x = xmax - stringwidth(value, FALSE, hud_fontsize) - hud_fontsize_x * 0.25;
1060 drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1062 pos_y+= hud_fontsize_y;
1067 vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
1068 float stat_secrets_found, stat_secrets_total;
1072 // get secrets stats
1073 stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
1074 stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
1076 // get number of rows
1077 rows = (stat_secrets_total ? 1 : 0);
1079 // if no rows, return
1083 // draw table header
1084 drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1085 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
1088 vector tmp = '0 0 0';
1090 tmp_y = hud_fontsize_y * rows;
1093 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1095 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1096 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1099 val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
1100 pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
1103 pos_y += 1.25 * hud_fontsize_y;
1108 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1111 RANKINGS_RECEIVED_CNT = 0;
1112 for (i=RANKINGS_CNT-1; i>=0; --i)
1114 ++RANKINGS_RECEIVED_CNT;
1116 if (RANKINGS_RECEIVED_CNT == 0)
1120 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
1122 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1123 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1124 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1126 pos_y += hud_fontsize_y;
1127 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1128 pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness;
1129 vector tmp = '0 0 0';
1131 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1134 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1136 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1137 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1140 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1147 n = grecordholder[i];
1148 p = race_PlaceName(i+1);
1149 if(grecordholder[i] == GetPlayerName(player_localnum))
1150 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1151 else if(!mod(i, 2) && scoreboard_highlight)
1152 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1153 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1154 drawstring(pos + '3 0 0' * hud_fontsize_y, TIME_ENCODED_TOSTRING(t), '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1155 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1156 pos_y += 1.25 * hud_fontsize_y;
1158 pos_y += autocvar_scoreboard_border_thickness;
1163 float hud_woulddrawscoreboard_prev;
1164 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1165 void HUD_DrawScoreboard()
1167 float hud_woulddrawscoreboard;
1168 hud_woulddrawscoreboard = scoreboard_active;
1169 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1170 hud_woulddrawscoreboard_change = time;
1171 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1174 if(hud_woulddrawscoreboard) {
1175 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1176 if (scoreboard_fadeinspeed)
1177 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1179 scoreboard_fade_alpha = 1;
1182 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1183 if (scoreboard_fadeoutspeed)
1184 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1186 scoreboard_fade_alpha = 0;
1189 if not(scoreboard_fade_alpha)
1192 HUD_UpdatePlayerTeams();
1194 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1195 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1196 scoreboard_highlight = autocvar_scoreboard_highlight;
1197 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1198 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1199 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1200 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1202 vector rgb, pos, tmp;
1206 xmin = (autocvar_scoreboard_offset_left * vid_conwidth);
1207 ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth));
1209 xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth);
1210 ymax = (vid_conheight - ymin);
1212 sbwidth = xmax - xmin;
1214 // Initializes position
1220 vector sb_heading_fontsize;
1221 sb_heading_fontsize = hud_fontsize * 2;
1222 draw_beginBoldFont();
1223 drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1226 pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25;
1228 // Draw the scoreboard
1229 vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1233 vector team_score_baseoffset;
1234 team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25);
1235 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1237 if(tm.team == COLOR_SPECTATOR)
1240 draw_beginBoldFont();
1241 rgb = GetTeamRGB(tm.team);
1242 str = ftos(tm.(teamscores[ts_primary]));
1243 drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1245 if(ts_primary != ts_secondary)
1247 str = ftos(tm.(teamscores[ts_secondary]));
1248 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);
1252 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1258 rgb_x = autocvar_scoreboard_color_bg_r;
1259 rgb_y = autocvar_scoreboard_color_bg_g;
1260 rgb_z = autocvar_scoreboard_color_bg_b;
1267 rgb_x = autocvar_scoreboard_color_bg_r;
1268 rgb_y = autocvar_scoreboard_color_bg_g;
1269 rgb_z = autocvar_scoreboard_color_bg_b;
1271 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1273 if(tm.team == COLOR_SPECTATOR)
1276 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1280 if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) {
1281 if(race_speedaward) {
1282 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1283 pos_y += 1.25 * hud_fontsize_y;
1285 if(race_speedaward_alltimebest) {
1286 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1287 pos_y += 1.25 * hud_fontsize_y;
1289 pos = HUD_DrawScoreboardRankings(pos, playerslots[player_localnum], rgb, bg_size);
1291 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1293 pos = HUD_DrawScoreboardAccuracyStats(pos, GetTeamRGB(myteam), bg_size);
1295 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1300 pos = HUD_DrawMapStats(pos, GetTeamRGB(myteam), bg_size);
1302 pos = HUD_DrawMapStats(pos, rgb, bg_size);
1308 for(pl = players.sort_next; pl; pl = pl.sort_next)
1310 if(pl.team != COLOR_SPECTATOR)
1312 pos_y += 1.25 * hud_fontsize_y;
1313 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
1319 draw_beginBoldFont();
1320 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1322 pos_y += 1.25 * hud_fontsize_y;
1325 // Print info string
1327 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1328 tl = getstatf(STAT_TIMELIMIT);
1329 fl = getstatf(STAT_FRAGLIMIT);
1330 ll = getstatf(STAT_LEADLIMIT);
1331 if(gametype == MAPINFO_TYPE_LMS)
1334 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1339 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1343 str = strcat(str, _(" or"));
1346 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1347 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1348 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1349 TranslateScoresLabel(teamscores_label[ts_primary])));
1353 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1354 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1355 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1356 TranslateScoresLabel(scores_label[ps_primary])));
1361 if(tl > 0 || fl > 0)
1362 str = strcat(str, _(" or"));
1365 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1366 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1367 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1368 TranslateScoresLabel(teamscores_label[ts_primary])));
1372 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1373 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1374 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1375 TranslateScoresLabel(scores_label[ps_primary])));
1380 pos_y += 1.2 * hud_fontsize_y;
1381 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1383 // print information about respawn status
1384 float respawn_time = getstatf(STAT_RESPAWN_TIME);
1387 if(respawn_time < 0)
1389 // a negative number means we are awaiting respawn, time value is still the same
1390 respawn_time *= -1; // remove mark now that we checked it
1391 respawn_time = max(time, respawn_time); // don't show a negative value while the server is respawning the player (lag)
1393 str = sprintf(_("^1Respawning in ^3%s^1 seconds..."), ftos_decimals(respawn_time - time, autocvar_scoreboard_respawntime_decimals));
1395 else if(time < respawn_time)
1396 str = sprintf(_("You are dead, wait ^3%s^7 seconds before respawning"), ftos_decimals(respawn_time - time, autocvar_scoreboard_respawntime_decimals));
1397 else if(time >= respawn_time)
1398 str = sprintf(_("You are dead, press ^2%s^7 to respawn"), getcommandkey("jump", "+jump"));
1400 pos_y += 1.2 * hud_fontsize_y;
1401 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1404 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;