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]);
191 void HUD_UpdatePlayerPos(entity player)
193 for(other = player.sort_next; other && HUD_ComparePlayerScores(player, other); other = player.sort_next)
195 SORT_SWAP(player, other);
197 for(other = player.sort_prev; other != players && HUD_ComparePlayerScores(other, player); other = player.sort_prev)
199 SORT_SWAP(other, player);
203 float HUD_CompareTeamScores(entity left, entity right)
207 if(left.team == COLOR_SPECTATOR)
209 if(right.team == COLOR_SPECTATOR)
212 r = HUD_CompareScore(left.teamscores[ts_primary], right.teamscores[ts_primary], teamscores_flags[ts_primary]);
216 r = HUD_CompareScore(left.teamscores[ts_secondary], right.teamscores[ts_secondary], teamscores_flags[ts_secondary]);
220 for(i = 0; i < MAX_SCORE; ++i)
222 r = HUD_CompareScore(left.teamscores[i], right.teamscores[i], teamscores_flags[i]);
230 void HUD_UpdateTeamPos(entity Team)
232 for(other = Team.sort_next; other && HUD_CompareTeamScores(Team, other); other = Team.sort_next)
234 SORT_SWAP(Team, other);
236 for(other = Team.sort_prev; other != teams && HUD_CompareTeamScores(other, Team); other = Team.sort_prev)
238 SORT_SWAP(other, Team);
244 print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
245 print(_("^3|---------------------------------------------------------------|\n"));
246 print(_("Usage:\n"));
247 print(_("^2scoreboard_columns_set default\n"));
248 print(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
249 print(_("The following field names are recognized (case insensitive):\n"));
250 print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
252 print(_("^3name^7 or ^3nick^7 Name of a player\n"));
253 print(_("^3ping^7 Ping time\n"));
254 print(_("^3pl^7 Packet loss\n"));
255 print(_("^3kills^7 Number of kills\n"));
256 print(_("^3deaths^7 Number of deaths\n"));
257 print(_("^3suicides^7 Number of suicides\n"));
258 print(_("^3frags^7 kills - suicides\n"));
259 print(_("^3kd^7 The kill-death ratio\n"));
260 print(_("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n"));
261 print(_("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
262 print(_("^3captime^7 Time of fastest cap (CTF)\n"));
263 print(_("^3fckills^7 Number of flag carrier kills\n"));
264 print(_("^3returns^7 Number of flag returns\n"));
265 print(_("^3drops^7 Number of flag drops\n"));
266 print(_("^3lives^7 Number of lives (LMS)\n"));
267 print(_("^3rank^7 Player rank\n"));
268 print(_("^3pushes^7 Number of players pushed into void\n"));
269 print(_("^3destroyed^7 Number of keys destroyed by pushing them into void\n"));
270 print(_("^3kckills^7 Number of keys carrier kills\n"));
271 print(_("^3losses^7 Number of times a key was lost\n"));
272 print(_("^3laps^7 Number of laps finished (race/cts)\n"));
273 print(_("^3time^7 Total time raced (race/cts)\n"));
274 print(_("^3fastest^7 Time of fastest lap (race/cts)\n"));
275 print(_("^3ticks^7 Number of ticks (DOM)\n"));
276 print(_("^3takes^7 Number of domination points taken (DOM)\n"));
277 print(_("^3bckills^7 Number of ball carrier kills\n"));
278 print(_("^3bctime^7 Total amount of time holding the ball in Keepaway\n"));
279 print(_("^3score^7 Total score\n\n"));
281 print(_("Before a field you can put a + or - sign, then a comma separated list\n"
282 "of game types, then a slash, to make the field show up only in these\n"
283 "or in all but these game types. You can also specify 'all' as a\n"
284 "field to show all fields available for the current game mode.\n\n"));
286 print(_("The special game type names 'teams' and 'noteams' can be used to\n"
287 "include/exclude ALL teams/noteams game modes.\n\n"));
289 print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
290 print(_("will display name, ping and pl aligned to the left, and the fields\n"
291 "right of the vertical bar aligned to the right.\n"));
292 print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
293 "other gamemodes except DM.\n"));
296 string HUD_DefaultColumnLayout()
298 return strcat( // fteqcc sucks
300 "-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"
301 "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ",
302 "+lms/lives +lms/rank ",
303 "+kh/caps +kh/pushes +kh/destroyed ",
304 "?+race/laps ?+race/time ?+race/fastest ",
305 "+as/objectives +nexball/faults +nexball/goals +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ",
306 "-lms,race,nexball/score");
309 void Cmd_HUD_SetFields(float argc)
313 float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
316 // TODO: re enable with gametype dependant cvars?
317 if(argc < 3) // no arguments provided
318 argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
321 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
325 if(argv(2) == "default")
326 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
327 else if(argv(2) == "all")
330 s = "ping pl name |";
331 for(i = 0; i < MAX_SCORE; ++i)
334 if(i != ps_secondary)
335 if(scores_label[i] != "")
336 s = strcat(s, " ", scores_label[i]);
338 if(ps_secondary != ps_primary)
339 s = strcat(s, " ", scores_label[ps_secondary]);
340 s = strcat(s, " ", scores_label[ps_primary]);
341 argc = tokenizebyseparator(strcat("0 1 ", s), " ");
348 hud_fontsize = HUD_GetFontsize("hud_fontsize");
350 draw_beginBoldFont();
351 for(i = 1; i < argc - 1; ++i)
357 if(substring(str, 0, 1) == "?")
360 str = substring(str, 1, strlen(str) - 1);
363 slash = strstrofs(str, "/", 0);
366 pattern = substring(str, 0, slash);
367 str = substring(str, slash + 1, strlen(str) - (slash + 1));
369 if not(isGametypeInFilter(gametype, teamplay, FALSE, pattern))
373 strunzone(hud_title[hud_num_fields]);
374 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
375 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
376 str = strtolower(str);
379 hud_field[hud_num_fields] = SP_PING;
380 } else if(str == "pl") {
381 hud_field[hud_num_fields] = SP_PL;
382 } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
383 hud_field[hud_num_fields] = SP_KDRATIO;
384 } else if(str == "name" || str == "nick") {
385 hud_field[hud_num_fields] = SP_NAME;
387 } else if(str == "|") {
388 hud_field[hud_num_fields] = SP_SEPARATOR;
391 for(j = 0; j < MAX_SCORE; ++j)
392 if(str == strtolower(scores_label[j]))
393 goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
402 print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
406 hud_field[hud_num_fields] = j;
409 if(j == ps_secondary)
413 if(hud_num_fields >= MAX_HUD_FIELDS)
417 if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
419 if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
421 if(ps_primary == ps_secondary)
423 missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
425 if(hud_num_fields+missing < MAX_HUD_FIELDS)
429 strunzone(hud_title[hud_num_fields]);
430 for(i = hud_num_fields; i > 0; --i)
432 hud_title[i] = hud_title[i-1];
433 hud_size[i] = hud_size[i-1];
434 hud_field[i] = hud_field[i-1];
436 hud_title[0] = strzone(TranslateScoresLabel("name"));
437 hud_field[0] = SP_NAME;
439 print(sprintf(_("fixed missing field '%s'\n"), "name"));
443 strunzone(hud_title[hud_num_fields]);
444 for(i = hud_num_fields; i > 1; --i)
446 hud_title[i] = hud_title[i-1];
447 hud_size[i] = hud_size[i-1];
448 hud_field[i] = hud_field[i-1];
450 hud_title[1] = strzone("|");
451 hud_field[1] = SP_SEPARATOR;
452 hud_size[1] = stringwidth("|", FALSE, hud_fontsize);
454 print(sprintf(_("fixed missing field '%s'\n"), "|"));
457 else if(!have_separator)
459 strunzone(hud_title[hud_num_fields]);
460 hud_title[hud_num_fields] = strzone("|");
461 hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize);
462 hud_field[hud_num_fields] = SP_SEPARATOR;
464 print(sprintf(_("fixed missing field '%s'\n"), "|"));
468 strunzone(hud_title[hud_num_fields]);
469 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
470 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
471 hud_field[hud_num_fields] = ps_secondary;
473 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_secondary]));
477 strunzone(hud_title[hud_num_fields]);
478 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
479 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
480 hud_field[hud_num_fields] = ps_primary;
482 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_primary]));
486 hud_field[hud_num_fields] = SP_END;
491 vector hud_field_rgb;
492 string hud_field_icon0;
493 string hud_field_icon1;
494 string hud_field_icon2;
495 vector hud_field_icon0_rgb;
496 vector hud_field_icon1_rgb;
497 vector hud_field_icon2_rgb;
498 float hud_field_icon0_alpha;
499 float hud_field_icon1_alpha;
500 float hud_field_icon2_alpha;
501 string HUD_GetField(entity pl, float field)
503 float tmp, num, denom, f;
505 hud_field_rgb = '1 1 1';
506 hud_field_icon0 = "";
507 hud_field_icon1 = "";
508 hud_field_icon2 = "";
509 hud_field_icon0_rgb = '1 1 1';
510 hud_field_icon1_rgb = '1 1 1';
511 hud_field_icon2_rgb = '1 1 1';
512 hud_field_icon0_alpha = 1;
513 hud_field_icon1_alpha = 1;
514 hud_field_icon2_alpha = 1;
519 return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
520 //str = getplayerkeyvalue(pl.sv_entnum, "ping");
524 tmp = max(0, min(220, f-80)) / 220;
525 hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
531 f = pl.ping_packetloss;
532 tmp = pl.ping_movementloss;
533 if(f == 0 && tmp == 0)
535 str = ftos(ceil(f * 100));
537 str = strcat(str, "~", ftos(ceil(tmp * 100)));
538 tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
539 hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
543 if(ready_waiting && pl.ready)
545 hud_field_icon0 = "gfx/scoreboard/player_ready";
549 f = stof(getplayerkeyvalue(pl.sv_entnum, "colors"));
551 hud_field_icon0 = "gfx/scoreboard/playercolor_base";
552 hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
553 hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
554 hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
555 hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
558 return GetPlayerName(pl.sv_entnum);
561 f = pl.(scores[SP_KILLS]);
562 f -= pl.(scores[SP_SUICIDES]);
566 num = pl.(scores[SP_KILLS]);
567 denom = pl.(scores[SP_DEATHS]);
570 hud_field_rgb = '0 1 0';
571 str = sprintf("%d", num);
572 } else if(num <= 0) {
573 hud_field_rgb = '1 0 0';
574 str = sprintf("%.1f", num/denom);
576 str = sprintf("%.1f", num/denom);
580 tmp = pl.(scores[field]);
581 f = scores_flags[field];
582 if(field == ps_primary)
583 hud_field_rgb = '1 1 0';
584 else if(field == ps_secondary)
585 hud_field_rgb = '0 1 1';
587 hud_field_rgb = '1 1 1';
588 return ScoreString(f, tmp);
593 float xmin, xmax, ymin, ymax, sbwidth;
594 float hud_fixscoreboardcolumnwidth_len;
595 float hud_fixscoreboardcolumnwidth_iconlen;
596 float hud_fixscoreboardcolumnwidth_marginlen;
598 string HUD_FixScoreboardColumnWidth(float i, string str)
602 field = hud_field[i];
604 hud_fixscoreboardcolumnwidth_iconlen = 0;
606 if(hud_field_icon0 != "")
608 sz = draw_getimagesize(hud_field_icon0);
610 if(hud_fixscoreboardcolumnwidth_iconlen < f)
611 hud_fixscoreboardcolumnwidth_iconlen = f;
614 if(hud_field_icon1 != "")
616 sz = draw_getimagesize(hud_field_icon1);
618 if(hud_fixscoreboardcolumnwidth_iconlen < f)
619 hud_fixscoreboardcolumnwidth_iconlen = f;
622 if(hud_field_icon2 != "")
624 sz = draw_getimagesize(hud_field_icon2);
626 if(hud_fixscoreboardcolumnwidth_iconlen < f)
627 hud_fixscoreboardcolumnwidth_iconlen = f;
630 hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize_y / hud_fontsize_x; // fix icon aspect
632 if(hud_fixscoreboardcolumnwidth_iconlen != 0)
633 hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", FALSE, hud_fontsize);
635 hud_fixscoreboardcolumnwidth_marginlen = 0;
637 if(field == SP_NAME) // name gets all remaining space
640 namesize = sbwidth;// / hud_fontsize_x;
641 for(j = 0; j < hud_num_fields; ++j)
643 if (hud_field[i] != SP_SEPARATOR)
644 namesize -= hud_size[j] + hud_fontsize_x;
645 namesize += hud_fontsize_x;
646 hud_size[i] = namesize;
648 if (hud_fixscoreboardcolumnwidth_iconlen != 0)
649 namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
650 str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
651 hud_fixscoreboardcolumnwidth_len = stringwidth(str, TRUE, hud_fontsize);
654 hud_fixscoreboardcolumnwidth_len = stringwidth(str, FALSE, hud_fontsize);
656 f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
663 void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
666 rgb = GetTeamRGB(pl.team);
670 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
672 if((rgb == '1 1 1') && (!is_spec)) {
673 rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
674 rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
675 rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
679 tmp_y = hud_fontsize_y * 1.25;
682 // alternated rows highlighting
684 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
685 else if((scoreboard_highlight) && (!mod(pl_number,2)))
686 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
690 for(i = 0; i < hud_num_fields; ++i)
692 field = hud_field[i];
693 if(field == SP_SEPARATOR)
696 if(is_spec && field != SP_NAME && field != SP_PING) {
697 pos_x += hud_size[i] + hud_fontsize_x;
700 str = HUD_GetField(pl, field);
701 str = HUD_FixScoreboardColumnWidth(i, str);
703 pos_x += hud_size[i] + hud_fontsize_x;
705 if(field == SP_NAME) {
706 tmp_x = hud_size[i] - hud_fontsize_x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize_x;
708 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
710 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
712 tmp_x = hud_fixscoreboardcolumnwidth_len + hud_fontsize_x;
714 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
716 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
719 tmp_x = hud_size[i] + hud_fontsize_x;
720 if(hud_field_icon0 != "")
722 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);
724 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);
725 if(hud_field_icon1 != "")
727 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);
729 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);
730 if(hud_field_icon2 != "")
732 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);
734 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);
737 if(hud_field[i] == SP_SEPARATOR)
740 for(i = hud_num_fields-1; i > 0; --i)
742 field = hud_field[i];
743 if(field == SP_SEPARATOR)
746 if(is_spec && field != SP_NAME && field != SP_PING) {
747 pos_x -= hud_size[i] + hud_fontsize_x;
751 str = HUD_GetField(pl, field);
752 str = HUD_FixScoreboardColumnWidth(i, str);
754 if(field == SP_NAME) {
755 tmp_x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
757 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
759 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
761 tmp_x = hud_fixscoreboardcolumnwidth_len;
763 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
765 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
769 if(hud_field_icon0 != "")
771 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);
773 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);
774 if(hud_field_icon1 != "")
776 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);
778 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);
779 if(hud_field_icon2 != "")
781 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);
783 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);
784 pos_x -= hud_size[i] + hud_fontsize_x;
790 * HUD_Scoreboard_MakeTable
792 * Makes a table for a team (for all playing players in DM) and fills it
795 vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
797 float body_table_height, i;
798 vector tmp = '0 0 0', column_dim = '0 0 0';
801 body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
803 pos_y += autocvar_scoreboard_border_thickness;
807 tmp_y = 1.25 * hud_fontsize_y;
811 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
813 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
816 tmp_y += autocvar_scoreboard_border_thickness;
817 tmp_y += body_table_height;
818 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
820 // separator header/table
821 pos_y += 1.25 * hud_fontsize_y;
822 tmp_y = autocvar_scoreboard_border_thickness;
823 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
825 pos_y += autocvar_scoreboard_border_thickness;
828 tmp_y = body_table_height;
830 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
832 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
834 // anyway, apply some color
835 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
837 // go back to the top to make alternated columns highlighting and to print the strings
838 pos_y -= 1.25 * hud_fontsize_y;
839 pos_y -= autocvar_scoreboard_border_thickness;
843 if (scoreboard_highlight)
845 column_dim_y = 1.25 * hud_fontsize_y; // header
846 column_dim_y += autocvar_scoreboard_border_thickness;
847 column_dim_y += body_table_height;
850 // print the strings of the columns headers and draw the columns
851 draw_beginBoldFont();
852 for(i = 0; i < hud_num_fields; ++i)
854 if(hud_field[i] == SP_SEPARATOR)
856 column_dim_x = hud_size[i] + hud_fontsize_x;
857 if (scoreboard_highlight)
860 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
862 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
863 pos_x += column_dim_x;
865 if(hud_field[i] == SP_SEPARATOR)
869 for(i = hud_num_fields-1; i > 0; --i)
871 if(hud_field[i] == SP_SEPARATOR)
874 pos_x -= hud_size[i];
876 if (scoreboard_highlight)
880 if (i == hud_num_fields-1)
881 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
883 column_dim_x = hud_size[i] + hud_fontsize_x;
884 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
888 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
889 tmp_x = (hud_size[i] - tmp_x);
890 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
891 pos_x -= hud_fontsize_x;
897 pos_y += 1.25 * hud_fontsize_y; // skip the header
898 pos_y += autocvar_scoreboard_border_thickness;
900 // fill the table and draw the rows
903 for(pl = players.sort_next; pl; pl = pl.sort_next)
905 if(pl.team != tm.team)
907 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
908 pos_y += 1.25 * hud_fontsize_y;
912 for(pl = players.sort_next; pl; pl = pl.sort_next)
914 if(pl.team == COLOR_SPECTATOR)
916 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
917 pos_y += 1.25 * hud_fontsize_y;
922 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
923 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
928 float HUD_WouldDrawScoreboard() {
929 if (autocvar__hud_configure)
931 else if (scoreboard_showscores)
933 else if (intermission == 1)
935 else if (intermission == 2)
937 else if (spectatee_status != -1 && getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS)
939 else if (scoreboard_showscores_force)
945 float average_accuracy;
946 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
949 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
951 if(autocvar_scoreboard_accuracy_doublerows)
956 float fontsize = height * 1/3;
957 float weapon_height = height * 2/3;
958 float weapon_width = sbwidth / weapon_cnt;
960 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
961 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
962 vector tmp = '0 0 0';
964 tmp_y = height * rows;
967 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
969 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
970 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
972 // column highlighting
973 for(i = 0; i < weapon_cnt/rows; ++i)
976 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);
980 for(i = 0; i < rows; ++i)
982 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);
985 average_accuracy = 0;
986 float weapons_with_stats;
987 weapons_with_stats = 0;
989 pos_x += weapon_width / 2;
991 if(switchweapon == WEP_MINSTANEX)
992 g_minstagib = 1; // TODO: real detection for minstagib?
998 else if (acc_col[0] == '-1 0 0')
999 for (i = 0; i < acc_levels; ++i)
1000 acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i))));
1002 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
1004 self = get_weaponinfo(i);
1007 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
1009 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1012 if(weapon_stats >= 0)
1013 weapon_alpha = scoreboard_alpha_fg;
1015 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1018 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);
1020 if(weapon_stats >= 0) {
1021 weapons_with_stats += 1;
1022 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1025 s = sprintf(_("%d%%"), weapon_stats*100);
1028 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1032 // find the max level lower than weapon_stats
1035 while ( j && weapon_stats < acc_lev[j] )
1038 // inject color j+1 in color j, how much depending on how much weapon_stats is higher than level j
1040 factor = (weapon_stats - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
1042 rgb = rgb + factor * (acc_col[j+1] - rgb);
1045 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1047 pos_x += weapon_width * rows;
1048 if(rows == 2 && i == 6) {
1054 if(weapons_with_stats)
1055 average_accuracy = floor(average_accuracy / weapons_with_stats);
1058 pos_x -= weapon_width / 2;
1062 pos_y += 1.25 * hud_fontsize_y;
1066 vector HUD_DrawKeyValue(vector pos, string key, string value) {
1068 pos_x += hud_fontsize_x * 0.25;
1069 drawstring(pos, key, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1070 pos_x = xmax - stringwidth(value, FALSE, hud_fontsize) - hud_fontsize_x * 0.25;
1071 drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1073 pos_y+= hud_fontsize_y;
1078 vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
1079 float stat_secrets_found, stat_secrets_total;
1083 // get secrets stats
1084 stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
1085 stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
1087 // get number of rows
1088 rows = (stat_secrets_total ? 1 : 0);
1090 // if no rows, return
1094 // draw table header
1095 drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1096 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
1099 vector tmp = '0 0 0';
1101 tmp_y = hud_fontsize_y * rows;
1104 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1106 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1107 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1110 val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
1111 pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
1114 pos_y += 1.25 * hud_fontsize_y;
1119 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1122 RANKINGS_RECEIVED_CNT = 0;
1123 for (i=RANKINGS_CNT-1; i>=0; --i)
1125 ++RANKINGS_RECEIVED_CNT;
1127 if (RANKINGS_RECEIVED_CNT == 0)
1131 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
1133 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1134 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1135 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1137 pos_y += hud_fontsize_y;
1138 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1139 pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness;
1140 vector tmp = '0 0 0';
1142 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1145 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1147 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1148 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1151 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1158 n = grecordholder[i];
1159 p = race_PlaceName(i+1);
1160 if(grecordholder[i] == GetPlayerName(player_localnum))
1161 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1162 else if(!mod(i, 2) && scoreboard_highlight)
1163 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1164 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1165 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);
1166 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1167 pos_y += 1.25 * hud_fontsize_y;
1169 pos_y += autocvar_scoreboard_border_thickness;
1174 float hud_woulddrawscoreboard_prev;
1175 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1176 void HUD_DrawScoreboard()
1178 float hud_woulddrawscoreboard;
1179 hud_woulddrawscoreboard = scoreboard_active;
1180 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1181 hud_woulddrawscoreboard_change = time;
1182 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1185 if(hud_woulddrawscoreboard) {
1186 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1187 if (scoreboard_fadeinspeed)
1188 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1190 scoreboard_fade_alpha = 1;
1193 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1194 if (scoreboard_fadeoutspeed)
1195 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1197 scoreboard_fade_alpha = 0;
1200 if not(scoreboard_fade_alpha)
1203 HUD_UpdatePlayerTeams();
1205 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1206 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1207 scoreboard_highlight = autocvar_scoreboard_highlight;
1208 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1209 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1210 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1211 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1213 vector rgb, pos, tmp;
1217 xmin = (autocvar_scoreboard_offset_left * vid_conwidth);
1218 ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth));
1220 xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth);
1221 ymax = (vid_conheight - ymin);
1223 sbwidth = xmax - xmin;
1225 // Initializes position
1231 vector sb_heading_fontsize;
1232 sb_heading_fontsize = hud_fontsize * 2;
1233 draw_beginBoldFont();
1234 drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1237 pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25;
1239 // Draw the scoreboard
1240 vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1244 vector team_score_baseoffset;
1245 team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25);
1246 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1248 if(tm.team == COLOR_SPECTATOR)
1251 draw_beginBoldFont();
1252 rgb = GetTeamRGB(tm.team);
1253 str = ftos(tm.(teamscores[ts_primary]));
1254 drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1256 if(ts_primary != ts_secondary)
1258 str = ftos(tm.(teamscores[ts_secondary]));
1259 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);
1263 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1269 rgb_x = autocvar_scoreboard_color_bg_r;
1270 rgb_y = autocvar_scoreboard_color_bg_g;
1271 rgb_z = autocvar_scoreboard_color_bg_b;
1278 rgb_x = autocvar_scoreboard_color_bg_r;
1279 rgb_y = autocvar_scoreboard_color_bg_g;
1280 rgb_z = autocvar_scoreboard_color_bg_b;
1282 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1284 if(tm.team == COLOR_SPECTATOR)
1287 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1291 if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) {
1292 if(race_speedaward) {
1293 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1294 pos_y += 1.25 * hud_fontsize_y;
1296 if(race_speedaward_alltimebest) {
1297 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1298 pos_y += 1.25 * hud_fontsize_y;
1300 pos = HUD_DrawScoreboardRankings(pos, playerslots[player_localnum], rgb, bg_size);
1302 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1304 pos = HUD_DrawScoreboardAccuracyStats(pos, GetTeamRGB(myteam), bg_size);
1306 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1311 pos = HUD_DrawMapStats(pos, GetTeamRGB(myteam), bg_size);
1313 pos = HUD_DrawMapStats(pos, rgb, bg_size);
1319 for(pl = players.sort_next; pl; pl = pl.sort_next)
1321 if(pl.team != COLOR_SPECTATOR)
1323 pos_y += 1.25 * hud_fontsize_y;
1324 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
1330 draw_beginBoldFont();
1331 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1333 pos_y += 1.25 * hud_fontsize_y;
1336 // Print info string
1338 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1339 tl = getstatf(STAT_TIMELIMIT);
1340 fl = getstatf(STAT_FRAGLIMIT);
1341 ll = getstatf(STAT_LEADLIMIT);
1342 if(gametype == MAPINFO_TYPE_LMS)
1345 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1350 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1354 str = strcat(str, _(" or"));
1357 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1358 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1359 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1360 TranslateScoresLabel(teamscores_label[ts_primary])));
1364 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1365 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1366 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1367 TranslateScoresLabel(scores_label[ps_primary])));
1372 if(tl > 0 || fl > 0)
1373 str = strcat(str, _(" or"));
1376 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1377 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1378 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1379 TranslateScoresLabel(teamscores_label[ts_primary])));
1383 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1384 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1385 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1386 TranslateScoresLabel(scores_label[ps_primary])));
1391 pos_y += 1.2 * hud_fontsize_y;
1392 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1394 // print information about respawn status
1395 float respawn_time = getstatf(STAT_RESPAWN_TIME);
1398 if(respawn_time < 0)
1400 // a negative number means we are awaiting respawn, time value is still the same
1401 respawn_time *= -1; // remove mark now that we checked it
1402 respawn_time = max(time, respawn_time); // don't show a negative value while the server is respawning the player (lag)
1404 str = sprintf(_("^1Respawning in ^3%s^1 seconds..."), ftos_decimals(respawn_time - time, autocvar_scoreboard_respawntime_decimals));
1406 else if(time < respawn_time)
1407 str = sprintf(_("You are dead, wait ^3%s^7 seconds before respawning"), ftos_decimals(respawn_time - time, autocvar_scoreboard_respawntime_decimals));
1408 else if(time >= respawn_time)
1409 str = sprintf(_("You are dead, press ^2%s^7 to respawn"), getcommandkey("jump", "+jump"));
1411 pos_y += 1.2 * hud_fontsize_y;
1412 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1415 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;