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 "net": return CTX(_("SCO^net"));
40 case "nick": return CTX(_("SCO^nick"));
41 case "objectives": return CTX(_("SCO^objectives"));
42 case "pickups": return CTX(_("SCO^pickups"));
43 case "ping": return CTX(_("SCO^ping"));
44 case "pl": return CTX(_("SCO^pl"));
45 case "pushes": return CTX(_("SCO^pushes"));
46 case "rank": return CTX(_("SCO^rank"));
47 case "returns": return CTX(_("SCO^returns"));
48 case "revivals": return CTX(_("SCO^revivals"));
49 case "score": return CTX(_("SCO^score"));
50 case "suicides": return CTX(_("SCO^suicides"));
51 case "takes": return CTX(_("SCO^takes"));
52 case "ticks": return CTX(_("SCO^ticks"));
58 void HUD_FinaleOverlay()
61 pos_x = (vid_conwidth - 1)/2;
65 //drawpic(pos, "gfx/finale", '0 0 0', '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
67 //drawstring(pos, "END", hud_fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
71 void Cmd_HUD_SetFields(float argc);
76 ps_primary = ps_secondary = ts_primary = ts_secondary = -1;
77 for(i = 0; i < MAX_SCORE; ++i)
79 f = (scores_flags[i] & SFL_SORT_PRIO_MASK);
80 if(f == SFL_SORT_PRIO_PRIMARY)
82 if(f == SFL_SORT_PRIO_SECONDARY)
85 if(ps_secondary == -1)
86 ps_secondary = ps_primary;
88 for(i = 0; i < MAX_TEAMSCORE; ++i)
90 f = (teamscores_flags[i] & SFL_SORT_PRIO_MASK);
91 if(f == SFL_SORT_PRIO_PRIMARY)
93 if(f == SFL_SORT_PRIO_SECONDARY)
96 if(ts_secondary == -1)
97 ts_secondary = ts_primary;
102 void HUD_UpdatePlayerPos(entity pl);
103 float SetTeam(entity pl, float Team);
105 void HUD_UpdatePlayerTeams()
112 for(pl = players.sort_next; pl; pl = pl.sort_next)
115 Team = GetPlayerColor(pl.sv_entnum);
116 if(SetTeam(pl, Team))
119 HUD_UpdatePlayerPos(pl);
123 pl = players.sort_next;
128 print(strcat("PNUM: ", ftos(num), "\n"));
133 float HUD_CompareScore(float vl, float vr, float f)
135 if(f & SFL_ZERO_IS_WORST)
137 if(vl == 0 && vr != 0)
139 if(vl != 0 && vr == 0)
143 return IS_INCREASING(f);
145 return IS_DECREASING(f);
149 float HUD_ComparePlayerScores(entity left, entity right)
152 vl = GetPlayerColor(left.sv_entnum);
153 vr = GetPlayerColor(right.sv_entnum);
165 if(vl == NUM_SPECTATOR)
167 // FIRST the one with scores (spectators), THEN the ones without (downloaders)
169 if(!left.gotscores && right.gotscores)
174 r = HUD_CompareScore(left.scores[ps_primary], right.scores[ps_primary], scores_flags[ps_primary]);
178 r = HUD_CompareScore(left.scores[ps_secondary], right.scores[ps_secondary], scores_flags[ps_secondary]);
182 for(i = 0; i < MAX_SCORE; ++i)
184 r = HUD_CompareScore(left.scores[i], right.scores[i], scores_flags[i]);
189 if (left.sv_entnum < right.sv_entnum)
195 void HUD_UpdatePlayerPos(entity player)
197 for(other = player.sort_next; other && HUD_ComparePlayerScores(player, other); other = player.sort_next)
199 SORT_SWAP(player, other);
201 for(other = player.sort_prev; other != players && HUD_ComparePlayerScores(other, player); other = player.sort_prev)
203 SORT_SWAP(other, player);
207 float HUD_CompareTeamScores(entity left, entity right)
211 if(left.team == NUM_SPECTATOR)
213 if(right.team == NUM_SPECTATOR)
216 r = HUD_CompareScore(left.teamscores[ts_primary], right.teamscores[ts_primary], teamscores_flags[ts_primary]);
220 r = HUD_CompareScore(left.teamscores[ts_secondary], right.teamscores[ts_secondary], teamscores_flags[ts_secondary]);
224 for(i = 0; i < MAX_SCORE; ++i)
226 r = HUD_CompareScore(left.teamscores[i], right.teamscores[i], teamscores_flags[i]);
231 if (left.team < right.team)
237 void HUD_UpdateTeamPos(entity Team)
239 for(other = Team.sort_next; other && HUD_CompareTeamScores(Team, other); other = Team.sort_next)
241 SORT_SWAP(Team, other);
243 for(other = Team.sort_prev; other != teams && HUD_CompareTeamScores(other, Team); other = Team.sort_prev)
245 SORT_SWAP(other, Team);
251 print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
252 print(_("^3|---------------------------------------------------------------|\n"));
253 print(_("Usage:\n"));
254 print(_("^2scoreboard_columns_set default\n"));
255 print(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
256 print(_("The following field names are recognized (case insensitive):\n"));
257 print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
259 print(_("^3name^7 or ^3nick^7 Name of a player\n"));
260 print(_("^3ping^7 Ping time\n"));
261 print(_("^3pl^7 Packet loss\n"));
262 print(_("^3kills^7 Number of kills\n"));
263 print(_("^3deaths^7 Number of deaths\n"));
264 print(_("^3suicides^7 Number of suicides\n"));
265 print(_("^3frags^7 kills - suicides\n"));
266 print(_("^3kd^7 The kill-death ratio\n"));
267 print(_("^3net^7 frags - deaths\n"));
268 print(_("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n"));
269 print(_("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
270 print(_("^3captime^7 Time of fastest cap (CTF)\n"));
271 print(_("^3fckills^7 Number of flag carrier kills\n"));
272 print(_("^3returns^7 Number of flag returns\n"));
273 print(_("^3drops^7 Number of flag drops\n"));
274 print(_("^3lives^7 Number of lives (LMS)\n"));
275 print(_("^3rank^7 Player rank\n"));
276 print(_("^3pushes^7 Number of players pushed into void\n"));
277 print(_("^3destroyed^7 Number of keys destroyed by pushing them into void\n"));
278 print(_("^3kckills^7 Number of keys carrier kills\n"));
279 print(_("^3losses^7 Number of times a key was lost\n"));
280 print(_("^3laps^7 Number of laps finished (race/cts)\n"));
281 print(_("^3time^7 Total time raced (race/cts)\n"));
282 print(_("^3fastest^7 Time of fastest lap (race/cts)\n"));
283 print(_("^3ticks^7 Number of ticks (DOM)\n"));
284 print(_("^3takes^7 Number of domination points taken (DOM)\n"));
285 print(_("^3bckills^7 Number of ball carrier kills\n"));
286 print(_("^3bctime^7 Total amount of time holding the ball in Keepaway\n"));
287 print(_("^3score^7 Total score\n\n"));
289 print(_("Before a field you can put a + or - sign, then a comma separated list\n"
290 "of game types, then a slash, to make the field show up only in these\n"
291 "or in all but these game types. You can also specify 'all' as a\n"
292 "field to show all fields available for the current game mode.\n\n"));
294 print(_("The special game type names 'teams' and 'noteams' can be used to\n"
295 "include/exclude ALL teams/noteams game modes.\n\n"));
297 print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
298 print(_("will display name, ping and pl aligned to the left, and the fields\n"
299 "right of the vertical bar aligned to the right.\n"));
300 print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
301 "other gamemodes except DM.\n"));
304 string HUD_DefaultColumnLayout()
306 return strcat( // fteqcc sucks
308 "-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"
309 "+tdm/frags +tdm/deaths +tdm/net ",
310 "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ",
311 "+lms/lives +lms/rank ",
312 "+kh/caps +kh/pushes +kh/destroyed ",
313 "?+race/laps ?+race/time ?+race/fastest ",
314 "+as/objectives +nexball/faults +nexball/goals +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ",
315 "-lms,race,nexball/score");
318 void Cmd_HUD_SetFields(float argc)
322 float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
325 // TODO: re enable with gametype dependant cvars?
326 if(argc < 3) // no arguments provided
327 argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
330 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
334 if(argv(2) == "default")
335 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
336 else if(argv(2) == "all")
339 s = "ping pl name |";
340 for(i = 0; i < MAX_SCORE; ++i)
343 if(i != ps_secondary)
344 if(scores_label[i] != "")
345 s = strcat(s, " ", scores_label[i]);
347 if(ps_secondary != ps_primary)
348 s = strcat(s, " ", scores_label[ps_secondary]);
349 s = strcat(s, " ", scores_label[ps_primary]);
350 argc = tokenizebyseparator(strcat("0 1 ", s), " ");
357 hud_fontsize = HUD_GetFontsize("hud_fontsize");
359 draw_beginBoldFont();
360 for(i = 1; i < argc - 1; ++i)
366 if(substring(str, 0, 1) == "?")
369 str = substring(str, 1, strlen(str) - 1);
372 slash = strstrofs(str, "/", 0);
375 pattern = substring(str, 0, slash);
376 str = substring(str, slash + 1, strlen(str) - (slash + 1));
378 if not(isGametypeInFilter(gametype, teamplay, FALSE, pattern))
382 strunzone(hud_title[hud_num_fields]);
383 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
384 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
385 str = strtolower(str);
388 hud_field[hud_num_fields] = SP_PING;
389 } else if(str == "pl") {
390 hud_field[hud_num_fields] = SP_PL;
391 } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
392 hud_field[hud_num_fields] = SP_KDRATIO;
393 } else if(str == "net" || str == "net" || str == "net" || str == "f-d") {
394 hud_field[hud_num_fields] = SP_NET;
395 } else if(str == "name" || str == "nick") {
396 hud_field[hud_num_fields] = SP_NAME;
398 } else if(str == "|") {
399 hud_field[hud_num_fields] = SP_SEPARATOR;
402 for(j = 0; j < MAX_SCORE; ++j)
403 if(str == strtolower(scores_label[j]))
404 goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
413 print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
417 hud_field[hud_num_fields] = j;
420 if(j == ps_secondary)
424 if(hud_num_fields >= MAX_HUD_FIELDS)
428 if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
430 if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
432 if(ps_primary == ps_secondary)
434 missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
436 if(hud_num_fields+missing < MAX_HUD_FIELDS)
440 strunzone(hud_title[hud_num_fields]);
441 for(i = hud_num_fields; i > 0; --i)
443 hud_title[i] = hud_title[i-1];
444 hud_size[i] = hud_size[i-1];
445 hud_field[i] = hud_field[i-1];
447 hud_title[0] = strzone(TranslateScoresLabel("name"));
448 hud_field[0] = SP_NAME;
450 print(sprintf(_("fixed missing field '%s'\n"), "name"));
454 strunzone(hud_title[hud_num_fields]);
455 for(i = hud_num_fields; i > 1; --i)
457 hud_title[i] = hud_title[i-1];
458 hud_size[i] = hud_size[i-1];
459 hud_field[i] = hud_field[i-1];
461 hud_title[1] = strzone("|");
462 hud_field[1] = SP_SEPARATOR;
463 hud_size[1] = stringwidth("|", FALSE, hud_fontsize);
465 print(sprintf(_("fixed missing field '%s'\n"), "|"));
468 else if(!have_separator)
470 strunzone(hud_title[hud_num_fields]);
471 hud_title[hud_num_fields] = strzone("|");
472 hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize);
473 hud_field[hud_num_fields] = SP_SEPARATOR;
475 print(sprintf(_("fixed missing field '%s'\n"), "|"));
479 strunzone(hud_title[hud_num_fields]);
480 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
481 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
482 hud_field[hud_num_fields] = ps_secondary;
484 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_secondary]));
488 strunzone(hud_title[hud_num_fields]);
489 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
490 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
491 hud_field[hud_num_fields] = ps_primary;
493 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_primary]));
497 hud_field[hud_num_fields] = SP_END;
502 vector hud_field_rgb;
503 string hud_field_icon0;
504 string hud_field_icon1;
505 string hud_field_icon2;
506 vector hud_field_icon0_rgb;
507 vector hud_field_icon1_rgb;
508 vector hud_field_icon2_rgb;
509 float hud_field_icon0_alpha;
510 float hud_field_icon1_alpha;
511 float hud_field_icon2_alpha;
512 string HUD_GetField(entity pl, float field)
514 float tmp, num, denom, f, num1;
516 hud_field_rgb = '1 1 1';
517 hud_field_icon0 = "";
518 hud_field_icon1 = "";
519 hud_field_icon2 = "";
520 hud_field_icon0_rgb = '1 1 1';
521 hud_field_icon1_rgb = '1 1 1';
522 hud_field_icon2_rgb = '1 1 1';
523 hud_field_icon0_alpha = 1;
524 hud_field_icon1_alpha = 1;
525 hud_field_icon2_alpha = 1;
530 return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
531 //str = getplayerkeyvalue(pl.sv_entnum, "ping");
535 tmp = max(0, min(220, f-80)) / 220;
536 hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
542 f = pl.ping_packetloss;
543 tmp = pl.ping_movementloss;
544 if(f == 0 && tmp == 0)
546 str = ftos(ceil(f * 100));
548 str = strcat(str, "~", ftos(ceil(tmp * 100)));
549 tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
550 hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
554 if(ready_waiting && pl.ready)
556 hud_field_icon0 = "gfx/scoreboard/player_ready";
560 f = stof(getplayerkeyvalue(pl.sv_entnum, "colors"));
562 hud_field_icon0 = "gfx/scoreboard/playercolor_base";
563 hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
564 hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
565 hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
566 hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
569 return GetPlayerName(pl.sv_entnum);
572 f = pl.(scores[SP_KILLS]);
573 f -= pl.(scores[SP_SUICIDES]);
577 num = pl.(scores[SP_KILLS]);
578 denom = pl.(scores[SP_DEATHS]);
581 hud_field_rgb = '0 1 0';
582 str = sprintf("%d", num);
583 } else if(num <= 0) {
584 hud_field_rgb = '1 0 0';
585 str = sprintf("%.1f", num/denom);
587 str = sprintf("%.1f", num/denom);
591 num1 = pl.(scores[SP_KILLS - SP_SUICIDES +2]);
592 denom = pl.(scores[SP_DEATHS]);
594 if((num1 - denom) > 0) {
595 hud_field_rgb = '0 1 0';
596 str = sprintf("%d", (num1 - denom));
597 } else if((num1 - denom) == 0) {
598 hud_field_rgb = '1 1 1';
599 str = sprintf("%d", (num1 - denom));
601 hud_field_rgb = '1 0 0';
602 str = sprintf("%d", (num1 - denom));
607 tmp = pl.(scores[field]);
608 f = scores_flags[field];
609 if(field == ps_primary)
610 hud_field_rgb = '1 1 0';
611 else if(field == ps_secondary)
612 hud_field_rgb = '0 1 1';
614 hud_field_rgb = '1 1 1';
615 return ScoreString(f, tmp);
620 float xmin, xmax, ymin, ymax, sbwidth;
621 float hud_fixscoreboardcolumnwidth_len;
622 float hud_fixscoreboardcolumnwidth_iconlen;
623 float hud_fixscoreboardcolumnwidth_marginlen;
625 string HUD_FixScoreboardColumnWidth(float i, string str)
629 field = hud_field[i];
631 hud_fixscoreboardcolumnwidth_iconlen = 0;
633 if(hud_field_icon0 != "")
635 sz = draw_getimagesize(hud_field_icon0);
637 if(hud_fixscoreboardcolumnwidth_iconlen < f)
638 hud_fixscoreboardcolumnwidth_iconlen = f;
641 if(hud_field_icon1 != "")
643 sz = draw_getimagesize(hud_field_icon1);
645 if(hud_fixscoreboardcolumnwidth_iconlen < f)
646 hud_fixscoreboardcolumnwidth_iconlen = f;
649 if(hud_field_icon2 != "")
651 sz = draw_getimagesize(hud_field_icon2);
653 if(hud_fixscoreboardcolumnwidth_iconlen < f)
654 hud_fixscoreboardcolumnwidth_iconlen = f;
657 hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize_y / hud_fontsize_x; // fix icon aspect
659 if(hud_fixscoreboardcolumnwidth_iconlen != 0)
660 hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", FALSE, hud_fontsize);
662 hud_fixscoreboardcolumnwidth_marginlen = 0;
664 if(field == SP_NAME) // name gets all remaining space
667 namesize = sbwidth;// / hud_fontsize_x;
668 for(j = 0; j < hud_num_fields; ++j)
670 if (hud_field[i] != SP_SEPARATOR)
671 namesize -= hud_size[j] + hud_fontsize_x;
672 namesize += hud_fontsize_x;
673 hud_size[i] = namesize;
675 if (hud_fixscoreboardcolumnwidth_iconlen != 0)
676 namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
677 str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
678 hud_fixscoreboardcolumnwidth_len = stringwidth(str, TRUE, hud_fontsize);
681 hud_fixscoreboardcolumnwidth_len = stringwidth(str, FALSE, hud_fontsize);
683 f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
690 void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
693 rgb = Team_ColorRGB(pl.team);
697 is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
699 if((rgb == '1 1 1') && (!is_spec)) {
700 rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
701 rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
702 rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
706 tmp_y = hud_fontsize_y * 1.25;
709 // alternated rows highlighting
711 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
712 else if((scoreboard_highlight) && (!mod(pl_number,2)))
713 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
717 for(i = 0; i < hud_num_fields; ++i)
719 field = hud_field[i];
720 if(field == SP_SEPARATOR)
723 if(is_spec && field != SP_NAME && field != SP_PING) {
724 pos_x += hud_size[i] + hud_fontsize_x;
727 str = HUD_GetField(pl, field);
728 str = HUD_FixScoreboardColumnWidth(i, str);
730 pos_x += hud_size[i] + hud_fontsize_x;
732 if(field == SP_NAME) {
733 tmp_x = hud_size[i] - hud_fontsize_x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize_x;
735 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
737 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
739 tmp_x = hud_fixscoreboardcolumnwidth_len + hud_fontsize_x;
741 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
743 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
746 tmp_x = hud_size[i] + hud_fontsize_x;
747 if(hud_field_icon0 != "")
749 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);
751 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);
752 if(hud_field_icon1 != "")
754 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);
756 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);
757 if(hud_field_icon2 != "")
759 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);
761 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);
764 if(hud_field[i] == SP_SEPARATOR)
767 for(i = hud_num_fields-1; i > 0; --i)
769 field = hud_field[i];
770 if(field == SP_SEPARATOR)
773 if(is_spec && field != SP_NAME && field != SP_PING) {
774 pos_x -= hud_size[i] + hud_fontsize_x;
778 str = HUD_GetField(pl, field);
779 str = HUD_FixScoreboardColumnWidth(i, str);
781 if(field == SP_NAME) {
782 tmp_x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
784 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
786 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
788 tmp_x = hud_fixscoreboardcolumnwidth_len;
790 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
792 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
796 if(hud_field_icon0 != "")
798 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);
800 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);
801 if(hud_field_icon1 != "")
803 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);
805 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);
806 if(hud_field_icon2 != "")
808 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);
810 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);
811 pos_x -= hud_size[i] + hud_fontsize_x;
817 * HUD_Scoreboard_MakeTable
819 * Makes a table for a team (for all playing players in DM) and fills it
822 vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
824 float body_table_height, i;
825 vector tmp = '0 0 0', column_dim = '0 0 0';
828 body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
830 pos_y += autocvar_scoreboard_border_thickness;
834 tmp_y = 1.25 * hud_fontsize_y;
838 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
840 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
843 tmp_y += autocvar_scoreboard_border_thickness;
844 tmp_y += body_table_height;
845 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
847 // separator header/table
848 pos_y += 1.25 * hud_fontsize_y;
849 tmp_y = autocvar_scoreboard_border_thickness;
850 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
852 pos_y += autocvar_scoreboard_border_thickness;
855 tmp_y = body_table_height;
857 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
859 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
861 // anyway, apply some color
862 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
864 // go back to the top to make alternated columns highlighting and to print the strings
865 pos_y -= 1.25 * hud_fontsize_y;
866 pos_y -= autocvar_scoreboard_border_thickness;
870 if (scoreboard_highlight)
872 column_dim_y = 1.25 * hud_fontsize_y; // header
873 column_dim_y += autocvar_scoreboard_border_thickness;
874 column_dim_y += body_table_height;
877 // print the strings of the columns headers and draw the columns
878 draw_beginBoldFont();
879 for(i = 0; i < hud_num_fields; ++i)
881 if(hud_field[i] == SP_SEPARATOR)
883 column_dim_x = hud_size[i] + hud_fontsize_x;
884 if (scoreboard_highlight)
887 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
889 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
890 pos_x += column_dim_x;
892 if(hud_field[i] == SP_SEPARATOR)
896 for(i = hud_num_fields-1; i > 0; --i)
898 if(hud_field[i] == SP_SEPARATOR)
901 pos_x -= hud_size[i];
903 if (scoreboard_highlight)
907 if (i == hud_num_fields-1)
908 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
910 column_dim_x = hud_size[i] + hud_fontsize_x;
911 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
915 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
916 tmp_x = (hud_size[i] - tmp_x);
917 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
918 pos_x -= hud_fontsize_x;
924 pos_y += 1.25 * hud_fontsize_y; // skip the header
925 pos_y += autocvar_scoreboard_border_thickness;
927 // fill the table and draw the rows
930 for(pl = players.sort_next; pl; pl = pl.sort_next)
932 if(pl.team != tm.team)
934 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
935 pos_y += 1.25 * hud_fontsize_y;
939 for(pl = players.sort_next; pl; pl = pl.sort_next)
941 if(pl.team == NUM_SPECTATOR)
943 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
944 pos_y += 1.25 * hud_fontsize_y;
949 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
950 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
955 float HUD_WouldDrawScoreboard() {
956 if (autocvar__hud_configure)
958 else if (scoreboard_showscores)
960 else if (intermission == 1)
962 else if (intermission == 2)
964 else if (spectatee_status != -1 && getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS)
966 else if (scoreboard_showscores_force)
972 float average_accuracy;
973 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
976 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
978 if(autocvar_scoreboard_accuracy_doublerows)
983 float fontsize = height * 1/3;
984 float weapon_height = height * 2/3;
985 float weapon_width = sbwidth / weapon_cnt;
987 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
988 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
989 vector tmp = '0 0 0';
991 tmp_y = height * rows;
994 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
996 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
997 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
999 // column highlighting
1000 for(i = 0; i < weapon_cnt/rows; ++i)
1003 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);
1007 for(i = 0; i < rows; ++i)
1009 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);
1012 average_accuracy = 0;
1013 float weapons_with_stats;
1014 weapons_with_stats = 0;
1016 pos_x += weapon_width / 2;
1018 if(switchweapon == WEP_MINSTANEX)
1019 g_minstagib = 1; // TODO: real detection for minstagib?
1022 if(autocvar_scoreboard_accuracy_nocolors)
1025 Accuracy_LoadColors();
1027 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
1029 self = get_weaponinfo(i);
1032 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
1034 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1037 if(weapon_stats >= 0)
1038 weapon_alpha = scoreboard_alpha_fg;
1040 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1043 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);
1045 if(weapon_stats >= 0) {
1046 weapons_with_stats += 1;
1047 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1050 s = sprintf(_("%d%%"), weapon_stats*100);
1053 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1055 if(!autocvar_scoreboard_accuracy_nocolors)
1056 rgb = Accuracy_GetColor(weapon_stats);
1058 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1060 pos_x += weapon_width * rows;
1061 if(rows == 2 && i == 6) {
1067 if(weapons_with_stats)
1068 average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5);
1071 pos_x -= weapon_width / 2;
1075 pos_y += 1.25 * hud_fontsize_y;
1079 vector HUD_DrawKeyValue(vector pos, string key, string value) {
1081 pos_x += hud_fontsize_x * 0.25;
1082 drawstring(pos, key, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1083 pos_x = xmax - stringwidth(value, FALSE, hud_fontsize) - hud_fontsize_x * 0.25;
1084 drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1086 pos_y+= hud_fontsize_y;
1091 vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
1092 float stat_secrets_found, stat_secrets_total;
1096 // get secrets stats
1097 stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
1098 stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
1100 // get number of rows
1101 rows = (stat_secrets_total ? 1 : 0);
1103 // if no rows, return
1107 // draw table header
1108 drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1109 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
1112 vector tmp = '0 0 0';
1114 tmp_y = hud_fontsize_y * rows;
1117 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1119 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1120 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1123 val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
1124 pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
1127 pos_y += 1.25 * hud_fontsize_y;
1132 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1135 RANKINGS_RECEIVED_CNT = 0;
1136 for (i=RANKINGS_CNT-1; i>=0; --i)
1138 ++RANKINGS_RECEIVED_CNT;
1140 if (RANKINGS_RECEIVED_CNT == 0)
1144 is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
1146 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1147 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1148 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1150 pos_y += hud_fontsize_y;
1151 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1152 pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness;
1153 vector tmp = '0 0 0';
1155 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1158 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1160 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1161 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1164 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1171 n = grecordholder[i];
1172 p = count_ordinal(i+1);
1173 if(grecordholder[i] == GetPlayerName(player_localnum))
1174 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1175 else if(!mod(i, 2) && scoreboard_highlight)
1176 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1177 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1178 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);
1179 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1180 pos_y += 1.25 * hud_fontsize_y;
1182 pos_y += autocvar_scoreboard_border_thickness;
1187 float hud_woulddrawscoreboard_prev;
1188 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1189 void HUD_DrawScoreboard()
1191 float hud_woulddrawscoreboard;
1192 hud_woulddrawscoreboard = scoreboard_active;
1193 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1194 hud_woulddrawscoreboard_change = time;
1195 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1198 if(hud_woulddrawscoreboard) {
1199 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1200 if (scoreboard_fadeinspeed)
1201 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1203 scoreboard_fade_alpha = 1;
1206 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1207 if (scoreboard_fadeoutspeed)
1208 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1210 scoreboard_fade_alpha = 0;
1213 if not(scoreboard_fade_alpha)
1216 HUD_UpdatePlayerTeams();
1218 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1219 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1220 scoreboard_highlight = autocvar_scoreboard_highlight;
1221 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1222 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1223 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1224 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1226 vector rgb, pos, tmp;
1230 xmin = (autocvar_scoreboard_offset_left * vid_conwidth);
1231 ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth));
1233 xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth);
1234 ymax = (vid_conheight - ymin);
1236 sbwidth = xmax - xmin;
1238 // Initializes position
1244 vector sb_heading_fontsize;
1245 sb_heading_fontsize = hud_fontsize * 2;
1246 draw_beginBoldFont();
1247 drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1250 pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25;
1252 // Draw the scoreboard
1253 vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1257 vector team_score_baseoffset;
1258 team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25);
1259 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1261 if(tm.team == NUM_SPECTATOR)
1264 draw_beginBoldFont();
1265 rgb = Team_ColorRGB(tm.team);
1266 str = ftos(tm.(teamscores[ts_primary]));
1267 drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1269 if(ts_primary != ts_secondary)
1271 str = ftos(tm.(teamscores[ts_secondary]));
1272 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);
1276 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1282 rgb_x = autocvar_scoreboard_color_bg_r;
1283 rgb_y = autocvar_scoreboard_color_bg_g;
1284 rgb_z = autocvar_scoreboard_color_bg_b;
1291 rgb_x = autocvar_scoreboard_color_bg_r;
1292 rgb_y = autocvar_scoreboard_color_bg_g;
1293 rgb_z = autocvar_scoreboard_color_bg_b;
1295 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1297 if(tm.team == NUM_SPECTATOR)
1300 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1304 if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) {
1305 if(race_speedaward) {
1306 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1307 pos_y += 1.25 * hud_fontsize_y;
1309 if(race_speedaward_alltimebest) {
1310 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1311 pos_y += 1.25 * hud_fontsize_y;
1313 pos = HUD_DrawScoreboardRankings(pos, playerslots[player_localnum], rgb, bg_size);
1315 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1317 pos = HUD_DrawScoreboardAccuracyStats(pos, Team_ColorRGB(myteam), bg_size);
1319 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1324 pos = HUD_DrawMapStats(pos, Team_ColorRGB(myteam), bg_size);
1326 pos = HUD_DrawMapStats(pos, rgb, bg_size);
1332 for(pl = players.sort_next; pl; pl = pl.sort_next)
1334 if(pl.team != NUM_SPECTATOR)
1336 pos_y += 1.25 * hud_fontsize_y;
1337 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
1343 draw_beginBoldFont();
1344 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1346 pos_y += 1.25 * hud_fontsize_y;
1349 // Print info string
1351 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1352 tl = getstatf(STAT_TIMELIMIT);
1353 fl = getstatf(STAT_FRAGLIMIT);
1354 ll = getstatf(STAT_LEADLIMIT);
1355 if(gametype == MAPINFO_TYPE_LMS)
1358 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1363 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1367 str = strcat(str, _(" or"));
1370 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1371 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1372 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1373 TranslateScoresLabel(teamscores_label[ts_primary])));
1377 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1378 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1379 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1380 TranslateScoresLabel(scores_label[ps_primary])));
1385 if(tl > 0 || fl > 0)
1386 str = strcat(str, _(" or"));
1389 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1390 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1391 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1392 TranslateScoresLabel(teamscores_label[ts_primary])));
1396 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1397 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1398 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1399 TranslateScoresLabel(scores_label[ps_primary])));
1404 pos_y += 1.2 * hud_fontsize_y;
1405 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1407 // print information about respawn status
1408 float respawn_time = getstatf(STAT_RESPAWN_TIME);
1411 if(respawn_time < 0)
1413 // a negative number means we are awaiting respawn, time value is still the same
1414 respawn_time *= -1; // remove mark now that we checked it
1415 respawn_time = max(time, respawn_time); // don't show a negative value while the server is respawning the player (lag)
1417 str = sprintf(_("^1Respawning in ^3%s^1..."),
1418 (autocvar_scoreboard_respawntime_decimals ?
1419 count_seconds_decs(respawn_time - time, autocvar_scoreboard_respawntime_decimals)
1421 count_seconds(respawn_time - time)
1425 else if(time < respawn_time)
1427 str = sprintf(_("You are dead, wait ^3%s^7 before respawning"),
1428 (autocvar_scoreboard_respawntime_decimals ?
1429 count_seconds_decs(respawn_time - time, autocvar_scoreboard_respawntime_decimals)
1431 count_seconds(respawn_time - time)
1435 else if(time >= respawn_time)
1436 str = sprintf(_("You are dead, press ^2%s^7 to respawn"), getcommandkey("jump", "+jump"));
1438 pos_y += 1.2 * hud_fontsize_y;
1439 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1442 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;