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_ComparePlayerScores(entity left, entity right)
135 vl = GetPlayerColor(left.sv_entnum);
136 vr = GetPlayerColor(right.sv_entnum);
139 vl = COLOR_SPECTATOR;
141 vr = COLOR_SPECTATOR;
148 if(vl == COLOR_SPECTATOR)
150 // FIRST the one with scores (spectators), THEN the ones without (downloaders)
152 if(!left.gotscores && right.gotscores)
157 vl = left.scores[ps_primary];
158 vr = right.scores[ps_primary];
159 if(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)
161 if(vl == 0 && vr != 0)
163 if(vl != 0 && vr == 0)
167 return IS_INCREASING(scores_flags[ps_primary]);
169 return IS_DECREASING(scores_flags[ps_primary]);
171 vl = left.scores[ps_secondary];
172 vr = right.scores[ps_secondary];
173 if(scores_flags[ps_secondary] & SFL_ZERO_IS_WORST)
175 if(vl == 0 && vr != 0)
177 if(vl != 0 && vr == 0)
181 return IS_INCREASING(scores_flags[ps_secondary]);
183 return IS_DECREASING(scores_flags[ps_secondary]);
188 void HUD_UpdatePlayerPos(entity player)
190 for(other = player.sort_next; other && HUD_ComparePlayerScores(player, other); other = player.sort_next)
192 SORT_SWAP(player, other);
194 for(other = player.sort_prev; other != players && HUD_ComparePlayerScores(other, player); other = player.sort_prev)
196 SORT_SWAP(other, player);
200 float HUD_CompareTeamScores(entity left, entity right)
204 if(left.team == COLOR_SPECTATOR)
206 if(right.team == COLOR_SPECTATOR)
209 vl = left.teamscores[ts_primary];
210 vr = right.teamscores[ts_primary];
212 return IS_INCREASING(teamscores_flags[ts_primary]);
214 return IS_DECREASING(teamscores_flags[ts_primary]);
216 vl = left.teamscores[ts_secondary];
217 vr = right.teamscores[ts_secondary];
219 return IS_INCREASING(teamscores_flags[ts_secondary]);
221 return IS_DECREASING(teamscores_flags[ts_secondary]);
226 void HUD_UpdateTeamPos(entity Team)
228 for(other = Team.sort_next; other && HUD_CompareTeamScores(Team, other); other = Team.sort_next)
230 SORT_SWAP(Team, other);
232 for(other = Team.sort_prev; other != teams && HUD_CompareTeamScores(other, Team); other = Team.sort_prev)
234 SORT_SWAP(other, Team);
240 print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
241 print(_("^3|---------------------------------------------------------------|\n"));
242 print(_("Usage:\n"));
243 print(_("^2scoreboard_columns_set default\n"));
244 print(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
245 print(_("The following field names are recognized (case insensitive):\n"));
246 print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
248 print(_("^3name^7 or ^3nick^7 Name of a player\n"));
249 print(_("^3ping^7 Ping time\n"));
250 print(_("^3pl^7 Packet loss\n"));
251 print(_("^3kills^7 Number of kills\n"));
252 print(_("^3deaths^7 Number of deaths\n"));
253 print(_("^3suicides^7 Number of suicides\n"));
254 print(_("^3frags^7 kills - suicides\n"));
255 print(_("^3kd^7 The kill-death ratio\n"));
256 print(_("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n"));
257 print(_("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
258 print(_("^3captime^7 Time of fastest cap (CTF)\n"));
259 print(_("^3fckills^7 Number of flag carrier kills\n"));
260 print(_("^3returns^7 Number of flag returns\n"));
261 print(_("^3drops^7 Number of flag drops\n"));
262 print(_("^3lives^7 Number of lives (LMS)\n"));
263 print(_("^3rank^7 Player rank\n"));
264 print(_("^3pushes^7 Number of players pushed into void\n"));
265 print(_("^3destroyed^7 Number of keys destroyed by pushing them into void\n"));
266 print(_("^3kckills^7 Number of keys carrier kills\n"));
267 print(_("^3losses^7 Number of times a key was lost\n"));
268 print(_("^3laps^7 Number of laps finished (race/cts)\n"));
269 print(_("^3time^7 Total time raced (race/cts)\n"));
270 print(_("^3fastest^7 Time of fastest lap (race/cts)\n"));
271 print(_("^3ticks^7 Number of ticks (DOM)\n"));
272 print(_("^3takes^7 Number of domination points taken (DOM)\n"));
273 print(_("^3bckills^7 Number of ball carrier kills\n"));
274 print(_("^3bctime^7 Total amount of time holding the ball in Keepaway\n"));
275 print(_("^3score^7 Total score\n\n"));
277 print(_("Before a field you can put a + or - sign, then a comma separated list\n"
278 "of game types, then a slash, to make the field show up only in these\n"
279 "or in all but these game types. You can also specify 'all' as a\n"
280 "field to show all fields available for the current game mode.\n\n"));
282 print(_("The special game type names 'teams' and 'noteams' can be used to\n"
283 "include/exclude ALL teams/noteams game modes.\n\n"));
285 print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
286 print(_("will display name, ping and pl aligned to the left, and the fields\n"
287 "right of the vertical bar aligned to the right.\n"));
288 print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
289 "other gamemodes except DM.\n"));
292 string HUD_DefaultColumnLayout()
294 return strcat( // fteqcc sucks
296 "-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"
297 "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ",
298 "+lms/lives +lms/rank ",
299 "+kh/caps +kh/pushes +kh/destroyed ",
300 "?+race/laps ?+race/time ?+race/fastest ",
301 "+as/objectives +nexball/faults +nexball/goals +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ",
302 "-lms,race,nexball/score");
305 void Cmd_HUD_SetFields(float argc)
309 float have_name, have_primary, have_secondary, have_separator;
312 // TODO: re enable with gametype dependant cvars?
313 if(argc < 3) // no arguments provided
314 argc = tokenizebyseparator(strcat("x ", autocvar_scoreboard_columns), " ");
317 argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
321 if(argv(2) == "default")
322 argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
323 else if(argv(2) == "all")
326 s = "ping pl name |";
327 for(i = 0; i < MAX_SCORE; ++i)
330 if(i != ps_secondary)
331 if(scores_label[i] != "")
332 s = strcat(s, " ", scores_label[i]);
334 if(ps_secondary != ps_primary)
335 s = strcat(s, " ", scores_label[ps_secondary]);
336 s = strcat(s, " ", scores_label[ps_primary]);
337 argc = tokenizebyseparator(strcat("x ", s), " ");
344 hud_fontsize = HUD_GetFontsize("hud_fontsize");
346 draw_beginBoldFont();
347 for(i = 0; i < argc - 1; ++i)
353 if(substring(str, 0, 1) == "?")
356 str = substring(str, 1, strlen(str) - 1);
359 slash = strstrofs(str, "/", 0);
362 pattern = substring(str, 0, slash);
363 str = substring(str, slash + 1, strlen(str) - (slash + 1));
365 if not(isGametypeInFilter(gametype, teamplay, FALSE, pattern))
369 strunzone(hud_title[hud_num_fields]);
370 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
371 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
372 str = strtolower(str);
375 hud_field[hud_num_fields] = SP_PING;
376 } else if(str == "pl") {
377 hud_field[hud_num_fields] = SP_PL;
378 } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
379 hud_field[hud_num_fields] = SP_KDRATIO;
380 } else if(str == "name" || str == "nick") {
381 hud_field[hud_num_fields] = SP_NAME;
383 } else if(str == "|") {
384 hud_field[hud_num_fields] = SP_SEPARATOR;
387 for(j = 0; j < MAX_SCORE; ++j)
388 if(str == strtolower(scores_label[j]))
389 goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
398 print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
402 hud_field[hud_num_fields] = j;
405 if(j == ps_secondary)
409 if(hud_num_fields >= MAX_HUD_FIELDS)
413 if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
415 if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
417 if(ps_primary == ps_secondary)
419 missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
421 if(hud_num_fields+missing < MAX_HUD_FIELDS)
425 strunzone(hud_title[hud_num_fields]);
426 for(i = hud_num_fields; i > 0; --i)
428 hud_title[i] = hud_title[i-1];
429 hud_size[i] = hud_size[i-1];
430 hud_field[i] = hud_field[i-1];
432 hud_title[0] = strzone(TranslateScoresLabel("name"));
433 hud_field[0] = SP_NAME;
435 print(sprintf(_("fixed missing field '%s'\n"), "name"));
439 strunzone(hud_title[hud_num_fields]);
440 for(i = hud_num_fields; i > 1; --i)
442 hud_title[i] = hud_title[i-1];
443 hud_size[i] = hud_size[i-1];
444 hud_field[i] = hud_field[i-1];
446 hud_title[1] = strzone("|");
447 hud_field[1] = SP_SEPARATOR;
448 hud_size[1] = stringwidth("|", FALSE, hud_fontsize);
450 print(sprintf(_("fixed missing field '%s'\n"), "|"));
453 else if(!have_separator)
455 strunzone(hud_title[hud_num_fields]);
456 hud_title[hud_num_fields] = strzone("|");
457 hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize);
458 hud_field[hud_num_fields] = SP_SEPARATOR;
460 print(sprintf(_("fixed missing field '%s'\n"), "|"));
464 strunzone(hud_title[hud_num_fields]);
465 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
466 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
467 hud_field[hud_num_fields] = ps_secondary;
469 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_secondary]));
473 strunzone(hud_title[hud_num_fields]);
474 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
475 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
476 hud_field[hud_num_fields] = ps_primary;
478 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_primary]));
482 hud_field[hud_num_fields] = SP_END;
487 vector hud_field_rgb;
488 string hud_field_icon0;
489 string hud_field_icon1;
490 string hud_field_icon2;
491 vector hud_field_icon0_rgb;
492 vector hud_field_icon1_rgb;
493 vector hud_field_icon2_rgb;
494 float hud_field_icon0_alpha;
495 float hud_field_icon1_alpha;
496 float hud_field_icon2_alpha;
497 string HUD_GetField(entity pl, float field)
499 float tmp, num, denom, f;
501 hud_field_rgb = '1 1 1';
502 hud_field_icon0 = "";
503 hud_field_icon1 = "";
504 hud_field_icon2 = "";
505 hud_field_icon0_rgb = '1 1 1';
506 hud_field_icon1_rgb = '1 1 1';
507 hud_field_icon2_rgb = '1 1 1';
508 hud_field_icon0_alpha = 1;
509 hud_field_icon1_alpha = 1;
510 hud_field_icon2_alpha = 1;
515 return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
516 //str = getplayerkeyvalue(pl.sv_entnum, "ping");
520 tmp = max(0, min(220, f-80)) / 220;
521 hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
527 f = pl.ping_packetloss;
528 tmp = pl.ping_movementloss;
529 if(f == 0 && tmp == 0)
531 str = ftos(ceil(f * 100));
533 str = strcat(str, "~", ftos(ceil(tmp * 100)));
534 tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
535 hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
539 if(ready_waiting && pl.ready)
541 hud_field_icon0 = "gfx/scoreboard/player_ready";
545 f = stof(getplayerkeyvalue(pl.sv_entnum, "colors"));
547 hud_field_icon0 = "gfx/scoreboard/playercolor_base";
548 hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
549 hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
550 hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
551 hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
554 return GetPlayerName(pl.sv_entnum);
557 f = pl.(scores[SP_KILLS]);
558 f -= pl.(scores[SP_SUICIDES]);
562 num = pl.(scores[SP_KILLS]);
563 denom = pl.(scores[SP_DEATHS]);
566 hud_field_rgb = '0 1 0';
567 str = sprintf("%d", num);
568 } else if(num <= 0) {
569 hud_field_rgb = '1 0 0';
570 str = sprintf("%.1f", num/denom);
572 str = sprintf("%.1f", num/denom);
576 tmp = pl.(scores[field]);
577 f = scores_flags[field];
578 if(field == ps_primary)
579 hud_field_rgb = '1 1 0';
580 else if(field == ps_secondary)
581 hud_field_rgb = '0 1 1';
583 hud_field_rgb = '1 1 1';
584 return ScoreString(f, tmp);
589 float xmin, xmax, ymin, ymax, sbwidth;
590 float hud_fixscoreboardcolumnwidth_len;
591 float hud_fixscoreboardcolumnwidth_iconlen;
592 float hud_fixscoreboardcolumnwidth_marginlen;
594 string HUD_FixScoreboardColumnWidth(float i, string str)
598 field = hud_field[i];
600 hud_fixscoreboardcolumnwidth_iconlen = 0;
602 if(hud_field_icon0 != "")
604 sz = draw_getimagesize(hud_field_icon0);
606 if(hud_fixscoreboardcolumnwidth_iconlen < f)
607 hud_fixscoreboardcolumnwidth_iconlen = f;
610 if(hud_field_icon1 != "")
612 sz = draw_getimagesize(hud_field_icon1);
614 if(hud_fixscoreboardcolumnwidth_iconlen < f)
615 hud_fixscoreboardcolumnwidth_iconlen = f;
618 if(hud_field_icon2 != "")
620 sz = draw_getimagesize(hud_field_icon2);
622 if(hud_fixscoreboardcolumnwidth_iconlen < f)
623 hud_fixscoreboardcolumnwidth_iconlen = f;
626 hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize_y / hud_fontsize_x; // fix icon aspect
628 if(hud_fixscoreboardcolumnwidth_iconlen != 0)
629 hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", FALSE, hud_fontsize);
631 hud_fixscoreboardcolumnwidth_marginlen = 0;
633 if(field == SP_NAME) // name gets all remaining space
636 namesize = sbwidth;// / hud_fontsize_x;
637 for(j = 0; j < hud_num_fields; ++j)
639 if (hud_field[i] != SP_SEPARATOR)
640 namesize -= hud_size[j] + hud_fontsize_x;
641 namesize += hud_fontsize_x;
642 hud_size[i] = namesize;
644 if (hud_fixscoreboardcolumnwidth_iconlen != 0)
645 namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
646 str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
647 hud_fixscoreboardcolumnwidth_len = stringwidth(str, TRUE, hud_fontsize);
650 hud_fixscoreboardcolumnwidth_len = stringwidth(str, FALSE, hud_fontsize);
652 f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
659 void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
662 rgb = GetTeamRGB(pl.team);
666 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
668 if((rgb == '1 1 1') && (!is_spec)) {
669 rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
670 rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
671 rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
675 tmp_y = hud_fontsize_y * 1.25;
678 // alternated rows highlighting
680 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
681 else if((scoreboard_highlight) && (!mod(pl_number,2)))
682 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
686 for(i = 0; i < hud_num_fields; ++i)
688 field = hud_field[i];
689 if(field == SP_SEPARATOR)
692 if(is_spec && field != SP_NAME && field != SP_PING) {
693 pos_x += hud_size[i] + hud_fontsize_x;
696 str = HUD_GetField(pl, field);
697 str = HUD_FixScoreboardColumnWidth(i, str);
699 pos_x += hud_size[i] + hud_fontsize_x;
701 if(field == SP_NAME) {
702 tmp_x = hud_size[i] - hud_fontsize_x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize_x;
704 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
706 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
708 tmp_x = hud_fixscoreboardcolumnwidth_len + hud_fontsize_x;
710 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
712 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
715 tmp_x = hud_size[i] + hud_fontsize_x;
716 if(hud_field_icon0 != "")
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_self, DRAWFLAG_NORMAL);
720 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);
721 if(hud_field_icon1 != "")
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_self, DRAWFLAG_NORMAL);
725 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);
726 if(hud_field_icon2 != "")
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_self, DRAWFLAG_NORMAL);
730 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);
733 if(hud_field[i] == SP_SEPARATOR)
736 for(i = hud_num_fields-1; i > 0; --i)
738 field = hud_field[i];
739 if(field == SP_SEPARATOR)
742 if(is_spec && field != SP_NAME && field != SP_PING) {
743 pos_x -= hud_size[i] + hud_fontsize_x;
747 str = HUD_GetField(pl, field);
748 str = HUD_FixScoreboardColumnWidth(i, str);
750 if(field == SP_NAME) {
751 tmp_x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
753 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
755 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
757 tmp_x = hud_fixscoreboardcolumnwidth_len;
759 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
761 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
765 if(hud_field_icon0 != "")
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_self, DRAWFLAG_NORMAL);
769 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);
770 if(hud_field_icon1 != "")
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_self, DRAWFLAG_NORMAL);
774 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);
775 if(hud_field_icon2 != "")
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_self, DRAWFLAG_NORMAL);
779 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);
780 pos_x -= hud_size[i] + hud_fontsize_x;
786 * HUD_Scoreboard_MakeTable
788 * Makes a table for a team (for all playing players in DM) and fills it
791 vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
793 float body_table_height, i;
794 vector tmp, column_dim;
797 body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
799 pos_y += autocvar_scoreboard_border_thickness;
803 tmp_y = 1.25 * hud_fontsize_y;
807 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
809 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
812 tmp_y += autocvar_scoreboard_border_thickness;
813 tmp_y += body_table_height;
814 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
816 // separator header/table
817 pos_y += 1.25 * hud_fontsize_y;
818 tmp_y = autocvar_scoreboard_border_thickness;
819 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
821 pos_y += autocvar_scoreboard_border_thickness;
824 tmp_y = body_table_height;
826 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
828 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
830 // anyway, apply some color
831 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
833 // go back to the top to make alternated columns highlighting and to print the strings
834 pos_y -= 1.25 * hud_fontsize_y;
835 pos_y -= autocvar_scoreboard_border_thickness;
839 if (scoreboard_highlight)
841 column_dim_y = 1.25 * hud_fontsize_y; // header
842 column_dim_y += autocvar_scoreboard_border_thickness;
843 column_dim_y += body_table_height;
846 // print the strings of the columns headers and draw the columns
847 draw_beginBoldFont();
848 for(i = 0; i < hud_num_fields; ++i)
850 if(hud_field[i] == SP_SEPARATOR)
852 column_dim_x = hud_size[i] + hud_fontsize_x;
853 if (scoreboard_highlight)
856 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
858 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
859 pos_x += column_dim_x;
861 if(hud_field[i] == SP_SEPARATOR)
865 for(i = hud_num_fields-1; i > 0; --i)
867 if(hud_field[i] == SP_SEPARATOR)
870 pos_x -= hud_size[i];
872 if (scoreboard_highlight)
876 if (i == hud_num_fields-1)
877 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
879 column_dim_x = hud_size[i] + hud_fontsize_x;
880 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
884 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
885 tmp_x = (hud_size[i] - tmp_x);
886 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
887 pos_x -= hud_fontsize_x;
893 pos_y += 1.25 * hud_fontsize_y; // skip the header
894 pos_y += autocvar_scoreboard_border_thickness;
896 // fill the table and draw the rows
899 for(pl = players.sort_next; pl; pl = pl.sort_next)
901 if(pl.team != tm.team)
903 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
904 pos_y += 1.25 * hud_fontsize_y;
908 for(pl = players.sort_next; pl; pl = pl.sort_next)
910 if(pl.team == COLOR_SPECTATOR)
912 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
913 pos_y += 1.25 * hud_fontsize_y;
918 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
919 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
924 float HUD_WouldDrawScoreboard() {
925 if (autocvar__hud_configure)
927 else if (scoreboard_showscores)
929 else if (intermission == 1)
931 else if (intermission == 2)
933 else if (spectatee_status != -1 && getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS)
935 else if (scoreboard_showscores_force)
941 float average_accuracy;
942 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
945 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
947 if(autocvar_scoreboard_accuracy_doublerows)
952 float fontsize = height * 1/3;
953 float weapon_height = height * 2/3;
954 float weapon_width = sbwidth / weapon_cnt;
956 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
957 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
960 tmp_y = height * rows;
963 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
965 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
966 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
968 // column highlighting
969 for(i = 0; i < weapon_cnt/rows; ++i)
972 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);
976 for(i = 0; i < rows; ++i)
978 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);
981 average_accuracy = 0;
982 float weapons_with_stats;
983 weapons_with_stats = 0;
985 pos_x += weapon_width / 2;
987 if(switchweapon == WEP_MINSTANEX)
988 g_minstagib = 1; // TODO: real detection for minstagib?
994 else if (acc_col[0] == '-1 0 0')
995 for (i = 0; i < acc_levels; ++i)
996 acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i))));
998 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
1000 self = get_weaponinfo(i);
1003 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
1005 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1008 if(weapon_stats >= 0)
1009 weapon_alpha = scoreboard_alpha_fg;
1011 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1014 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);
1016 if(weapon_stats >= 0) {
1017 weapons_with_stats += 1;
1018 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1021 s = sprintf(_("%d%%"), weapon_stats*100);
1024 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1028 // find the max level lower than weapon_stats
1031 while ( j && weapon_stats < acc_lev[j] )
1034 // inject color j+1 in color j, how much depending on how much weapon_stats is higher than level j
1036 factor = (weapon_stats - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
1038 rgb = rgb + factor * (acc_col[j+1] - rgb);
1041 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1043 pos_x += weapon_width * rows;
1044 if(rows == 2 && i == 6) {
1050 if(weapons_with_stats)
1051 average_accuracy = floor(average_accuracy / weapons_with_stats);
1054 pos_x -= weapon_width / 2;
1058 pos_y += 1.25 * hud_fontsize_y;
1062 vector HUD_DrawKeyValue(vector pos, string key, string value) {
1064 pos_x += hud_fontsize_x * 0.25;
1065 drawstring(pos, key, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1066 pos_x = xmax - stringwidth(value, FALSE, hud_fontsize) - hud_fontsize_x * 0.25;
1067 drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1069 pos_y+= hud_fontsize_y;
1074 vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
1075 float stat_secrets_found, stat_secrets_total;
1079 // get secrets stats
1080 stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
1081 stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
1083 // get number of rows
1084 rows = (stat_secrets_total ? 1 : 0);
1086 // if no rows, return
1090 // draw table header
1091 drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1092 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
1097 tmp_y = hud_fontsize_y * rows;
1100 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1102 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1103 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1106 val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
1107 pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
1110 pos_y += 1.25 * hud_fontsize_y;
1115 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1118 RANKINGS_RECEIVED_CNT = 0;
1119 for (i=RANKINGS_CNT-1; i>=0; --i)
1121 ++RANKINGS_RECEIVED_CNT;
1123 if (RANKINGS_RECEIVED_CNT == 0)
1127 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
1129 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1130 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1131 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1133 pos_y += hud_fontsize_y;
1134 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1135 pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness;
1138 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1141 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1143 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1144 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1147 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1154 n = grecordholder[i];
1155 p = race_PlaceName(i+1);
1156 if(grecordholder[i] == GetPlayerName(player_localnum))
1157 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1158 else if(!mod(i, 2) && scoreboard_highlight)
1159 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1160 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1161 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);
1162 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1163 pos_y += 1.25 * hud_fontsize_y;
1165 pos_y += autocvar_scoreboard_border_thickness;
1170 float hud_woulddrawscoreboard_prev;
1171 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1172 void HUD_DrawScoreboard()
1174 float hud_woulddrawscoreboard;
1175 hud_woulddrawscoreboard = scoreboard_active;
1176 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1177 hud_woulddrawscoreboard_change = time;
1178 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1181 if(hud_woulddrawscoreboard) {
1182 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1183 if (scoreboard_fadeinspeed)
1184 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1186 scoreboard_fade_alpha = 1;
1189 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1190 if (scoreboard_fadeoutspeed)
1191 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1193 scoreboard_fade_alpha = 0;
1196 if not(scoreboard_fade_alpha)
1199 HUD_UpdatePlayerTeams();
1201 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1202 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1203 scoreboard_highlight = autocvar_scoreboard_highlight;
1204 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1205 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1206 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1207 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1209 vector rgb, pos, tmp;
1213 xmin = (autocvar_scoreboard_offset_left * vid_conwidth);
1214 ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth));
1216 xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth);
1217 ymax = (vid_conheight - ymin);
1219 sbwidth = xmax - xmin;
1221 // Initializes position
1227 vector sb_heading_fontsize;
1228 sb_heading_fontsize = hud_fontsize * 2;
1229 draw_beginBoldFont();
1230 drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1233 pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25;
1235 // Draw the scoreboard
1236 vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1240 vector team_score_baseoffset;
1241 team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25);
1242 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1244 if(tm.team == COLOR_SPECTATOR)
1247 draw_beginBoldFont();
1248 rgb = GetTeamRGB(tm.team);
1249 str = ftos(tm.(teamscores[ts_primary]));
1250 drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1252 if(ts_primary != ts_secondary)
1254 str = ftos(tm.(teamscores[ts_secondary]));
1255 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);
1259 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1264 rgb_x = autocvar_scoreboard_color_bg_r;
1265 rgb_y = autocvar_scoreboard_color_bg_g;
1266 rgb_z = autocvar_scoreboard_color_bg_b;
1268 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1270 if(tm.team == COLOR_SPECTATOR)
1273 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1277 if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) {
1278 if(race_speedaward) {
1279 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1280 pos_y += 1.25 * hud_fontsize_y;
1282 if(race_speedaward_alltimebest) {
1283 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1284 pos_y += 1.25 * hud_fontsize_y;
1286 pos = HUD_DrawScoreboardRankings(pos, pl, rgb, bg_size);
1288 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1290 pos = HUD_DrawScoreboardAccuracyStats(pos, GetTeamRGB(myteam), bg_size);
1292 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1297 pos = HUD_DrawMapStats(pos, GetTeamRGB(myteam), bg_size);
1299 pos = HUD_DrawMapStats(pos, rgb, bg_size);
1305 for(pl = players.sort_next; pl; pl = pl.sort_next)
1307 if(pl.team != COLOR_SPECTATOR)
1309 pos_y += 1.25 * hud_fontsize_y;
1310 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
1316 draw_beginBoldFont();
1317 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1319 pos_y += 1.25 * hud_fontsize_y;
1322 // Print info string
1324 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1325 tl = getstatf(STAT_TIMELIMIT);
1326 fl = getstatf(STAT_FRAGLIMIT);
1327 ll = getstatf(STAT_LEADLIMIT);
1328 if(gametype == MAPINFO_TYPE_LMS)
1331 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1336 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1340 str = strcat(str, _(" or"));
1343 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1344 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1345 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1346 TranslateScoresLabel(teamscores_label[ts_primary])));
1350 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1351 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1352 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1353 TranslateScoresLabel(scores_label[ps_primary])));
1358 if(tl > 0 || fl > 0)
1359 str = strcat(str, _(" or"));
1362 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1363 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1364 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1365 TranslateScoresLabel(teamscores_label[ts_primary])));
1369 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1370 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1371 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1372 TranslateScoresLabel(scores_label[ps_primary])));
1378 pos_y += 1.2 * hud_fontsize_y;
1379 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1381 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;