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]);
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 == COLOR_SPECTATOR)
212 if(right.team == COLOR_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 = GetTeamRGB(pl.team);
676 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_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 == COLOR_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?
1004 else if (acc_col[0] == '-1 0 0')
1005 for (i = 0; i < acc_levels; ++i)
1006 acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i))));
1008 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
1010 self = get_weaponinfo(i);
1013 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
1015 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1018 if(weapon_stats >= 0)
1019 weapon_alpha = scoreboard_alpha_fg;
1021 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1024 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);
1026 if(weapon_stats >= 0) {
1027 weapons_with_stats += 1;
1028 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1031 s = sprintf(_("%d%%"), weapon_stats*100);
1034 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1038 // find the max level lower than weapon_stats
1041 while ( j && weapon_stats < acc_lev[j] )
1044 // inject color j+1 in color j, how much depending on how much weapon_stats is higher than level j
1046 factor = (weapon_stats - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
1048 rgb = rgb + factor * (acc_col[j+1] - rgb);
1051 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1053 pos_x += weapon_width * rows;
1054 if(rows == 2 && i == 6) {
1060 if(weapons_with_stats)
1061 average_accuracy = floor(average_accuracy / weapons_with_stats);
1064 pos_x -= weapon_width / 2;
1068 pos_y += 1.25 * hud_fontsize_y;
1072 vector HUD_DrawKeyValue(vector pos, string key, string value) {
1074 pos_x += hud_fontsize_x * 0.25;
1075 drawstring(pos, key, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1076 pos_x = xmax - stringwidth(value, FALSE, hud_fontsize) - hud_fontsize_x * 0.25;
1077 drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1079 pos_y+= hud_fontsize_y;
1084 vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
1085 float stat_secrets_found, stat_secrets_total;
1089 // get secrets stats
1090 stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
1091 stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
1093 // get number of rows
1094 rows = (stat_secrets_total ? 1 : 0);
1096 // if no rows, return
1100 // draw table header
1101 drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1102 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
1105 vector tmp = '0 0 0';
1107 tmp_y = hud_fontsize_y * rows;
1110 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1112 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1113 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1116 val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
1117 pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
1120 pos_y += 1.25 * hud_fontsize_y;
1125 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1128 RANKINGS_RECEIVED_CNT = 0;
1129 for (i=RANKINGS_CNT-1; i>=0; --i)
1131 ++RANKINGS_RECEIVED_CNT;
1133 if (RANKINGS_RECEIVED_CNT == 0)
1137 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
1139 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1140 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1141 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1143 pos_y += hud_fontsize_y;
1144 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1145 pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness;
1146 vector tmp = '0 0 0';
1148 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1151 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1153 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1154 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1157 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1164 n = grecordholder[i];
1165 p = race_PlaceName(i+1);
1166 if(grecordholder[i] == GetPlayerName(player_localnum))
1167 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1168 else if(!mod(i, 2) && scoreboard_highlight)
1169 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1170 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1171 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);
1172 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1173 pos_y += 1.25 * hud_fontsize_y;
1175 pos_y += autocvar_scoreboard_border_thickness;
1180 float hud_woulddrawscoreboard_prev;
1181 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1182 void HUD_DrawScoreboard()
1184 float hud_woulddrawscoreboard;
1185 hud_woulddrawscoreboard = scoreboard_active;
1186 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1187 hud_woulddrawscoreboard_change = time;
1188 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1191 if(hud_woulddrawscoreboard) {
1192 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1193 if (scoreboard_fadeinspeed)
1194 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1196 scoreboard_fade_alpha = 1;
1199 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1200 if (scoreboard_fadeoutspeed)
1201 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1203 scoreboard_fade_alpha = 0;
1206 if not(scoreboard_fade_alpha)
1209 HUD_UpdatePlayerTeams();
1211 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1212 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1213 scoreboard_highlight = autocvar_scoreboard_highlight;
1214 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1215 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1216 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1217 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1219 vector rgb, pos, tmp;
1223 xmin = (autocvar_scoreboard_offset_left * vid_conwidth);
1224 ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth));
1226 xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth);
1227 ymax = (vid_conheight - ymin);
1229 sbwidth = xmax - xmin;
1231 // Initializes position
1237 vector sb_heading_fontsize;
1238 sb_heading_fontsize = hud_fontsize * 2;
1239 draw_beginBoldFont();
1240 drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1243 pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25;
1245 // Draw the scoreboard
1246 vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1250 vector team_score_baseoffset;
1251 team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25);
1252 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1254 if(tm.team == COLOR_SPECTATOR)
1257 draw_beginBoldFont();
1258 rgb = GetTeamRGB(tm.team);
1259 str = ftos(tm.(teamscores[ts_primary]));
1260 drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1262 if(ts_primary != ts_secondary)
1264 str = ftos(tm.(teamscores[ts_secondary]));
1265 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);
1269 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1275 rgb_x = autocvar_scoreboard_color_bg_r;
1276 rgb_y = autocvar_scoreboard_color_bg_g;
1277 rgb_z = autocvar_scoreboard_color_bg_b;
1284 rgb_x = autocvar_scoreboard_color_bg_r;
1285 rgb_y = autocvar_scoreboard_color_bg_g;
1286 rgb_z = autocvar_scoreboard_color_bg_b;
1288 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1290 if(tm.team == COLOR_SPECTATOR)
1293 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1297 if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) {
1298 if(race_speedaward) {
1299 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1300 pos_y += 1.25 * hud_fontsize_y;
1302 if(race_speedaward_alltimebest) {
1303 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1304 pos_y += 1.25 * hud_fontsize_y;
1306 pos = HUD_DrawScoreboardRankings(pos, playerslots[player_localnum], rgb, bg_size);
1308 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1310 pos = HUD_DrawScoreboardAccuracyStats(pos, GetTeamRGB(myteam), bg_size);
1312 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1317 pos = HUD_DrawMapStats(pos, GetTeamRGB(myteam), bg_size);
1319 pos = HUD_DrawMapStats(pos, rgb, bg_size);
1325 for(pl = players.sort_next; pl; pl = pl.sort_next)
1327 if(pl.team != COLOR_SPECTATOR)
1329 pos_y += 1.25 * hud_fontsize_y;
1330 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
1336 draw_beginBoldFont();
1337 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1339 pos_y += 1.25 * hud_fontsize_y;
1342 // Print info string
1344 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1345 tl = getstatf(STAT_TIMELIMIT);
1346 fl = getstatf(STAT_FRAGLIMIT);
1347 ll = getstatf(STAT_LEADLIMIT);
1348 if(gametype == MAPINFO_TYPE_LMS)
1351 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1356 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1360 str = strcat(str, _(" or"));
1363 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1364 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1365 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1366 TranslateScoresLabel(teamscores_label[ts_primary])));
1370 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1371 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1372 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1373 TranslateScoresLabel(scores_label[ps_primary])));
1378 if(tl > 0 || fl > 0)
1379 str = strcat(str, _(" or"));
1382 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1383 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1384 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1385 TranslateScoresLabel(teamscores_label[ts_primary])));
1389 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1390 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1391 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1392 TranslateScoresLabel(scores_label[ps_primary])));
1397 pos_y += 1.2 * hud_fontsize_y;
1398 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1400 // print information about respawn status
1401 float respawn_time = getstatf(STAT_RESPAWN_TIME);
1404 if(respawn_time < 0)
1406 // a negative number means we are awaiting respawn, time value is still the same
1407 respawn_time *= -1; // remove mark now that we checked it
1408 respawn_time = max(time, respawn_time); // don't show a negative value while the server is respawning the player (lag)
1410 str = sprintf(_("^1Respawning in ^3%s^1 seconds..."), ftos_decimals(respawn_time - time, autocvar_scoreboard_respawntime_decimals));
1412 else if(time < respawn_time)
1413 str = sprintf(_("You are dead, wait ^3%s^7 seconds before respawning"), ftos_decimals(respawn_time - time, autocvar_scoreboard_respawntime_decimals));
1414 else if(time >= respawn_time)
1415 str = sprintf(_("You are dead, press ^2%s^7 to respawn"), getcommandkey("jump", "+jump"));
1417 pos_y += 1.2 * hud_fontsize_y;
1418 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1421 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;