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 (spectatee_status != -1 && getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != GAME_CTS)
928 else if (scoreboard_showscores_force)
934 float average_accuracy;
935 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
938 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
940 if(autocvar_scoreboard_accuracy_doublerows)
945 float fontsize = height * 1/3;
946 float weapon_height = height * 2/3;
947 float weapon_width = sbwidth / weapon_cnt;
949 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
950 pos_y += 1.25 * hud_fontsize_y;
953 tmp_y = height * rows;
956 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
958 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
959 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
961 // column highlighting
962 for(i = 0; i < weapon_cnt/rows; ++i)
965 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);
969 for(i = 0; i < rows; ++i)
971 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);
974 average_accuracy = 0;
975 float weapons_with_stats;
976 weapons_with_stats = 0;
978 pos_x += weapon_width / 2;
980 if(getstati(STAT_SWITCHWEAPON) == WEP_MINSTANEX)
981 g_minstagib = 1; // TODO: real detection for minstagib?
983 float weapon_stats, weapon_number;
987 else if (acc_col_x[0] == -1)
988 for (i = 0; i < acc_levels; ++i)
989 acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i))));
991 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
993 self = get_weaponinfo(i);
996 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
998 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1001 if(weapon_stats >= 0)
1002 weapon_alpha = scoreboard_alpha_fg;
1004 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1007 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);
1009 if(weapon_stats >= 0) {
1010 weapons_with_stats += 1;
1011 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1014 s = sprintf(_("%d%%"), weapon_stats*100);
1017 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1021 // find the max level lower than weapon_stats
1024 while ( j && weapon_stats < acc_lev[j] )
1027 // inject color j+1 in color j, how much depending on how much weapon_stats is higher than level j
1029 factor = (weapon_stats - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
1031 rgb = rgb + factor * (acc_col[j+1] - rgb);
1034 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1036 pos_x += weapon_width * rows;
1037 if(rows == 2 && i == 6) {
1043 if(weapons_with_stats)
1044 average_accuracy = floor(average_accuracy / weapons_with_stats);
1047 pos_x -= weapon_width / 2;
1051 pos_y += 1.25 * hud_fontsize_y;
1055 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1058 RANKINGS_RECEIVED_CNT = 0;
1059 for (i=RANKINGS_CNT-1; i>=0; --i)
1061 ++RANKINGS_RECEIVED_CNT;
1063 if (RANKINGS_RECEIVED_CNT == 0)
1067 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
1069 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1070 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1071 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1073 pos_y += hud_fontsize_y;
1074 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1075 pos_y += hud_fontsize_y;
1078 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1081 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1083 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1084 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1087 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1094 n = grecordholder[i];
1095 p = race_PlaceName(i+1);
1096 if(grecordholder[i] == GetPlayerName(player_localentnum - 1))
1097 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1098 else if(!mod(i, 2) && scoreboard_highlight)
1099 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1100 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1101 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);
1102 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1103 pos_y += 1.25 * hud_fontsize_y;
1109 float hud_woulddrawscoreboard_prev;
1110 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1111 void HUD_DrawScoreboard()
1113 float hud_woulddrawscoreboard;
1114 hud_woulddrawscoreboard = scoreboard_active;
1115 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1116 hud_woulddrawscoreboard_change = time;
1117 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1120 if(hud_woulddrawscoreboard) {
1121 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1122 if (scoreboard_fadeinspeed)
1123 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1125 scoreboard_fade_alpha = 1;
1128 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1129 if (scoreboard_fadeoutspeed)
1130 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1132 scoreboard_fade_alpha = 0;
1135 if not(scoreboard_fade_alpha)
1138 HUD_UpdatePlayerTeams();
1140 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1141 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1142 scoreboard_highlight = autocvar_scoreboard_highlight;
1143 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1144 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1145 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1146 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1148 vector rgb, pos, tmp;
1151 xmin = autocvar_scoreboard_offset_left * vid_conwidth;
1152 ymin = autocvar_con_notify * autocvar_con_notifysize;
1154 xmax = (1 - autocvar_scoreboard_offset_right) * vid_conwidth;
1155 ymax = vid_conheight - ymin;
1157 sbwidth = xmax - xmin;
1159 // Initializes position
1165 drawstring(pos, _("Scoreboard"), '24 24 0', '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1167 centerprint_start_x = vid_conwidth - 0.5 * (pos_x + stringwidth(_("Scoreboard"), FALSE, '24 24 0'));
1168 centerprint_start_y = pos_y;
1172 // Draw the scoreboard
1173 vector bg_size = drawgetimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1177 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1179 if(tm.team == COLOR_SPECTATOR)
1182 rgb = GetTeamRGB(tm.team);
1183 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);
1185 if(ts_primary != ts_secondary)
1186 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);
1188 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1193 rgb_x = autocvar_scoreboard_color_bg_r;
1194 rgb_y = autocvar_scoreboard_color_bg_g;
1195 rgb_z = autocvar_scoreboard_color_bg_b;
1197 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1199 if(tm.team == COLOR_SPECTATOR)
1202 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1206 if(gametype == GAME_CTS || gametype == GAME_RACE) {
1207 if(race_speedaward) {
1208 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1209 pos_y += 1.25 * hud_fontsize_y;
1211 if(race_speedaward_alltimebest) {
1212 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1213 pos_y += 1.25 * hud_fontsize_y;
1215 pos = HUD_DrawScoreboardRankings(pos, pl, rgb, bg_size);
1217 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1219 pos = HUD_DrawScoreboardAccuracyStats(pos, GetTeamRGB(myteam), bg_size);
1221 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1228 for(pl = players.sort_next; pl; pl = pl.sort_next)
1230 if(pl.team != COLOR_SPECTATOR)
1232 pos_y += 1.25 * hud_fontsize_y;
1233 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), specs);
1239 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1240 pos_y += 1.25 * hud_fontsize_y;
1243 // Print info string
1246 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1247 tl = getstatf(STAT_TIMELIMIT);
1248 fl = getstatf(STAT_FRAGLIMIT);
1249 ll = getstatf(STAT_LEADLIMIT);
1250 if(gametype == GAME_LMS)
1253 str = strcat(str, sprintf(_(" for up to ^1%.1f minutes^7"), tl));
1258 str = strcat(str, sprintf(_(" for up to ^1%.1f minutes^7"), tl));
1262 str = strcat(str, _(" or"));
1265 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1266 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1267 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1268 TranslateScoresLabel(teamscores_label[ts_primary])));
1272 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1273 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1274 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1275 TranslateScoresLabel(scores_label[ps_primary])));
1280 if(tl > 0 || fl > 0)
1281 str = strcat(str, _(" or"));
1284 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1285 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1286 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1287 TranslateScoresLabel(teamscores_label[ts_primary])));
1291 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1292 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1293 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1294 TranslateScoresLabel(scores_label[ps_primary])));
1300 pos_y += 1.2 * hud_fontsize_y;
1301 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1303 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;