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 "deaths": return CTX(_("SCO^deaths"));
23 case "destroyed": return CTX(_("SCO^destroyed"));
24 case "drops": return CTX(_("SCO^drops"));
25 case "faults": return CTX(_("SCO^faults"));
26 case "fckills": return CTX(_("SCO^fckills"));
27 case "goals": return CTX(_("SCO^goals"));
28 case "kckills": return CTX(_("SCO^kckills"));
29 case "kdratio": return CTX(_("SCO^kdratio"));
30 case "k/d": return CTX(_("SCO^k/d"));
31 case "kd": return CTX(_("SCO^kd"));
32 case "kdr": return CTX(_("SCO^kdr"));
33 case "kills": return CTX(_("SCO^kills"));
34 case "laps": return CTX(_("SCO^laps"));
35 case "lives": return CTX(_("SCO^lives"));
36 case "losses": return CTX(_("SCO^losses"));
37 case "name": return CTX(_("SCO^name"));
38 case "nick": return CTX(_("SCO^nick"));
39 case "objectives": return CTX(_("SCO^objectives"));
40 case "pickups": return CTX(_("SCO^pickups"));
41 case "ping": return CTX(_("SCO^ping"));
42 case "pl": return CTX(_("SCO^pl"));
43 case "pushes": return CTX(_("SCO^pushes"));
44 case "rank": return CTX(_("SCO^rank"));
45 case "returns": return CTX(_("SCO^returns"));
46 case "revivals": return CTX(_("SCO^revivals"));
47 case "score": return CTX(_("SCO^score"));
48 case "suicides": return CTX(_("SCO^suicides"));
49 case "takes": return CTX(_("SCO^takes"));
50 case "ticks": return CTX(_("SCO^ticks"));
56 void HUD_FinaleOverlay()
59 pos_x = (vid_conwidth - 1)/2;
63 //drawpic(pos, "gfx/finale", '0 0 0', '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
65 //drawstring(pos, "END", hud_fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
69 void Cmd_HUD_SetFields(float argc);
74 ps_primary = ps_secondary = ts_primary = ts_secondary = -1;
75 for(i = 0; i < MAX_SCORE; ++i)
77 f = (scores_flags[i] & SFL_SORT_PRIO_MASK);
78 if(f == SFL_SORT_PRIO_PRIMARY)
80 if(f == SFL_SORT_PRIO_SECONDARY)
83 if(ps_secondary == -1)
84 ps_secondary = ps_primary;
86 for(i = 0; i < MAX_TEAMSCORE; ++i)
88 f = (teamscores_flags[i] & SFL_SORT_PRIO_MASK);
89 if(f == SFL_SORT_PRIO_PRIMARY)
91 if(f == SFL_SORT_PRIO_SECONDARY)
94 if(ts_secondary == -1)
95 ts_secondary = ts_primary;
100 void HUD_UpdatePlayerPos(entity pl);
101 float SetTeam(entity pl, float Team);
103 void HUD_UpdatePlayerTeams()
110 for(pl = players.sort_next; pl; pl = pl.sort_next)
113 Team = GetPlayerColor(pl.sv_entnum);
114 if(SetTeam(pl, Team))
117 HUD_UpdatePlayerPos(pl);
121 pl = players.sort_next;
126 print(strcat("PNUM: ", ftos(num), "\n"));
131 float HUD_ComparePlayerScores(entity left, entity right)
134 vl = GetPlayerColor(left.sv_entnum);
135 vr = GetPlayerColor(right.sv_entnum);
138 vl = COLOR_SPECTATOR;
140 vr = COLOR_SPECTATOR;
147 if(vl == COLOR_SPECTATOR)
149 // FIRST the one with scores (spectators), THEN the ones without (downloaders)
151 if(!left.gotscores && right.gotscores)
156 vl = left.scores[ps_primary];
157 vr = right.scores[ps_primary];
158 if(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)
160 if(vl == 0 && vr != 0)
162 if(vl != 0 && vr == 0)
166 return IS_INCREASING(scores_flags[ps_primary]);
168 return IS_DECREASING(scores_flags[ps_primary]);
170 vl = left.scores[ps_secondary];
171 vr = right.scores[ps_secondary];
172 if(scores_flags[ps_secondary] & SFL_ZERO_IS_WORST)
174 if(vl == 0 && vr != 0)
176 if(vl != 0 && vr == 0)
180 return IS_INCREASING(scores_flags[ps_secondary]);
182 return IS_DECREASING(scores_flags[ps_secondary]);
187 void HUD_UpdatePlayerPos(entity player)
189 for(other = player.sort_next; other && HUD_ComparePlayerScores(player, other); other = player.sort_next)
191 SORT_SWAP(player, other);
193 for(other = player.sort_prev; other != players && HUD_ComparePlayerScores(other, player); other = player.sort_prev)
195 SORT_SWAP(other, player);
199 float HUD_CompareTeamScores(entity left, entity right)
203 if(left.team == COLOR_SPECTATOR)
205 if(right.team == COLOR_SPECTATOR)
208 vl = left.teamscores[ts_primary];
209 vr = right.teamscores[ts_primary];
211 return IS_INCREASING(teamscores_flags[ts_primary]);
213 return IS_DECREASING(teamscores_flags[ts_primary]);
215 vl = left.teamscores[ts_secondary];
216 vr = right.teamscores[ts_secondary];
218 return IS_INCREASING(teamscores_flags[ts_secondary]);
220 return IS_DECREASING(teamscores_flags[ts_secondary]);
225 void HUD_UpdateTeamPos(entity Team)
227 for(other = Team.sort_next; other && HUD_CompareTeamScores(Team, other); other = Team.sort_next)
229 SORT_SWAP(Team, other);
231 for(other = Team.sort_prev; other != teams && HUD_CompareTeamScores(other, Team); other = Team.sort_prev)
233 SORT_SWAP(other, Team);
239 print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
240 print(_("^3|---------------------------------------------------------------|\n"));
241 print(_("Usage:\n"));
242 print(_("^2scoreboard_columns_set default\n"));
243 print(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
244 print(_("The following field names are recognized (case insensitive):\n"));
245 print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
247 print(_("^3name^7 or ^3nick^7 Name of a player\n"));
248 print(_("^3ping^7 Ping time\n"));
249 print(_("^3pl^7 Packet loss\n"));
250 print(_("^3kills^7 Number of kills\n"));
251 print(_("^3deaths^7 Number of deaths\n"));
252 print(_("^3suicides^7 Number of suicides\n"));
253 print(_("^3frags^7 kills - suicides\n"));
254 print(_("^3kd^7 The kill-death ratio\n"));
255 print(_("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n"));
256 print(_("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
257 print(_("^3fckills^7 Number of flag carrier kills\n"));
258 print(_("^3returns^7 Number of flag returns\n"));
259 print(_("^3drops^7 Number of flag drops\n"));
260 print(_("^3lives^7 Number of lives (LMS)\n"));
261 print(_("^3rank^7 Player rank\n"));
262 print(_("^3pushes^7 Number of players pushed into void\n"));
263 print(_("^3destroyed^7 Number of keys destroyed by pushing them into void\n"));
264 print(_("^3kckills^7 Number of keys carrier kills\n"));
265 print(_("^3losses^7 Number of times a key was lost\n"));
266 print(_("^3laps^7 Number of laps finished (race/cts)\n"));
267 print(_("^3time^7 Total time raced (race/cts)\n"));
268 print(_("^3fastest^7 Time of fastest lap (race/cts)\n"));
269 print(_("^3ticks^7 Number of ticks (DOM)\n"));
270 print(_("^3takes^7 Number of domination points taken (DOM)\n"));
271 print(_("^3bckills^7 Number of ball carrier kills\n"));
272 print(_("^3bctime^7 Total amount of time holding the ball in Keepaway\n"));
273 print(_("^3score^7 Total score\n\n"));
275 print(_("Before a field you can put a + or - sign, then a comma separated list\n"
276 "of game types, then a slash, to make the field show up only in these\n"
277 "or in all but these game types. You can also specify 'all' as a\n"
278 "field to show all fields available for the current game mode.\n\n"));
280 print(_("The special game type names 'teams' and 'noteams' can be used to\n"
281 "include/exclude ALL teams/noteams game modes.\n\n"));
283 print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
284 print(_("will display name, ping and pl aligned to the left, and the fields\n"
285 "right of the vertical bar aligned to the right.\n"));
286 print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
287 "other gamemodes except DM.\n"));
290 string HUD_DefaultColumnLayout()
292 return strcat( // fteqcc sucks
294 "-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"
295 "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ",
296 "+lms/lives +lms/rank ",
297 "+kh/caps +kh/pushes +kh/destroyed ",
298 "?+race/laps ?+race/time ?+race/fastest ",
299 "+as/objectives +nexball/faults +nexball/goals +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ",
300 "-lms,race,nexball/score");
303 void Cmd_HUD_SetFields(float argc)
307 float have_name, have_primary, have_secondary, have_separator;
310 // TODO: re enable with gametype dependant cvars?
311 if(argc < 3) // no arguments provided
312 argc = tokenizebyseparator(strcat("x ", autocvar_scoreboard_columns), " ");
315 argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
319 if(argv(2) == "default")
320 argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
321 else if(argv(2) == "all")
324 s = "ping pl name |";
325 for(i = 0; i < MAX_SCORE; ++i)
328 if(i != ps_secondary)
329 if(scores_label[i] != "")
330 s = strcat(s, " ", scores_label[i]);
332 if(ps_secondary != ps_primary)
333 s = strcat(s, " ", scores_label[ps_secondary]);
334 s = strcat(s, " ", scores_label[ps_primary]);
335 argc = tokenizebyseparator(strcat("x ", s), " ");
342 hud_fontsize = HUD_GetFontsize("hud_fontsize");
344 draw_beginBoldFont();
345 for(i = 0; i < argc - 1; ++i)
351 if(substring(str, 0, 1) == "?")
354 str = substring(str, 1, strlen(str) - 1);
357 slash = strstrofs(str, "/", 0);
360 pattern = substring(str, 0, slash);
361 str = substring(str, slash + 1, strlen(str) - (slash + 1));
363 if not(isGametypeInFilter(gametype, teamplay, FALSE, pattern))
367 strunzone(hud_title[hud_num_fields]);
368 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
369 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
370 str = strtolower(str);
373 hud_field[hud_num_fields] = SP_PING;
374 } else if(str == "pl") {
375 hud_field[hud_num_fields] = SP_PL;
376 } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
377 hud_field[hud_num_fields] = SP_KDRATIO;
378 } else if(str == "name" || str == "nick") {
379 hud_field[hud_num_fields] = SP_NAME;
381 } else if(str == "|") {
382 hud_field[hud_num_fields] = SP_SEPARATOR;
385 for(j = 0; j < MAX_SCORE; ++j)
386 if(str == strtolower(scores_label[j]))
387 goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
396 print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
400 hud_field[hud_num_fields] = j;
403 if(j == ps_secondary)
407 if(hud_num_fields >= MAX_HUD_FIELDS)
411 if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
413 if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
415 if(ps_primary == ps_secondary)
417 missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
419 if(hud_num_fields+missing < MAX_HUD_FIELDS)
423 strunzone(hud_title[hud_num_fields]);
424 for(i = hud_num_fields; i > 0; --i)
426 hud_title[i] = hud_title[i-1];
427 hud_size[i] = hud_size[i-1];
428 hud_field[i] = hud_field[i-1];
430 hud_title[0] = strzone(TranslateScoresLabel("name"));
431 hud_field[0] = SP_NAME;
433 print(sprintf(_("fixed missing field '%s'\n"), "name"));
437 strunzone(hud_title[hud_num_fields]);
438 for(i = hud_num_fields; i > 1; --i)
440 hud_title[i] = hud_title[i-1];
441 hud_size[i] = hud_size[i-1];
442 hud_field[i] = hud_field[i-1];
444 hud_title[1] = strzone("|");
445 hud_field[1] = SP_SEPARATOR;
446 hud_size[1] = stringwidth("|", FALSE, hud_fontsize);
448 print(sprintf(_("fixed missing field '%s'\n"), "|"));
451 else if(!have_separator)
453 strunzone(hud_title[hud_num_fields]);
454 hud_title[hud_num_fields] = strzone("|");
455 hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize);
456 hud_field[hud_num_fields] = SP_SEPARATOR;
458 print(sprintf(_("fixed missing field '%s'\n"), "|"));
462 strunzone(hud_title[hud_num_fields]);
463 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
464 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
465 hud_field[hud_num_fields] = ps_secondary;
467 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_secondary]));
471 strunzone(hud_title[hud_num_fields]);
472 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
473 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
474 hud_field[hud_num_fields] = ps_primary;
476 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_primary]));
480 hud_field[hud_num_fields] = SP_END;
485 vector hud_field_rgb;
486 string hud_field_icon0;
487 string hud_field_icon1;
488 string hud_field_icon2;
489 vector hud_field_icon0_rgb;
490 vector hud_field_icon1_rgb;
491 vector hud_field_icon2_rgb;
492 float hud_field_icon0_alpha;
493 float hud_field_icon1_alpha;
494 float hud_field_icon2_alpha;
495 string HUD_GetField(entity pl, float field)
497 float tmp, num, denom, f;
499 hud_field_rgb = '1 1 1';
500 hud_field_icon0 = "";
501 hud_field_icon1 = "";
502 hud_field_icon2 = "";
503 hud_field_icon0_rgb = '1 1 1';
504 hud_field_icon1_rgb = '1 1 1';
505 hud_field_icon2_rgb = '1 1 1';
506 hud_field_icon0_alpha = 1;
507 hud_field_icon1_alpha = 1;
508 hud_field_icon2_alpha = 1;
513 return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
514 //str = getplayerkeyvalue(pl.sv_entnum, "ping");
518 tmp = max(0, min(220, f-80)) / 220;
519 hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
525 f = pl.ping_packetloss;
526 tmp = pl.ping_movementloss;
527 if(f == 0 && tmp == 0)
529 str = ftos(ceil(f * 100));
531 str = strcat(str, "~", ftos(ceil(tmp * 100)));
532 tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
533 hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
537 if(ready_waiting && pl.ready)
539 hud_field_icon0 = "gfx/scoreboard/player_ready";
543 f = stof(getplayerkeyvalue(pl.sv_entnum, "colors"));
545 hud_field_icon0 = "gfx/scoreboard/playercolor_base";
546 hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
547 hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
548 hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
549 hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
552 return GetPlayerName(pl.sv_entnum);
555 f = pl.(scores[SP_KILLS]);
556 f -= pl.(scores[SP_SUICIDES]);
560 num = pl.(scores[SP_KILLS]);
561 denom = pl.(scores[SP_DEATHS]);
564 hud_field_rgb = '0 1 0';
565 str = sprintf("%d", num);
566 } else if(num <= 0) {
567 hud_field_rgb = '1 0 0';
568 str = sprintf("%.1f", num/denom);
570 str = sprintf("%.1f", num/denom);
574 tmp = pl.(scores[field]);
575 f = scores_flags[field];
576 if(field == ps_primary)
577 hud_field_rgb = '1 1 0';
578 else if(field == ps_secondary)
579 hud_field_rgb = '0 1 1';
581 hud_field_rgb = '1 1 1';
582 return ScoreString(f, tmp);
587 float xmin, xmax, ymin, ymax, sbwidth;
588 float hud_fixscoreboardcolumnwidth_len;
589 float hud_fixscoreboardcolumnwidth_iconlen;
590 float hud_fixscoreboardcolumnwidth_marginlen;
592 string HUD_FixScoreboardColumnWidth(float i, string str)
596 field = hud_field[i];
598 hud_fixscoreboardcolumnwidth_iconlen = 0;
600 if(hud_field_icon0 != "")
602 sz = draw_getimagesize(hud_field_icon0);
604 if(hud_fixscoreboardcolumnwidth_iconlen < f)
605 hud_fixscoreboardcolumnwidth_iconlen = f;
608 if(hud_field_icon1 != "")
610 sz = draw_getimagesize(hud_field_icon1);
612 if(hud_fixscoreboardcolumnwidth_iconlen < f)
613 hud_fixscoreboardcolumnwidth_iconlen = f;
616 if(hud_field_icon2 != "")
618 sz = draw_getimagesize(hud_field_icon2);
620 if(hud_fixscoreboardcolumnwidth_iconlen < f)
621 hud_fixscoreboardcolumnwidth_iconlen = f;
624 hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize_y / hud_fontsize_x; // fix icon aspect
626 if(hud_fixscoreboardcolumnwidth_iconlen != 0)
627 hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", FALSE, hud_fontsize);
629 hud_fixscoreboardcolumnwidth_marginlen = 0;
631 if(field == SP_NAME) // name gets all remaining space
634 namesize = sbwidth;// / hud_fontsize_x;
635 for(j = 0; j < hud_num_fields; ++j)
637 if (hud_field[i] != SP_SEPARATOR)
638 namesize -= hud_size[j] + hud_fontsize_x;
639 namesize += hud_fontsize_x;
640 hud_size[i] = namesize;
642 if (hud_fixscoreboardcolumnwidth_iconlen != 0)
643 namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
644 str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
645 hud_fixscoreboardcolumnwidth_len = stringwidth(str, TRUE, hud_fontsize);
648 hud_fixscoreboardcolumnwidth_len = stringwidth(str, FALSE, hud_fontsize);
650 f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
657 void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
660 rgb = GetTeamRGB(pl.team);
664 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
666 if((rgb == '1 1 1') && (!is_spec)) {
667 rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
668 rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
669 rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
673 tmp_y = hud_fontsize_y * 1.25;
676 // alternated rows highlighting
678 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
679 else if((scoreboard_highlight) && (!mod(pl_number,2)))
680 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
684 for(i = 0; i < hud_num_fields; ++i)
686 field = hud_field[i];
687 if(field == SP_SEPARATOR)
690 if(is_spec && field != SP_NAME && field != SP_PING) {
691 pos_x += hud_size[i] + hud_fontsize_x;
694 str = HUD_GetField(pl, field);
695 str = HUD_FixScoreboardColumnWidth(i, str);
697 pos_x += hud_size[i] + hud_fontsize_x;
699 if(field == SP_NAME) {
700 tmp_x = hud_size[i] - hud_fontsize_x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize_x;
702 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
704 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
706 tmp_x = hud_fixscoreboardcolumnwidth_len + hud_fontsize_x;
708 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
710 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
713 tmp_x = hud_size[i] + hud_fontsize_x;
714 if(hud_field_icon0 != "")
716 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);
718 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);
719 if(hud_field_icon1 != "")
721 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);
723 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);
724 if(hud_field_icon2 != "")
726 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);
728 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);
731 if(hud_field[i] == SP_SEPARATOR)
734 for(i = hud_num_fields-1; i > 0; --i)
736 field = hud_field[i];
737 if(field == SP_SEPARATOR)
740 if(is_spec && field != SP_NAME && field != SP_PING) {
741 pos_x -= hud_size[i] + hud_fontsize_x;
745 str = HUD_GetField(pl, field);
746 str = HUD_FixScoreboardColumnWidth(i, str);
748 if(field == SP_NAME) {
749 tmp_x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
751 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
753 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
755 tmp_x = hud_fixscoreboardcolumnwidth_len;
757 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
759 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
763 if(hud_field_icon0 != "")
765 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);
767 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);
768 if(hud_field_icon1 != "")
770 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);
772 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);
773 if(hud_field_icon2 != "")
775 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);
777 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);
778 pos_x -= hud_size[i] + hud_fontsize_x;
784 * HUD_Scoreboard_MakeTable
786 * Makes a table for a team (for all playing players in DM) and fills it
789 vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
791 float body_table_height, i;
792 vector tmp, column_dim;
795 body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
797 pos_y += autocvar_scoreboard_border_thickness;
801 tmp_y = 1.25 * hud_fontsize_y;
805 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
807 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
810 tmp_y += autocvar_scoreboard_border_thickness;
811 tmp_y += body_table_height;
812 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
814 // separator header/table
815 pos_y += 1.25 * hud_fontsize_y;
816 tmp_y = autocvar_scoreboard_border_thickness;
817 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
819 pos_y += autocvar_scoreboard_border_thickness;
822 tmp_y = body_table_height;
824 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
826 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
828 // anyway, apply some color
829 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
831 // go back to the top to make alternated columns highlighting and to print the strings
832 pos_y -= 1.25 * hud_fontsize_y;
833 pos_y -= autocvar_scoreboard_border_thickness;
837 if (scoreboard_highlight)
839 column_dim_y = 1.25 * hud_fontsize_y; // header
840 column_dim_y += autocvar_scoreboard_border_thickness;
841 column_dim_y += body_table_height;
844 // print the strings of the columns headers and draw the columns
845 draw_beginBoldFont();
846 for(i = 0; i < hud_num_fields; ++i)
848 if(hud_field[i] == SP_SEPARATOR)
850 column_dim_x = hud_size[i] + hud_fontsize_x;
851 if (scoreboard_highlight)
854 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
856 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
857 pos_x += column_dim_x;
859 if(hud_field[i] == SP_SEPARATOR)
863 for(i = hud_num_fields-1; i > 0; --i)
865 if(hud_field[i] == SP_SEPARATOR)
868 pos_x -= hud_size[i];
870 if (scoreboard_highlight)
874 if (i == hud_num_fields-1)
875 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
877 column_dim_x = hud_size[i] + hud_fontsize_x;
878 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
882 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
883 tmp_x = (hud_size[i] - tmp_x);
884 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
885 pos_x -= hud_fontsize_x;
891 pos_y += 1.25 * hud_fontsize_y; // skip the header
892 pos_y += autocvar_scoreboard_border_thickness;
894 // fill the table and draw the rows
897 for(pl = players.sort_next; pl; pl = pl.sort_next)
899 if(pl.team != tm.team)
901 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
902 pos_y += 1.25 * hud_fontsize_y;
906 for(pl = players.sort_next; pl; pl = pl.sort_next)
908 if(pl.team == COLOR_SPECTATOR)
910 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
911 pos_y += 1.25 * hud_fontsize_y;
916 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
917 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
922 float HUD_WouldDrawScoreboard() {
923 if (autocvar__hud_configure)
925 else if (scoreboard_showscores)
927 else if (intermission == 1)
929 else if (intermission == 2)
931 else if (spectatee_status != -1 && getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS)
933 else if (scoreboard_showscores_force)
939 float average_accuracy;
940 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
943 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
945 if(autocvar_scoreboard_accuracy_doublerows)
950 float fontsize = height * 1/3;
951 float weapon_height = height * 2/3;
952 float weapon_width = sbwidth / weapon_cnt;
954 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
955 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
958 tmp_y = height * rows;
961 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
963 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
964 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
966 // column highlighting
967 for(i = 0; i < weapon_cnt/rows; ++i)
970 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);
974 for(i = 0; i < rows; ++i)
976 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);
979 average_accuracy = 0;
980 float weapons_with_stats;
981 weapons_with_stats = 0;
983 pos_x += weapon_width / 2;
985 if(switchweapon == WEP_MINSTANEX)
986 g_minstagib = 1; // TODO: real detection for minstagib?
992 else if (acc_col[0] == '-1 0 0')
993 for (i = 0; i < acc_levels; ++i)
994 acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i))));
996 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
998 self = get_weaponinfo(i);
1001 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
1003 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1006 if(weapon_stats >= 0)
1007 weapon_alpha = scoreboard_alpha_fg;
1009 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1012 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);
1014 if(weapon_stats >= 0) {
1015 weapons_with_stats += 1;
1016 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1019 s = sprintf(_("%d%%"), weapon_stats*100);
1022 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1026 // find the max level lower than weapon_stats
1029 while ( j && weapon_stats < acc_lev[j] )
1032 // inject color j+1 in color j, how much depending on how much weapon_stats is higher than level j
1034 factor = (weapon_stats - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
1036 rgb = rgb + factor * (acc_col[j+1] - rgb);
1039 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1041 pos_x += weapon_width * rows;
1042 if(rows == 2 && i == 6) {
1048 if(weapons_with_stats)
1049 average_accuracy = floor(average_accuracy / weapons_with_stats);
1052 pos_x -= weapon_width / 2;
1056 pos_y += 1.25 * hud_fontsize_y;
1060 vector HUD_DrawKeyValue(vector pos, string key, string value) {
1062 pos_x += hud_fontsize_x * 0.25;
1063 drawstring(pos, key, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1064 pos_x = xmax - stringwidth(value, FALSE, hud_fontsize) - hud_fontsize_x * 0.25;
1065 drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1067 pos_y+= hud_fontsize_y;
1072 vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
1073 float stat_secrets_found, stat_secrets_total;
1077 // get secrets stats
1078 stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
1079 stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
1081 // get number of rows
1082 rows = (stat_secrets_total ? 1 : 0);
1084 // if no rows, return
1088 // draw table header
1089 drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1090 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
1095 tmp_y = hud_fontsize_y * rows;
1098 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1100 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1101 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1104 val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
1105 pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
1108 pos_y += 1.25 * hud_fontsize_y;
1113 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1116 RANKINGS_RECEIVED_CNT = 0;
1117 for (i=RANKINGS_CNT-1; i>=0; --i)
1119 ++RANKINGS_RECEIVED_CNT;
1121 if (RANKINGS_RECEIVED_CNT == 0)
1125 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
1127 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1128 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1129 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1131 pos_y += hud_fontsize_y;
1132 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1133 pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness;
1136 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1139 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1141 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1142 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1145 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1152 n = grecordholder[i];
1153 p = race_PlaceName(i+1);
1154 if(grecordholder[i] == GetPlayerName(player_localnum))
1155 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1156 else if(!mod(i, 2) && scoreboard_highlight)
1157 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1158 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1159 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);
1160 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1161 pos_y += 1.25 * hud_fontsize_y;
1163 pos_y += autocvar_scoreboard_border_thickness;
1168 float hud_woulddrawscoreboard_prev;
1169 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1170 void HUD_DrawScoreboard()
1172 float hud_woulddrawscoreboard;
1173 hud_woulddrawscoreboard = scoreboard_active;
1174 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1175 hud_woulddrawscoreboard_change = time;
1176 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1179 if(hud_woulddrawscoreboard) {
1180 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1181 if (scoreboard_fadeinspeed)
1182 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1184 scoreboard_fade_alpha = 1;
1187 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1188 if (scoreboard_fadeoutspeed)
1189 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1191 scoreboard_fade_alpha = 0;
1194 if not(scoreboard_fade_alpha)
1197 HUD_UpdatePlayerTeams();
1199 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1200 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1201 scoreboard_highlight = autocvar_scoreboard_highlight;
1202 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1203 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1204 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1205 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1207 vector rgb, pos, tmp;
1211 xmin = (autocvar_scoreboard_offset_left * vid_conwidth);
1212 ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth));
1214 xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth);
1215 ymax = (vid_conheight - ymin);
1217 sbwidth = xmax - xmin;
1219 // Initializes position
1225 vector sb_heading_fontsize;
1226 sb_heading_fontsize = hud_fontsize * 2;
1227 draw_beginBoldFont();
1228 drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1231 pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25;
1233 // Draw the scoreboard
1234 vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1238 vector team_score_baseoffset;
1239 team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25);
1240 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1242 if(tm.team == COLOR_SPECTATOR)
1245 draw_beginBoldFont();
1246 rgb = GetTeamRGB(tm.team);
1247 str = ftos(tm.(teamscores[ts_primary]));
1248 drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1250 if(ts_primary != ts_secondary)
1252 str = ftos(tm.(teamscores[ts_secondary]));
1253 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);
1257 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1262 rgb_x = autocvar_scoreboard_color_bg_r;
1263 rgb_y = autocvar_scoreboard_color_bg_g;
1264 rgb_z = autocvar_scoreboard_color_bg_b;
1266 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1268 if(tm.team == COLOR_SPECTATOR)
1271 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1275 if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) {
1276 if(race_speedaward) {
1277 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1278 pos_y += 1.25 * hud_fontsize_y;
1280 if(race_speedaward_alltimebest) {
1281 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1282 pos_y += 1.25 * hud_fontsize_y;
1284 pos = HUD_DrawScoreboardRankings(pos, pl, rgb, bg_size);
1286 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1288 pos = HUD_DrawScoreboardAccuracyStats(pos, GetTeamRGB(myteam), bg_size);
1290 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1295 pos = HUD_DrawMapStats(pos, GetTeamRGB(myteam), bg_size);
1297 pos = HUD_DrawMapStats(pos, rgb, bg_size);
1303 for(pl = players.sort_next; pl; pl = pl.sort_next)
1305 if(pl.team != COLOR_SPECTATOR)
1307 pos_y += 1.25 * hud_fontsize_y;
1308 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
1314 draw_beginBoldFont();
1315 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1317 pos_y += 1.25 * hud_fontsize_y;
1320 // Print info string
1322 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1323 tl = getstatf(STAT_TIMELIMIT);
1324 fl = getstatf(STAT_FRAGLIMIT);
1325 ll = getstatf(STAT_LEADLIMIT);
1326 if(gametype == MAPINFO_TYPE_LMS)
1329 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1334 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1338 str = strcat(str, _(" or"));
1341 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1342 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1343 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1344 TranslateScoresLabel(teamscores_label[ts_primary])));
1348 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1349 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1350 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1351 TranslateScoresLabel(scores_label[ps_primary])));
1356 if(tl > 0 || fl > 0)
1357 str = strcat(str, _(" or"));
1360 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1361 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1362 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1363 TranslateScoresLabel(teamscores_label[ts_primary])));
1367 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1368 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1369 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1370 TranslateScoresLabel(scores_label[ps_primary])));
1376 pos_y += 1.2 * hud_fontsize_y;
1377 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1379 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;