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);
164 if(vl == FL_SPECTATOR)
166 // FIRST the one with scores (spectators), THEN the ones without (downloaders)
168 if(!left.gotscores && right.gotscores)
173 r = HUD_CompareScore(left.scores[ps_primary], right.scores[ps_primary], scores_flags[ps_primary]);
177 r = HUD_CompareScore(left.scores[ps_secondary], right.scores[ps_secondary], scores_flags[ps_secondary]);
181 for(i = 0; i < MAX_SCORE; ++i)
183 r = HUD_CompareScore(left.scores[i], right.scores[i], scores_flags[i]);
188 if (left.sv_entnum < right.sv_entnum)
194 void HUD_UpdatePlayerPos(entity player)
196 for(other = player.sort_next; other && HUD_ComparePlayerScores(player, other); other = player.sort_next)
198 SORT_SWAP(player, other);
200 for(other = player.sort_prev; other != players && HUD_ComparePlayerScores(other, player); other = player.sort_prev)
202 SORT_SWAP(other, player);
206 float HUD_CompareTeamScores(entity left, entity right)
210 if(left.team == FL_SPECTATOR)
212 if(right.team == FL_SPECTATOR)
215 r = HUD_CompareScore(left.teamscores[ts_primary], right.teamscores[ts_primary], teamscores_flags[ts_primary]);
219 r = HUD_CompareScore(left.teamscores[ts_secondary], right.teamscores[ts_secondary], teamscores_flags[ts_secondary]);
223 for(i = 0; i < MAX_SCORE; ++i)
225 r = HUD_CompareScore(left.teamscores[i], right.teamscores[i], teamscores_flags[i]);
230 if (left.team < right.team)
236 void HUD_UpdateTeamPos(entity Team)
238 for(other = Team.sort_next; other && HUD_CompareTeamScores(Team, other); other = Team.sort_next)
240 SORT_SWAP(Team, other);
242 for(other = Team.sort_prev; other != teams && HUD_CompareTeamScores(other, Team); other = Team.sort_prev)
244 SORT_SWAP(other, Team);
250 print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
251 print(_("^3|---------------------------------------------------------------|\n"));
252 print(_("Usage:\n"));
253 print(_("^2scoreboard_columns_set default\n"));
254 print(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
255 print(_("The following field names are recognized (case insensitive):\n"));
256 print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
258 print(_("^3name^7 or ^3nick^7 Name of a player\n"));
259 print(_("^3ping^7 Ping time\n"));
260 print(_("^3pl^7 Packet loss\n"));
261 print(_("^3kills^7 Number of kills\n"));
262 print(_("^3deaths^7 Number of deaths\n"));
263 print(_("^3suicides^7 Number of suicides\n"));
264 print(_("^3frags^7 kills - suicides\n"));
265 print(_("^3kd^7 The kill-death ratio\n"));
266 print(_("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n"));
267 print(_("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
268 print(_("^3captime^7 Time of fastest cap (CTF)\n"));
269 print(_("^3fckills^7 Number of flag carrier kills\n"));
270 print(_("^3returns^7 Number of flag returns\n"));
271 print(_("^3drops^7 Number of flag drops\n"));
272 print(_("^3lives^7 Number of lives (LMS)\n"));
273 print(_("^3rank^7 Player rank\n"));
274 print(_("^3pushes^7 Number of players pushed into void\n"));
275 print(_("^3destroyed^7 Number of keys destroyed by pushing them into void\n"));
276 print(_("^3kckills^7 Number of keys carrier kills\n"));
277 print(_("^3losses^7 Number of times a key was lost\n"));
278 print(_("^3laps^7 Number of laps finished (race/cts)\n"));
279 print(_("^3time^7 Total time raced (race/cts)\n"));
280 print(_("^3fastest^7 Time of fastest lap (race/cts)\n"));
281 print(_("^3ticks^7 Number of ticks (DOM)\n"));
282 print(_("^3takes^7 Number of domination points taken (DOM)\n"));
283 print(_("^3bckills^7 Number of ball carrier kills\n"));
284 print(_("^3bctime^7 Total amount of time holding the ball in Keepaway\n"));
285 print(_("^3score^7 Total score\n\n"));
287 print(_("Before a field you can put a + or - sign, then a comma separated list\n"
288 "of game types, then a slash, to make the field show up only in these\n"
289 "or in all but these game types. You can also specify 'all' as a\n"
290 "field to show all fields available for the current game mode.\n\n"));
292 print(_("The special game type names 'teams' and 'noteams' can be used to\n"
293 "include/exclude ALL teams/noteams game modes.\n\n"));
295 print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
296 print(_("will display name, ping and pl aligned to the left, and the fields\n"
297 "right of the vertical bar aligned to the right.\n"));
298 print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
299 "other gamemodes except DM.\n"));
302 string HUD_DefaultColumnLayout()
304 return strcat( // fteqcc sucks
306 "-teams,race,lms/kills +freezetag/kills -teams,lms/deaths +freezetag/deaths -teams,lms,race,ka/suicides +freezetag/suicides -race,dm,tdm,ka,freezetag/frags ", // tdm already has this in "score"
307 "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ",
308 "+lms/lives +lms/rank ",
309 "+kh/caps +kh/pushes +kh/destroyed ",
310 "?+race/laps ?+race/time ?+race/fastest ",
311 "+as/objectives +nexball/faults +nexball/goals +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ",
312 "-lms,race,nexball/score");
315 void Cmd_HUD_SetFields(float argc)
319 float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
322 // TODO: re enable with gametype dependant cvars?
323 if(argc < 3) // no arguments provided
324 argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
327 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
331 if(argv(2) == "default")
332 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
333 else if(argv(2) == "all")
336 s = "ping pl name |";
337 for(i = 0; i < MAX_SCORE; ++i)
340 if(i != ps_secondary)
341 if(scores_label[i] != "")
342 s = strcat(s, " ", scores_label[i]);
344 if(ps_secondary != ps_primary)
345 s = strcat(s, " ", scores_label[ps_secondary]);
346 s = strcat(s, " ", scores_label[ps_primary]);
347 argc = tokenizebyseparator(strcat("0 1 ", s), " ");
354 hud_fontsize = HUD_GetFontsize("hud_fontsize");
356 draw_beginBoldFont();
357 for(i = 1; i < argc - 1; ++i)
363 if(substring(str, 0, 1) == "?")
366 str = substring(str, 1, strlen(str) - 1);
369 slash = strstrofs(str, "/", 0);
372 pattern = substring(str, 0, slash);
373 str = substring(str, slash + 1, strlen(str) - (slash + 1));
375 if not(isGametypeInFilter(gametype, teamplay, FALSE, pattern))
379 strunzone(hud_title[hud_num_fields]);
380 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
381 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
382 str = strtolower(str);
385 hud_field[hud_num_fields] = SP_PING;
386 } else if(str == "pl") {
387 hud_field[hud_num_fields] = SP_PL;
388 } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
389 hud_field[hud_num_fields] = SP_KDRATIO;
390 } else if(str == "name" || str == "nick") {
391 hud_field[hud_num_fields] = SP_NAME;
393 } else if(str == "|") {
394 hud_field[hud_num_fields] = SP_SEPARATOR;
397 for(j = 0; j < MAX_SCORE; ++j)
398 if(str == strtolower(scores_label[j]))
399 goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
408 print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
412 hud_field[hud_num_fields] = j;
415 if(j == ps_secondary)
419 if(hud_num_fields >= MAX_HUD_FIELDS)
423 if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
425 if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
427 if(ps_primary == ps_secondary)
429 missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
431 if(hud_num_fields+missing < MAX_HUD_FIELDS)
435 strunzone(hud_title[hud_num_fields]);
436 for(i = hud_num_fields; i > 0; --i)
438 hud_title[i] = hud_title[i-1];
439 hud_size[i] = hud_size[i-1];
440 hud_field[i] = hud_field[i-1];
442 hud_title[0] = strzone(TranslateScoresLabel("name"));
443 hud_field[0] = SP_NAME;
445 print(sprintf(_("fixed missing field '%s'\n"), "name"));
449 strunzone(hud_title[hud_num_fields]);
450 for(i = hud_num_fields; i > 1; --i)
452 hud_title[i] = hud_title[i-1];
453 hud_size[i] = hud_size[i-1];
454 hud_field[i] = hud_field[i-1];
456 hud_title[1] = strzone("|");
457 hud_field[1] = SP_SEPARATOR;
458 hud_size[1] = stringwidth("|", FALSE, hud_fontsize);
460 print(sprintf(_("fixed missing field '%s'\n"), "|"));
463 else if(!have_separator)
465 strunzone(hud_title[hud_num_fields]);
466 hud_title[hud_num_fields] = strzone("|");
467 hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize);
468 hud_field[hud_num_fields] = SP_SEPARATOR;
470 print(sprintf(_("fixed missing field '%s'\n"), "|"));
474 strunzone(hud_title[hud_num_fields]);
475 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
476 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
477 hud_field[hud_num_fields] = ps_secondary;
479 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_secondary]));
483 strunzone(hud_title[hud_num_fields]);
484 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
485 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
486 hud_field[hud_num_fields] = ps_primary;
488 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_primary]));
492 hud_field[hud_num_fields] = SP_END;
497 vector hud_field_rgb;
498 string hud_field_icon0;
499 string hud_field_icon1;
500 string hud_field_icon2;
501 vector hud_field_icon0_rgb;
502 vector hud_field_icon1_rgb;
503 vector hud_field_icon2_rgb;
504 float hud_field_icon0_alpha;
505 float hud_field_icon1_alpha;
506 float hud_field_icon2_alpha;
507 string HUD_GetField(entity pl, float field)
509 float tmp, num, denom, f;
511 hud_field_rgb = '1 1 1';
512 hud_field_icon0 = "";
513 hud_field_icon1 = "";
514 hud_field_icon2 = "";
515 hud_field_icon0_rgb = '1 1 1';
516 hud_field_icon1_rgb = '1 1 1';
517 hud_field_icon2_rgb = '1 1 1';
518 hud_field_icon0_alpha = 1;
519 hud_field_icon1_alpha = 1;
520 hud_field_icon2_alpha = 1;
525 return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
526 //str = getplayerkeyvalue(pl.sv_entnum, "ping");
530 tmp = max(0, min(220, f-80)) / 220;
531 hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
537 f = pl.ping_packetloss;
538 tmp = pl.ping_movementloss;
539 if(f == 0 && tmp == 0)
541 str = ftos(ceil(f * 100));
543 str = strcat(str, "~", ftos(ceil(tmp * 100)));
544 tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
545 hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
549 if(ready_waiting && pl.ready)
551 hud_field_icon0 = "gfx/scoreboard/player_ready";
555 f = stof(getplayerkeyvalue(pl.sv_entnum, "colors"));
557 hud_field_icon0 = "gfx/scoreboard/playercolor_base";
558 hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
559 hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
560 hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
561 hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
564 return GetPlayerName(pl.sv_entnum);
567 f = pl.(scores[SP_KILLS]);
568 f -= pl.(scores[SP_SUICIDES]);
572 num = pl.(scores[SP_KILLS]);
573 denom = pl.(scores[SP_DEATHS]);
576 hud_field_rgb = '0 1 0';
577 str = sprintf("%d", num);
578 } else if(num <= 0) {
579 hud_field_rgb = '1 0 0';
580 str = sprintf("%.1f", num/denom);
582 str = sprintf("%.1f", num/denom);
586 tmp = pl.(scores[field]);
587 f = scores_flags[field];
588 if(field == ps_primary)
589 hud_field_rgb = '1 1 0';
590 else if(field == ps_secondary)
591 hud_field_rgb = '0 1 1';
593 hud_field_rgb = '1 1 1';
594 return ScoreString(f, tmp);
599 float xmin, xmax, ymin, ymax, sbwidth;
600 float hud_fixscoreboardcolumnwidth_len;
601 float hud_fixscoreboardcolumnwidth_iconlen;
602 float hud_fixscoreboardcolumnwidth_marginlen;
604 string HUD_FixScoreboardColumnWidth(float i, string str)
608 field = hud_field[i];
610 hud_fixscoreboardcolumnwidth_iconlen = 0;
612 if(hud_field_icon0 != "")
614 sz = draw_getimagesize(hud_field_icon0);
616 if(hud_fixscoreboardcolumnwidth_iconlen < f)
617 hud_fixscoreboardcolumnwidth_iconlen = f;
620 if(hud_field_icon1 != "")
622 sz = draw_getimagesize(hud_field_icon1);
624 if(hud_fixscoreboardcolumnwidth_iconlen < f)
625 hud_fixscoreboardcolumnwidth_iconlen = f;
628 if(hud_field_icon2 != "")
630 sz = draw_getimagesize(hud_field_icon2);
632 if(hud_fixscoreboardcolumnwidth_iconlen < f)
633 hud_fixscoreboardcolumnwidth_iconlen = f;
636 hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize_y / hud_fontsize_x; // fix icon aspect
638 if(hud_fixscoreboardcolumnwidth_iconlen != 0)
639 hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", FALSE, hud_fontsize);
641 hud_fixscoreboardcolumnwidth_marginlen = 0;
643 if(field == SP_NAME) // name gets all remaining space
646 namesize = sbwidth;// / hud_fontsize_x;
647 for(j = 0; j < hud_num_fields; ++j)
649 if (hud_field[i] != SP_SEPARATOR)
650 namesize -= hud_size[j] + hud_fontsize_x;
651 namesize += hud_fontsize_x;
652 hud_size[i] = namesize;
654 if (hud_fixscoreboardcolumnwidth_iconlen != 0)
655 namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
656 str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
657 hud_fixscoreboardcolumnwidth_len = stringwidth(str, TRUE, hud_fontsize);
660 hud_fixscoreboardcolumnwidth_len = stringwidth(str, FALSE, hud_fontsize);
662 f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
669 void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
672 rgb = Team_ColorRGB(pl.team);
676 is_spec = (GetPlayerColor(pl.sv_entnum) == FL_SPECTATOR);
678 if((rgb == '1 1 1') && (!is_spec)) {
679 rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
680 rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
681 rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
685 tmp_y = hud_fontsize_y * 1.25;
688 // alternated rows highlighting
690 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
691 else if((scoreboard_highlight) && (!mod(pl_number,2)))
692 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
696 for(i = 0; i < hud_num_fields; ++i)
698 field = hud_field[i];
699 if(field == SP_SEPARATOR)
702 if(is_spec && field != SP_NAME && field != SP_PING) {
703 pos_x += hud_size[i] + hud_fontsize_x;
706 str = HUD_GetField(pl, field);
707 str = HUD_FixScoreboardColumnWidth(i, str);
709 pos_x += hud_size[i] + hud_fontsize_x;
711 if(field == SP_NAME) {
712 tmp_x = hud_size[i] - hud_fontsize_x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize_x;
714 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
716 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
718 tmp_x = hud_fixscoreboardcolumnwidth_len + hud_fontsize_x;
720 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
722 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
725 tmp_x = hud_size[i] + hud_fontsize_x;
726 if(hud_field_icon0 != "")
728 drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
730 drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
731 if(hud_field_icon1 != "")
733 drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
735 drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
736 if(hud_field_icon2 != "")
738 drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
740 drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
743 if(hud_field[i] == SP_SEPARATOR)
746 for(i = hud_num_fields-1; i > 0; --i)
748 field = hud_field[i];
749 if(field == SP_SEPARATOR)
752 if(is_spec && field != SP_NAME && field != SP_PING) {
753 pos_x -= hud_size[i] + hud_fontsize_x;
757 str = HUD_GetField(pl, field);
758 str = HUD_FixScoreboardColumnWidth(i, str);
760 if(field == SP_NAME) {
761 tmp_x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
763 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
765 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
767 tmp_x = hud_fixscoreboardcolumnwidth_len;
769 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
771 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
775 if(hud_field_icon0 != "")
777 drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
779 drawpic(pos - tmp, hud_field_icon0, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon0_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
780 if(hud_field_icon1 != "")
782 drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
784 drawpic(pos - tmp, hud_field_icon1, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon1_rgb, hud_field_icon1_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
785 if(hud_field_icon2 != "")
787 drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
789 drawpic(pos - tmp, hud_field_icon2, '0 1 0' * hud_fontsize_y + '1 0 0' * hud_fontsize_x * hud_fixscoreboardcolumnwidth_iconlen, hud_field_icon2_rgb, hud_field_icon2_alpha * scoreboard_alpha_name, DRAWFLAG_NORMAL);
790 pos_x -= hud_size[i] + hud_fontsize_x;
796 * HUD_Scoreboard_MakeTable
798 * Makes a table for a team (for all playing players in DM) and fills it
801 vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
803 float body_table_height, i;
804 vector tmp = '0 0 0', column_dim = '0 0 0';
807 body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
809 pos_y += autocvar_scoreboard_border_thickness;
813 tmp_y = 1.25 * hud_fontsize_y;
817 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
819 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
822 tmp_y += autocvar_scoreboard_border_thickness;
823 tmp_y += body_table_height;
824 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
826 // separator header/table
827 pos_y += 1.25 * hud_fontsize_y;
828 tmp_y = autocvar_scoreboard_border_thickness;
829 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
831 pos_y += autocvar_scoreboard_border_thickness;
834 tmp_y = body_table_height;
836 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
838 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
840 // anyway, apply some color
841 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
843 // go back to the top to make alternated columns highlighting and to print the strings
844 pos_y -= 1.25 * hud_fontsize_y;
845 pos_y -= autocvar_scoreboard_border_thickness;
849 if (scoreboard_highlight)
851 column_dim_y = 1.25 * hud_fontsize_y; // header
852 column_dim_y += autocvar_scoreboard_border_thickness;
853 column_dim_y += body_table_height;
856 // print the strings of the columns headers and draw the columns
857 draw_beginBoldFont();
858 for(i = 0; i < hud_num_fields; ++i)
860 if(hud_field[i] == SP_SEPARATOR)
862 column_dim_x = hud_size[i] + hud_fontsize_x;
863 if (scoreboard_highlight)
866 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
868 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
869 pos_x += column_dim_x;
871 if(hud_field[i] == SP_SEPARATOR)
875 for(i = hud_num_fields-1; i > 0; --i)
877 if(hud_field[i] == SP_SEPARATOR)
880 pos_x -= hud_size[i];
882 if (scoreboard_highlight)
886 if (i == hud_num_fields-1)
887 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
889 column_dim_x = hud_size[i] + hud_fontsize_x;
890 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
894 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
895 tmp_x = (hud_size[i] - tmp_x);
896 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
897 pos_x -= hud_fontsize_x;
903 pos_y += 1.25 * hud_fontsize_y; // skip the header
904 pos_y += autocvar_scoreboard_border_thickness;
906 // fill the table and draw the rows
909 for(pl = players.sort_next; pl; pl = pl.sort_next)
911 if(pl.team != tm.team)
913 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
914 pos_y += 1.25 * hud_fontsize_y;
918 for(pl = players.sort_next; pl; pl = pl.sort_next)
920 if(pl.team == FL_SPECTATOR)
922 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
923 pos_y += 1.25 * hud_fontsize_y;
928 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
929 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
934 float HUD_WouldDrawScoreboard() {
935 if (autocvar__hud_configure)
937 else if (scoreboard_showscores)
939 else if (intermission == 1)
941 else if (intermission == 2)
943 else if (spectatee_status != -1 && getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS)
945 else if (scoreboard_showscores_force)
951 float average_accuracy;
952 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
955 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
957 if(autocvar_scoreboard_accuracy_doublerows)
962 float fontsize = height * 1/3;
963 float weapon_height = height * 2/3;
964 float weapon_width = sbwidth / weapon_cnt;
966 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
967 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
968 vector tmp = '0 0 0';
970 tmp_y = height * rows;
973 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
975 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
976 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
978 // column highlighting
979 for(i = 0; i < weapon_cnt/rows; ++i)
982 drawfill(pos + '1 0 0' * weapon_width * rows * i, '0 1 0' * height * rows + '1 0 0' * weapon_width * rows, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
986 for(i = 0; i < rows; ++i)
988 drawfill(pos + '0 1 0' * weapon_height + '0 1 0' * height * i, '1 0 0' * sbwidth + '0 1 0' * fontsize, '1 1 1', scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
991 average_accuracy = 0;
992 float weapons_with_stats;
993 weapons_with_stats = 0;
995 pos_x += weapon_width / 2;
997 if(switchweapon == WEP_MINSTANEX)
998 g_minstagib = 1; // TODO: real detection for minstagib?
1001 if(autocvar_scoreboard_accuracy_nocolors)
1004 Accuracy_LoadColors();
1006 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
1008 self = get_weaponinfo(i);
1011 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
1013 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1016 if(weapon_stats >= 0)
1017 weapon_alpha = scoreboard_alpha_fg;
1019 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1022 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);
1024 if(weapon_stats >= 0) {
1025 weapons_with_stats += 1;
1026 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1029 s = sprintf(_("%d%%"), weapon_stats*100);
1032 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1034 if(!autocvar_scoreboard_accuracy_nocolors)
1035 rgb = Accuracy_GetColor(weapon_stats);
1037 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1039 pos_x += weapon_width * rows;
1040 if(rows == 2 && i == 6) {
1046 if(weapons_with_stats)
1047 average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5);
1050 pos_x -= weapon_width / 2;
1054 pos_y += 1.25 * hud_fontsize_y;
1058 vector HUD_DrawKeyValue(vector pos, string key, string value) {
1060 pos_x += hud_fontsize_x * 0.25;
1061 drawstring(pos, key, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1062 pos_x = xmax - stringwidth(value, FALSE, hud_fontsize) - hud_fontsize_x * 0.25;
1063 drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1065 pos_y+= hud_fontsize_y;
1070 vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
1071 float stat_secrets_found, stat_secrets_total;
1075 // get secrets stats
1076 stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
1077 stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
1079 // get number of rows
1080 rows = (stat_secrets_total ? 1 : 0);
1082 // if no rows, return
1086 // draw table header
1087 drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1088 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
1091 vector tmp = '0 0 0';
1093 tmp_y = hud_fontsize_y * rows;
1096 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1098 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1099 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1102 val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
1103 pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
1106 pos_y += 1.25 * hud_fontsize_y;
1111 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1114 RANKINGS_RECEIVED_CNT = 0;
1115 for (i=RANKINGS_CNT-1; i>=0; --i)
1117 ++RANKINGS_RECEIVED_CNT;
1119 if (RANKINGS_RECEIVED_CNT == 0)
1123 is_spec = (GetPlayerColor(pl.sv_entnum) == FL_SPECTATOR);
1125 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1126 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1127 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1129 pos_y += hud_fontsize_y;
1130 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1131 pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness;
1132 vector tmp = '0 0 0';
1134 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1137 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1139 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1140 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1143 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1150 n = grecordholder[i];
1151 p = race_PlaceName(i+1);
1152 if(grecordholder[i] == GetPlayerName(player_localnum))
1153 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1154 else if(!mod(i, 2) && scoreboard_highlight)
1155 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1156 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1157 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);
1158 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1159 pos_y += 1.25 * hud_fontsize_y;
1161 pos_y += autocvar_scoreboard_border_thickness;
1166 float hud_woulddrawscoreboard_prev;
1167 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1168 void HUD_DrawScoreboard()
1170 float hud_woulddrawscoreboard;
1171 hud_woulddrawscoreboard = scoreboard_active;
1172 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1173 hud_woulddrawscoreboard_change = time;
1174 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1177 if(hud_woulddrawscoreboard) {
1178 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1179 if (scoreboard_fadeinspeed)
1180 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1182 scoreboard_fade_alpha = 1;
1185 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1186 if (scoreboard_fadeoutspeed)
1187 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1189 scoreboard_fade_alpha = 0;
1192 if not(scoreboard_fade_alpha)
1195 HUD_UpdatePlayerTeams();
1197 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1198 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1199 scoreboard_highlight = autocvar_scoreboard_highlight;
1200 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1201 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1202 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1203 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1205 vector rgb, pos, tmp;
1209 xmin = (autocvar_scoreboard_offset_left * vid_conwidth);
1210 ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth));
1212 xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth);
1213 ymax = (vid_conheight - ymin);
1215 sbwidth = xmax - xmin;
1217 // Initializes position
1223 vector sb_heading_fontsize;
1224 sb_heading_fontsize = hud_fontsize * 2;
1225 draw_beginBoldFont();
1226 drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1229 pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25;
1231 // Draw the scoreboard
1232 vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1236 vector team_score_baseoffset;
1237 team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25);
1238 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1240 if(tm.team == FL_SPECTATOR)
1243 draw_beginBoldFont();
1244 rgb = Team_ColorRGB(tm.team);
1245 str = ftos(tm.(teamscores[ts_primary]));
1246 drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1248 if(ts_primary != ts_secondary)
1250 str = ftos(tm.(teamscores[ts_secondary]));
1251 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);
1255 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1261 rgb_x = autocvar_scoreboard_color_bg_r;
1262 rgb_y = autocvar_scoreboard_color_bg_g;
1263 rgb_z = autocvar_scoreboard_color_bg_b;
1270 rgb_x = autocvar_scoreboard_color_bg_r;
1271 rgb_y = autocvar_scoreboard_color_bg_g;
1272 rgb_z = autocvar_scoreboard_color_bg_b;
1274 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1276 if(tm.team == FL_SPECTATOR)
1279 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1283 if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) {
1284 if(race_speedaward) {
1285 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1286 pos_y += 1.25 * hud_fontsize_y;
1288 if(race_speedaward_alltimebest) {
1289 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1290 pos_y += 1.25 * hud_fontsize_y;
1292 pos = HUD_DrawScoreboardRankings(pos, playerslots[player_localnum], rgb, bg_size);
1294 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1296 pos = HUD_DrawScoreboardAccuracyStats(pos, Team_ColorRGB(myteam), bg_size);
1298 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1303 pos = HUD_DrawMapStats(pos, Team_ColorRGB(myteam), bg_size);
1305 pos = HUD_DrawMapStats(pos, rgb, bg_size);
1311 for(pl = players.sort_next; pl; pl = pl.sort_next)
1313 if(pl.team != FL_SPECTATOR)
1315 pos_y += 1.25 * hud_fontsize_y;
1316 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
1322 draw_beginBoldFont();
1323 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1325 pos_y += 1.25 * hud_fontsize_y;
1328 // Print info string
1330 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1331 tl = getstatf(STAT_TIMELIMIT);
1332 fl = getstatf(STAT_FRAGLIMIT);
1333 ll = getstatf(STAT_LEADLIMIT);
1334 if(gametype == MAPINFO_TYPE_LMS)
1337 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1342 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1346 str = strcat(str, _(" or"));
1349 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1350 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1351 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1352 TranslateScoresLabel(teamscores_label[ts_primary])));
1356 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1357 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1358 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1359 TranslateScoresLabel(scores_label[ps_primary])));
1364 if(tl > 0 || fl > 0)
1365 str = strcat(str, _(" or"));
1368 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1369 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1370 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1371 TranslateScoresLabel(teamscores_label[ts_primary])));
1375 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1376 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1377 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1378 TranslateScoresLabel(scores_label[ps_primary])));
1383 pos_y += 1.2 * hud_fontsize_y;
1384 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1386 // print information about respawn status
1387 float respawn_time = getstatf(STAT_RESPAWN_TIME);
1390 if(respawn_time < 0)
1392 // a negative number means we are awaiting respawn, time value is still the same
1393 respawn_time *= -1; // remove mark now that we checked it
1394 respawn_time = max(time, respawn_time); // don't show a negative value while the server is respawning the player (lag)
1396 str = sprintf(_("^1Respawning in ^3%s^1 seconds..."), ftos_decimals(respawn_time - time, autocvar_scoreboard_respawntime_decimals));
1398 else if(time < respawn_time)
1399 str = sprintf(_("You are dead, wait ^3%s^7 seconds before respawning"), ftos_decimals(respawn_time - time, autocvar_scoreboard_respawntime_decimals));
1400 else if(time >= respawn_time)
1401 str = sprintf(_("You are dead, press ^2%s^7 to respawn"), getcommandkey("jump", "+jump"));
1403 pos_y += 1.2 * hud_fontsize_y;
1404 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1407 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;