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 "deaths": return CTX(_("SCO^deaths"));
23 case "destroyed": return CTX(_("SCO^destroyed"));
24 case "drops": return CTX(_("SCO^drops"));
25 case "faults": return CTX(_("SCO^faults"));
26 case "fckills": return CTX(_("SCO^fckills"));
27 case "goals": return CTX(_("SCO^goals"));
28 case "kckills": return CTX(_("SCO^kckills"));
29 case "kdratio": return CTX(_("SCO^kdratio"));
30 case "k/d": return CTX(_("SCO^k/d"));
31 case "kd": return CTX(_("SCO^kd"));
32 case "kdr": return CTX(_("SCO^kdr"));
33 case "kills": return CTX(_("SCO^kills"));
34 case "laps": return CTX(_("SCO^laps"));
35 case "lives": return CTX(_("SCO^lives"));
36 case "losses": return CTX(_("SCO^losses"));
37 case "name": return CTX(_("SCO^name"));
38 case "nick": return CTX(_("SCO^nick"));
39 case "objectives": return CTX(_("SCO^objectives"));
40 case "pickups": return CTX(_("SCO^pickups"));
41 case "ping": return CTX(_("SCO^ping"));
42 case "pl": return CTX(_("SCO^pl"));
43 case "pushes": return CTX(_("SCO^pushes"));
44 case "rank": return CTX(_("SCO^rank"));
45 case "returns": return CTX(_("SCO^returns"));
46 case "revivals": return CTX(_("SCO^revivals"));
47 case "score": return CTX(_("SCO^score"));
48 case "suicides": return CTX(_("SCO^suicides"));
49 case "takes": return CTX(_("SCO^takes"));
50 case "ticks": return CTX(_("SCO^ticks"));
56 void HUD_FinaleOverlay()
59 pos_x = (vid_conwidth - 1)/2;
63 //drawpic(pos, "gfx/finale", '0 0 0', '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
65 //drawstring(pos, "END", hud_fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
69 void Cmd_HUD_SetFields(float argc);
74 ps_primary = ps_secondary = ts_primary = ts_secondary = -1;
75 for(i = 0; i < MAX_SCORE; ++i)
77 f = (scores_flags[i] & SFL_SORT_PRIO_MASK);
78 if(f == SFL_SORT_PRIO_PRIMARY)
80 if(f == SFL_SORT_PRIO_SECONDARY)
83 if(ps_secondary == -1)
84 ps_secondary = ps_primary;
86 for(i = 0; i < MAX_TEAMSCORE; ++i)
88 f = (teamscores_flags[i] & SFL_SORT_PRIO_MASK);
89 if(f == SFL_SORT_PRIO_PRIMARY)
91 if(f == SFL_SORT_PRIO_SECONDARY)
94 if(ts_secondary == -1)
95 ts_secondary = ts_primary;
100 void HUD_UpdatePlayerPos(entity pl);
101 float SetTeam(entity pl, float Team);
103 void HUD_UpdatePlayerTeams()
110 for(pl = players.sort_next; pl; pl = pl.sort_next)
113 Team = GetPlayerColor(pl.sv_entnum);
114 if(SetTeam(pl, Team))
117 HUD_UpdatePlayerPos(pl);
121 pl = players.sort_next;
126 print(strcat("PNUM: ", ftos(num), "\n"));
131 float HUD_ComparePlayerScores(entity left, entity right)
134 vl = GetPlayerColor(left.sv_entnum);
135 vr = GetPlayerColor(right.sv_entnum);
138 vl = COLOR_SPECTATOR;
140 vr = COLOR_SPECTATOR;
147 if(vl == COLOR_SPECTATOR)
149 // FIRST the one with scores (spectators), THEN the ones without (downloaders)
151 if(!left.gotscores && right.gotscores)
156 vl = left.scores[ps_primary];
157 vr = right.scores[ps_primary];
158 if(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)
160 if(vl == 0 && vr != 0)
162 if(vl != 0 && vr == 0)
166 return IS_INCREASING(scores_flags[ps_primary]);
168 return IS_DECREASING(scores_flags[ps_primary]);
170 vl = left.scores[ps_secondary];
171 vr = right.scores[ps_secondary];
172 if(scores_flags[ps_secondary] & SFL_ZERO_IS_WORST)
174 if(vl == 0 && vr != 0)
176 if(vl != 0 && vr == 0)
180 return IS_INCREASING(scores_flags[ps_secondary]);
182 return IS_DECREASING(scores_flags[ps_secondary]);
187 void HUD_UpdatePlayerPos(entity player)
189 for(other = player.sort_next; other && HUD_ComparePlayerScores(player, other); other = player.sort_next)
191 SORT_SWAP(player, other);
193 for(other = player.sort_prev; other != players && HUD_ComparePlayerScores(other, player); other = player.sort_prev)
195 SORT_SWAP(other, player);
199 float HUD_CompareTeamScores(entity left, entity right)
203 if(left.team == COLOR_SPECTATOR)
205 if(right.team == COLOR_SPECTATOR)
208 vl = left.teamscores[ts_primary];
209 vr = right.teamscores[ts_primary];
211 return IS_INCREASING(teamscores_flags[ts_primary]);
213 return IS_DECREASING(teamscores_flags[ts_primary]);
215 vl = left.teamscores[ts_secondary];
216 vr = right.teamscores[ts_secondary];
218 return IS_INCREASING(teamscores_flags[ts_secondary]);
220 return IS_DECREASING(teamscores_flags[ts_secondary]);
225 void HUD_UpdateTeamPos(entity Team)
227 for(other = Team.sort_next; other && HUD_CompareTeamScores(Team, other); other = Team.sort_next)
229 SORT_SWAP(Team, other);
231 for(other = Team.sort_prev; other != teams && HUD_CompareTeamScores(other, Team); other = Team.sort_prev)
233 SORT_SWAP(other, Team);
237 void Cmd_HUD_Help(float argc)
239 print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
240 print(_("^3|---------------------------------------------------------------|\n"));
241 print(_("Usage:\n"));
242 print(_("^2scoreboard_columns_set default\n"));
243 print(_("^2scoreboard_columns_set ^7filed1 field2 ...\n"));
244 print(_("The following field names are recognized (case insensitive):\n"));
245 print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
247 print(_("^3name^7 or ^3nick^7 Name of a player\n"));
248 print(_("^3ping^7 Ping time\n"));
249 print(_("^3pl^7 Packet loss\n"));
250 print(_("^3kills^7 Number of kills\n"));
251 print(_("^3deaths^7 Number of deaths\n"));
252 print(_("^3suicides^7 Number of suicides\n"));
253 print(_("^3frags^7 kills - suicides\n"));
254 print(_("^3kd^7 The kill-death ratio\n"));
255 print(_("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n"));
256 print(_("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
257 print(_("^3fckills^7 Number of flag carrier kills\n"));
258 print(_("^3returns^7 Number of flag returns\n"));
259 print(_("^3drops^7 Number of flag drops\n"));
260 print(_("^3lives^7 Number of lives (LMS)\n"));
261 print(_("^3rank^7 Player rank\n"));
262 print(_("^3pushes^7 Number of players pushed into void\n"));
263 print(_("^3destroyed^7 Number of keys destroyed by pushing them into void\n"));
264 print(_("^3kckills^7 Number of keys carrier kills\n"));
265 print(_("^3losses^7 Number of times a key was lost\n"));
266 print(_("^3laps^7 Number of laps finished (race/cts)\n"));
267 print(_("^3time^7 Total time raced (race/cts)\n"));
268 print(_("^3fastest^7 Time of fastest lap (race/cts)\n"));
269 print(_("^3ticks^7 Number of ticks (DOM)\n"));
270 print(_("^3takes^7 Number of domination points taken (DOM)\n"));
271 print(_("^3bckills^7 Number of ball carrier kills\n"));
272 print(_("^3bctime^7 Total amount of time holding the ball in Keepaway\n"));
273 print(_("^3score^7 Total score\n\n"));
275 print(_("Before a field you can put a + or - sign, then a comma separated list\n"
276 "of game types, then a slash, to make the field show up only in these\n"
277 "or in all but these game types. You can also specify 'all' as a\n"
278 "field to show all fields available for the current game mode.\n\n"));
280 print(_("The special game type names 'teams' and 'noteams' can be used to\n"
281 "include/exclude ALL teams/noteams game modes.\n\n"));
283 print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
284 print(_("will display name, ping and pl aligned to the left, and the fields\n"
285 "right of the vertical bar aligned to the right.\n"));
286 print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
287 "other gamemodes except DM.\n"));
290 string HUD_DefaultColumnLayout()
292 return strcat( // fteqcc sucks
294 "-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"
295 "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ",
296 "+lms/lives +lms/rank ",
297 "+kh/caps +kh/pushes +kh/destroyed ",
298 "?+race/laps ?+race/time ?+race/fastest ",
299 "+as/objectives +nexball/faults +nexball/goals +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ",
300 "-lms,race,nexball/score");
303 void Cmd_HUD_SetFields(float argc)
307 float have_name, have_primary, have_secondary, have_separator;
310 // TODO: re enable with gametype dependant cvars?
311 if(argc < 2) // no arguments provided
312 argc = tokenizebyseparator(strcat("x ", autocvar_scoreboard_columns), " ");
315 argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
319 if(argv(1) == "default")
320 argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
321 else if(argv(1) == "all")
324 s = "ping pl color name |";
325 for(i = 0; i < MAX_SCORE; ++i)
328 if(i != ps_secondary)
329 if(scores_label[i] != "")
330 s = strcat(s, " ", scores_label[i]);
332 if(ps_secondary != ps_primary)
333 s = strcat(s, " ", scores_label[ps_secondary]);
334 s = strcat(s, " ", scores_label[ps_primary]);
335 argc = tokenizebyseparator(strcat("x ", s), " ");
342 hud_fontsize = HUD_GetFontsize("hud_fontsize");
344 for(i = 0; i < argc - 1; ++i)
350 if(substring(str, 0, 1) == "?")
353 str = substring(str, 1, strlen(str) - 1);
356 slash = strstrofs(str, "/", 0);
359 pattern = substring(str, 0, slash);
360 str = substring(str, slash + 1, strlen(str) - (slash + 1));
362 if not(isGametypeInFilter(gametype, teamplay, FALSE, pattern))
366 strunzone(hud_title[hud_num_fields]);
367 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
368 hud_size[hud_num_fields] = stringwidth(str, FALSE, hud_fontsize);
369 str = strtolower(str);
372 hud_field[hud_num_fields] = SP_PING;
373 } else if(str == "pl") {
374 hud_field[hud_num_fields] = SP_PL;
375 } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
376 hud_field[hud_num_fields] = SP_KDRATIO;
377 } else if(str == "name" || str == "nick") {
378 hud_field[hud_num_fields] = SP_NAME;
380 } else if(str == "|") {
381 hud_field[hud_num_fields] = SP_SEPARATOR;
384 for(j = 0; j < MAX_SCORE; ++j)
385 if(str == strtolower(scores_label[j]))
386 goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
395 print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
399 hud_field[hud_num_fields] = j;
402 if(j == ps_secondary)
406 if(hud_num_fields >= MAX_HUD_FIELDS)
410 if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
412 if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
414 if(ps_primary == ps_secondary)
416 missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
418 if(hud_num_fields+missing < MAX_HUD_FIELDS)
422 strunzone(hud_title[hud_num_fields]);
423 for(i = hud_num_fields; i > 0; --i)
425 hud_title[i] = hud_title[i-1];
426 hud_size[i] = hud_size[i-1];
427 hud_field[i] = hud_field[i-1];
429 hud_title[0] = strzone(TranslateScoresLabel("name"));
430 hud_field[0] = SP_NAME;
432 print(sprintf(_("fixed missing field '%s'\n"), "name"));
436 strunzone(hud_title[hud_num_fields]);
437 for(i = hud_num_fields; i > 1; --i)
439 hud_title[i] = hud_title[i-1];
440 hud_size[i] = hud_size[i-1];
441 hud_field[i] = hud_field[i-1];
443 hud_title[1] = strzone("|");
444 hud_field[1] = SP_SEPARATOR;
445 hud_size[1] = stringwidth("|", FALSE, hud_fontsize);
447 print(sprintf(_("fixed missing field '%s'\n"), "|"));
450 else if(!have_separator)
452 strunzone(hud_title[hud_num_fields]);
453 hud_title[hud_num_fields] = strzone("|");
454 hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize);
455 hud_field[hud_num_fields] = SP_SEPARATOR;
457 print(sprintf(_("fixed missing field '%s'\n"), "|"));
461 strunzone(hud_title[hud_num_fields]);
462 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
463 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
464 hud_field[hud_num_fields] = ps_secondary;
466 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_secondary]));
470 strunzone(hud_title[hud_num_fields]);
471 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
472 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
473 hud_field[hud_num_fields] = ps_primary;
475 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_primary]));
479 hud_field[hud_num_fields] = SP_END;
483 vector hud_field_rgb;
484 string hud_field_icon0;
485 string hud_field_icon1;
486 string hud_field_icon2;
487 vector hud_field_icon0_rgb;
488 vector hud_field_icon1_rgb;
489 vector hud_field_icon2_rgb;
490 float hud_field_icon0_alpha;
491 float hud_field_icon1_alpha;
492 float hud_field_icon2_alpha;
493 string HUD_GetField(entity pl, float field)
495 float tmp, num, denom, f;
497 hud_field_rgb = '1 1 1';
498 hud_field_icon0 = "";
499 hud_field_icon1 = "";
500 hud_field_icon2 = "";
501 hud_field_icon0_rgb = '1 1 1';
502 hud_field_icon1_rgb = '1 1 1';
503 hud_field_icon2_rgb = '1 1 1';
504 hud_field_icon0_alpha = 1;
505 hud_field_icon1_alpha = 1;
506 hud_field_icon2_alpha = 1;
511 return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
512 //str = getplayerkey(pl.sv_entnum, "ping");
516 tmp = max(0, min(220, f-80)) / 220;
517 hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
523 f = pl.ping_packetloss;
524 tmp = pl.ping_movementloss;
525 if(f == 0 && tmp == 0)
527 str = ftos(ceil(f * 100));
529 str = strcat(str, "~", ftos(ceil(tmp * 100)));
530 tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
531 hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
535 if(ready_waiting && pl.ready)
537 hud_field_icon0 = "gfx/scoreboard/player_ready";
541 f = stof(getplayerkey(pl.sv_entnum, "colors"));
543 hud_field_icon0 = "gfx/scoreboard/playercolor_base";
544 hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
545 hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
546 hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
547 hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
550 return GetPlayerName(pl.sv_entnum);
553 f = pl.(scores[SP_KILLS]);
554 f -= pl.(scores[SP_SUICIDES]);
558 num = pl.(scores[SP_KILLS]);
559 denom = pl.(scores[SP_DEATHS]);
562 hud_field_rgb = '0 1 0';
563 str = sprintf("%d", num);
564 } else if(num <= 0) {
565 hud_field_rgb = '1 0 0';
566 str = sprintf("%.1f", num/denom);
568 str = sprintf("%.1f", num/denom);
572 tmp = pl.(scores[field]);
573 f = scores_flags[field];
574 if(field == ps_primary)
575 hud_field_rgb = '1 1 0';
576 else if(field == ps_secondary)
577 hud_field_rgb = '0 1 1';
579 hud_field_rgb = '1 1 1';
580 return ScoreString(f, tmp);
585 float xmin, xmax, ymin, ymax, sbwidth;
586 float hud_fixscoreboardcolumnwidth_len;
587 float hud_fixscoreboardcolumnwidth_iconlen;
588 float hud_fixscoreboardcolumnwidth_marginlen;
590 string HUD_FixScoreboardColumnWidth(float i, string str)
594 field = hud_field[i];
596 hud_fixscoreboardcolumnwidth_iconlen = 0;
598 if(hud_field_icon0 != "")
600 sz = drawgetimagesize(hud_field_icon0);
602 if(hud_fixscoreboardcolumnwidth_iconlen < f)
603 hud_fixscoreboardcolumnwidth_iconlen = f;
606 if(hud_field_icon1 != "")
608 sz = drawgetimagesize(hud_field_icon1);
610 if(hud_fixscoreboardcolumnwidth_iconlen < f)
611 hud_fixscoreboardcolumnwidth_iconlen = f;
614 if(hud_field_icon2 != "")
616 sz = drawgetimagesize(hud_field_icon2);
618 if(hud_fixscoreboardcolumnwidth_iconlen < f)
619 hud_fixscoreboardcolumnwidth_iconlen = f;
622 hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize_y / hud_fontsize_x; // fix icon aspect
624 if(hud_fixscoreboardcolumnwidth_iconlen != 0)
625 hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", FALSE, hud_fontsize);
627 hud_fixscoreboardcolumnwidth_marginlen = 0;
629 if(field == SP_NAME) // name gets all remaining space
632 namesize = sbwidth;// / hud_fontsize_x;
633 for(j = 0; j < hud_num_fields; ++j)
635 if (hud_field[i] != SP_SEPARATOR)
636 namesize -= hud_size[j] + hud_fontsize_x;
637 namesize += hud_fontsize_x;
638 hud_size[i] = namesize;
640 if (hud_fixscoreboardcolumnwidth_iconlen != 0)
641 namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
642 str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
643 hud_fixscoreboardcolumnwidth_len = stringwidth(str, TRUE, hud_fontsize);
646 hud_fixscoreboardcolumnwidth_len = stringwidth(str, FALSE, hud_fontsize);
648 f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
655 void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
658 rgb = GetTeamRGB(pl.team);
662 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
664 if((rgb == '1 1 1') && (!is_spec)) {
665 rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
666 rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
667 rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
671 tmp_y = hud_fontsize_y * 1.25;
674 // alternated rows highlighting
676 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
677 else if((scoreboard_highlight) && (!mod(pl_number,2)))
678 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
682 for(i = 0; i < hud_num_fields; ++i)
684 field = hud_field[i];
685 if(field == SP_SEPARATOR)
688 if(is_spec && field != SP_NAME && field != SP_PING) {
689 pos_x += hud_size[i] + hud_fontsize_x;
692 str = HUD_GetField(pl, field);
693 str = HUD_FixScoreboardColumnWidth(i, str);
695 pos_x += hud_size[i] + hud_fontsize_x;
697 if(field == SP_NAME) {
698 tmp_x = hud_size[i] - hud_fontsize_x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize_x;
700 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
702 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
704 tmp_x = hud_fixscoreboardcolumnwidth_len + hud_fontsize_x;
706 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
708 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
711 tmp_x = hud_size[i] + hud_fontsize_x;
712 if(hud_field_icon0 != "")
714 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);
716 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);
717 if(hud_field_icon1 != "")
719 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);
721 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);
722 if(hud_field_icon2 != "")
724 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);
726 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);
729 if(hud_field[i] == SP_SEPARATOR)
732 for(i = hud_num_fields-1; i > 0; --i)
734 field = hud_field[i];
735 if(field == SP_SEPARATOR)
738 if(is_spec && field != SP_NAME && field != SP_PING) {
739 pos_x -= hud_size[i] + hud_fontsize_x;
743 str = HUD_GetField(pl, field);
744 str = HUD_FixScoreboardColumnWidth(i, str);
746 if(field == SP_NAME) {
747 tmp_x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
749 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
751 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
753 tmp_x = hud_fixscoreboardcolumnwidth_len;
755 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
757 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
761 if(hud_field_icon0 != "")
763 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);
765 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);
766 if(hud_field_icon1 != "")
768 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);
770 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);
771 if(hud_field_icon2 != "")
773 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);
775 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);
776 pos_x -= hud_size[i] + hud_fontsize_x;
782 * HUD_Scoreboard_MakeTable
784 * Makes a table for a team (for all playing players in DM) and fills it
787 vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
789 float body_table_height, i;
790 vector tmp, column_dim;
793 body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
798 tmp_y = 1.25 * hud_fontsize_y;
802 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
804 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
807 tmp_y += autocvar_scoreboard_border_thickness;
808 tmp_y += body_table_height;
809 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
811 // separator header/table
812 pos_y += 1.25 * hud_fontsize_y;
813 tmp_y = autocvar_scoreboard_border_thickness;
814 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
816 pos_y += autocvar_scoreboard_border_thickness;
819 tmp_y = body_table_height;
821 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
823 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
825 // anyway, apply some color
826 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
828 // go back to the top to make alternated columns highlighting and to print the strings
829 pos_y -= 1.25 * hud_fontsize_y;
830 pos_y -= autocvar_scoreboard_border_thickness;
834 if (scoreboard_highlight)
836 column_dim_y = 1.25 * hud_fontsize_y; // header
837 column_dim_y += autocvar_scoreboard_border_thickness;
838 column_dim_y += body_table_height;
841 // print the strings of the columns headers and draw the columns
842 for(i = 0; i < hud_num_fields; ++i)
844 if(hud_field[i] == SP_SEPARATOR)
846 column_dim_x = hud_size[i] + hud_fontsize_x;
847 if (scoreboard_highlight)
850 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
852 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
853 pos_x += column_dim_x;
855 if(hud_field[i] == SP_SEPARATOR)
859 for(i = hud_num_fields-1; i > 0; --i)
861 if(hud_field[i] == SP_SEPARATOR)
864 pos_x -= hud_size[i];
866 if (scoreboard_highlight)
870 if (i == hud_num_fields-1)
871 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
873 column_dim_x = hud_size[i] + hud_fontsize_x;
874 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
878 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
879 tmp_x = (hud_size[i] - tmp_x);
880 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
881 pos_x -= hud_fontsize_x;
886 pos_y += 1.25 * hud_fontsize_y; // skip the header
887 pos_y += autocvar_scoreboard_border_thickness;
889 // fill the table and draw the rows
892 for(pl = players.sort_next; pl; pl = pl.sort_next)
894 if(pl.team != tm.team)
896 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i);
897 pos_y += 1.25 * hud_fontsize_y;
901 for(pl = players.sort_next; pl; pl = pl.sort_next)
903 if(pl.team == COLOR_SPECTATOR)
905 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i);
906 pos_y += 1.25 * hud_fontsize_y;
911 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
912 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
917 float HUD_WouldDrawScoreboard() {
918 if (autocvar__hud_configure)
920 else if (scoreboard_showscores)
922 else if (intermission == 1)
924 else if (intermission == 2)
926 else if (getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != GAME_CTS)
928 else if (spectatee_status == -1)
930 else if (scoreboard_showscores_force)
936 float average_accuracy;
937 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
940 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
942 if(autocvar_scoreboard_accuracy_doublerows)
947 float fontsize = height * 1/3;
948 float weapon_height = height * 2/3;
949 float weapon_width = sbwidth / weapon_cnt;
951 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
952 pos_y += 1.25 * hud_fontsize_y;
955 tmp_y = height * rows;
958 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
960 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
961 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
963 // column highlighting
964 for(i = 0; i < weapon_cnt/rows; ++i)
967 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);
971 for(i = 0; i < rows; ++i)
973 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);
976 average_accuracy = 0;
977 float weapons_with_stats;
978 weapons_with_stats = 0;
980 pos_x += weapon_width / 2;
982 if(getstati(STAT_SWITCHWEAPON) == WEP_MINSTANEX)
983 g_minstagib = 1; // TODO: real detection for minstagib?
985 float weapon_stats, weapon_number;
989 else if (acc_col_x[0] == -1)
990 for (i = 0; i < acc_levels; ++i)
991 acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i))));
993 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
995 self = get_weaponinfo(i);
998 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
1000 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1003 if(weapon_stats >= 0)
1004 weapon_alpha = scoreboard_alpha_fg;
1006 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1009 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);
1011 if(weapon_stats >= 0) {
1012 weapons_with_stats += 1;
1013 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1016 s = sprintf(_("%d%%"), weapon_stats*100);
1019 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1023 // find the max level lower than weapon_stats
1026 while ( j && weapon_stats < acc_lev[j] )
1029 // inject color j+1 in color j, how much depending on how much weapon_stats is higher than level j
1031 factor = (weapon_stats - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
1033 rgb = rgb + factor * (acc_col[j+1] - rgb);
1036 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1038 pos_x += weapon_width * rows;
1039 if(rows == 2 && i == 6) {
1045 if(weapons_with_stats)
1046 average_accuracy = floor(average_accuracy / weapons_with_stats);
1049 pos_x -= weapon_width / 2;
1053 pos_y += 1.25 * hud_fontsize_y;
1057 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1060 RANKINGS_RECEIVED_CNT = 0;
1061 for (i=RANKINGS_CNT-1; i>=0; --i)
1063 ++RANKINGS_RECEIVED_CNT;
1065 if (RANKINGS_RECEIVED_CNT == 0)
1069 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
1071 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1072 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1073 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1075 pos_y += hud_fontsize_y;
1076 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1077 pos_y += hud_fontsize_y;
1080 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1083 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1085 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1086 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1089 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1096 n = grecordholder[i];
1097 p = race_PlaceName(i+1);
1098 if(grecordholder[i] == GetPlayerName(player_localentnum - 1))
1099 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1100 else if(!mod(i, 2) && scoreboard_highlight)
1101 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1102 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1103 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);
1104 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1105 pos_y += 1.25 * hud_fontsize_y;
1111 float hud_woulddrawscoreboard_prev;
1112 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1113 void HUD_DrawScoreboard()
1115 float hud_woulddrawscoreboard;
1116 hud_woulddrawscoreboard = scoreboard_active;
1117 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1118 hud_woulddrawscoreboard_change = time;
1119 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1122 if(hud_woulddrawscoreboard) {
1123 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1124 if (scoreboard_fadeinspeed)
1125 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1127 scoreboard_fade_alpha = 1;
1130 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1131 if (scoreboard_fadeoutspeed)
1132 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1134 scoreboard_fade_alpha = 0;
1137 if not(scoreboard_fade_alpha)
1140 HUD_UpdatePlayerTeams();
1142 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1143 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1144 scoreboard_highlight = autocvar_scoreboard_highlight;
1145 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1146 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1147 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1148 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1150 vector rgb, pos, tmp;
1153 xmin = autocvar_scoreboard_offset_left * vid_conwidth;
1154 ymin = autocvar_con_notify * autocvar_con_notifysize;
1156 xmax = (1 - autocvar_scoreboard_offset_right) * vid_conwidth;
1157 ymax = vid_conheight - ymin;
1159 sbwidth = xmax - xmin;
1161 // Initializes position
1167 drawstring(pos, _("Scoreboard"), '24 24 0', '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1169 centerprint_start_x = vid_conwidth - 0.5 * (pos_x + stringwidth(_("Scoreboard"), FALSE, '24 24 0'));
1170 centerprint_start_y = pos_y;
1174 // Draw the scoreboard
1175 vector bg_size = drawgetimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1179 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1181 if(tm.team == COLOR_SPECTATOR)
1184 rgb = GetTeamRGB(tm.team);
1185 drawstring(pos - '2 0 0' * hud_fontsize_x + '0 1 0' * hud_fontsize_y, ftos(tm.(teamscores[ts_primary])), '1 1 0' * hud_fontsize_y * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1187 if(ts_primary != ts_secondary)
1188 drawstring(pos - '2 0 0' * hud_fontsize_x + '0 2.5 0' * hud_fontsize_y, ftos(tm.(teamscores[ts_secondary])), '1 1 0' * hud_fontsize_y * 1, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1190 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1195 rgb_x = autocvar_scoreboard_color_bg_r;
1196 rgb_y = autocvar_scoreboard_color_bg_g;
1197 rgb_z = autocvar_scoreboard_color_bg_b;
1199 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1201 if(tm.team == COLOR_SPECTATOR)
1204 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1208 if(gametype == GAME_CTS || gametype == GAME_RACE) {
1209 if(race_speedaward) {
1210 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1211 pos_y += 1.25 * hud_fontsize_y;
1213 if(race_speedaward_alltimebest) {
1214 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1215 pos_y += 1.25 * hud_fontsize_y;
1217 pos = HUD_DrawScoreboardRankings(pos, pl, rgb, bg_size);
1219 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1221 pos = HUD_DrawScoreboardAccuracyStats(pos, GetTeamRGB(myteam), bg_size);
1223 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1230 for(pl = players.sort_next; pl; pl = pl.sort_next)
1232 if(pl.team != COLOR_SPECTATOR)
1234 pos_y += 1.25 * hud_fontsize_y;
1235 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), specs);
1241 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1242 pos_y += 1.25 * hud_fontsize_y;
1245 // Print info string
1248 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1249 tl = getstatf(STAT_TIMELIMIT);
1250 fl = getstatf(STAT_FRAGLIMIT);
1251 ll = getstatf(STAT_LEADLIMIT);
1252 if(gametype == GAME_LMS)
1255 str = strcat(str, sprintf(_(" for up to ^1%.1f minutes^7"), tl));
1260 str = strcat(str, sprintf(_(" for up to ^1%.1f minutes^7"), tl));
1264 str = strcat(str, _(" or"));
1267 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1268 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1269 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1270 TranslateScoresLabel(teamscores_label[ts_primary])));
1274 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1275 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1276 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1277 TranslateScoresLabel(scores_label[ps_primary])));
1282 if(tl > 0 || fl > 0)
1283 str = strcat(str, _(" or"));
1286 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1287 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1288 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1289 TranslateScoresLabel(teamscores_label[ts_primary])));
1293 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1294 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1295 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1296 TranslateScoresLabel(scores_label[ps_primary])));
1302 pos_y += 1.2 * hud_fontsize_y;
1303 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1305 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;