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 "caps": return CTX(_("SCO^caps"));
21 case "deaths": return CTX(_("SCO^deaths"));
22 case "destroyed": return CTX(_("SCO^destroyed"));
23 case "drops": return CTX(_("SCO^drops"));
24 case "faults": return CTX(_("SCO^faults"));
25 case "fckills": return CTX(_("SCO^fckills"));
26 case "goals": return CTX(_("SCO^goals"));
27 case "kckills": return CTX(_("SCO^kckills"));
28 case "kdratio": return CTX(_("SCO^kdratio"));
29 case "k/d": return CTX(_("SCO^k/d"));
30 case "kd": return CTX(_("SCO^kd"));
31 case "kdr": return CTX(_("SCO^kdr"));
32 case "kills": return CTX(_("SCO^kills"));
33 case "laps": return CTX(_("SCO^laps"));
34 case "lives": return CTX(_("SCO^lives"));
35 case "losses": return CTX(_("SCO^losses"));
36 case "name": return CTX(_("SCO^name"));
37 case "nick": return CTX(_("SCO^nick"));
38 case "objectives": return CTX(_("SCO^objectives"));
39 case "pickups": return CTX(_("SCO^pickups"));
40 case "ping": return CTX(_("SCO^ping"));
41 case "pl": return CTX(_("SCO^pl"));
42 case "pushes": return CTX(_("SCO^pushes"));
43 case "rank": return CTX(_("SCO^rank"));
44 case "returns": return CTX(_("SCO^returns"));
45 case "revivals": return CTX(_("SCO^revivals"));
46 case "score": return CTX(_("SCO^score"));
47 case "suicides": return CTX(_("SCO^suicides"));
48 case "takes": return CTX(_("SCO^takes"));
49 case "ticks": return CTX(_("SCO^ticks"));
55 void HUD_FinaleOverlay()
58 pos_x = (vid_conwidth - 1)/2;
62 //drawpic(pos, "gfx/finale", '0 0 0', '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
64 //drawstring(pos, "END", hud_fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
68 void Cmd_HUD_SetFields(float argc);
73 ps_primary = ps_secondary = ts_primary = ts_secondary = -1;
74 for(i = 0; i < MAX_SCORE; ++i)
76 f = (scores_flags[i] & SFL_SORT_PRIO_MASK);
77 if(f == SFL_SORT_PRIO_PRIMARY)
79 if(f == SFL_SORT_PRIO_SECONDARY)
82 if(ps_secondary == -1)
83 ps_secondary = ps_primary;
85 for(i = 0; i < MAX_TEAMSCORE; ++i)
87 f = (teamscores_flags[i] & SFL_SORT_PRIO_MASK);
88 if(f == SFL_SORT_PRIO_PRIMARY)
90 if(f == SFL_SORT_PRIO_SECONDARY)
93 if(ts_secondary == -1)
94 ts_secondary = ts_primary;
99 void HUD_UpdatePlayerPos(entity pl);
100 float SetTeam(entity pl, float Team);
102 void HUD_UpdatePlayerTeams()
109 for(pl = players.sort_next; pl; pl = pl.sort_next)
112 Team = GetPlayerColor(pl.sv_entnum);
113 if(SetTeam(pl, Team))
116 HUD_UpdatePlayerPos(pl);
120 pl = players.sort_next;
125 print(strcat("PNUM: ", ftos(num), "\n"));
130 float HUD_ComparePlayerScores(entity left, entity right)
133 vl = GetPlayerColor(left.sv_entnum);
134 vr = GetPlayerColor(right.sv_entnum);
137 vl = COLOR_SPECTATOR;
139 vr = COLOR_SPECTATOR;
146 if(vl == COLOR_SPECTATOR)
148 // FIRST the one with scores (spectators), THEN the ones without (downloaders)
150 if(!left.gotscores && right.gotscores)
155 vl = left.scores[ps_primary];
156 vr = right.scores[ps_primary];
157 if(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)
159 if(vl == 0 && vr != 0)
161 if(vl != 0 && vr == 0)
165 return IS_INCREASING(scores_flags[ps_primary]);
167 return IS_DECREASING(scores_flags[ps_primary]);
169 vl = left.scores[ps_secondary];
170 vr = right.scores[ps_secondary];
171 if(scores_flags[ps_secondary] & SFL_ZERO_IS_WORST)
173 if(vl == 0 && vr != 0)
175 if(vl != 0 && vr == 0)
179 return IS_INCREASING(scores_flags[ps_secondary]);
181 return IS_DECREASING(scores_flags[ps_secondary]);
186 void HUD_UpdatePlayerPos(entity player)
188 for(other = player.sort_next; other && HUD_ComparePlayerScores(player, other); other = player.sort_next)
190 SORT_SWAP(player, other);
192 for(other = player.sort_prev; other != players && HUD_ComparePlayerScores(other, player); other = player.sort_prev)
194 SORT_SWAP(other, player);
198 float HUD_CompareTeamScores(entity left, entity right)
202 if(left.team == COLOR_SPECTATOR)
204 if(right.team == COLOR_SPECTATOR)
207 vl = left.teamscores[ts_primary];
208 vr = right.teamscores[ts_primary];
210 return IS_INCREASING(teamscores_flags[ts_primary]);
212 return IS_DECREASING(teamscores_flags[ts_primary]);
214 vl = left.teamscores[ts_secondary];
215 vr = right.teamscores[ts_secondary];
217 return IS_INCREASING(teamscores_flags[ts_secondary]);
219 return IS_DECREASING(teamscores_flags[ts_secondary]);
224 void HUD_UpdateTeamPos(entity Team)
226 for(other = Team.sort_next; other && HUD_CompareTeamScores(Team, other); other = Team.sort_next)
228 SORT_SWAP(Team, other);
230 for(other = Team.sort_prev; other != teams && HUD_CompareTeamScores(other, Team); other = Team.sort_prev)
232 SORT_SWAP(other, Team);
236 void Cmd_HUD_Help(float argc)
238 print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
239 print(_("^3|---------------------------------------------------------------|\n"));
240 print(_("Usage:\n"));
241 print(_("^2scoreboard_columns_set default\n"));
242 print(_("^2scoreboard_columns_set ^7filed1 field2 ...\n"));
243 print(_("The following field names are recognized (case insensitive):\n"));
244 print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
246 print(_("^3name^7 or ^3nick^7 Name of a player\n"));
247 print(_("^3ping^7 Ping time\n"));
248 print(_("^3pl^7 Packet loss\n"));
249 print(_("^3kills^7 Number of kills\n"));
250 print(_("^3deaths^7 Number of deaths\n"));
251 print(_("^3suicides^7 Number of suicides\n"));
252 print(_("^3frags^7 kills - suicides\n"));
253 print(_("^3kd^7 The kill-death ratio\n"));
254 print(_("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n"));
255 print(_("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) was picked up\n"));
256 print(_("^3fckills^7 Number of flag carrier kills\n"));
257 print(_("^3returns^7 Number of flag returns\n"));
258 print(_("^3drops^7 Number of flag drops\n"));
259 print(_("^3lives^7 Number of lives (LMS)\n"));
260 print(_("^3rank^7 Player rank\n"));
261 print(_("^3pushes^7 Number of players pushed into void\n"));
262 print(_("^3destroyed^7 Number of keys destroyed by pushing them into void\n"));
263 print(_("^3kckills^7 Number of keys carrier kills\n"));
264 print(_("^3losses^7 Number of times a key was lost\n"));
265 print(_("^3laps^7 Number of laps finished (race/cts)\n"));
266 print(_("^3time^7 Total time raced (race/cts)\n"));
267 print(_("^3fastest^7 Time of fastest lap (race/cts)\n"));
268 print(_("^3ticks^7 Number of ticks (DOM)\n"));
269 print(_("^3takes^7 Number of domination points taken (DOM)\n"));
270 print(_("^3score^7 Total score\n\n"));
272 print(_("Before a field you can put a + or - sign, then a comma separated list\n"
273 "of game types, then a slash, to make the field show up only in these\n"
274 "or in all but these game types. You can also specify 'all' as a\n"
275 "field to show all fields available for the current game mode.\n\n"));
277 print(_("The special game type names 'teams' and 'noteams' can be used to\n"
278 "include/exclude ALL teams/noteams game modes.\n\n"));
280 print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
281 print(_("will display name, ping and pl aligned to the left, and the fields\n"
282 "right of the vertical bar aligned to the right.\n"));
283 print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
284 "other gamemodes except DM.\n"));
287 string HUD_DefaultColumnLayout()
289 return strcat( // fteqcc sucks
291 "-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"
292 "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ",
293 "+lms/lives +lms/rank ",
294 "+kh/caps +kh/pushes +kh/destroyed ",
295 "?+race/laps ?+race/time ?+race/fastest ",
296 "+as/objectives +nexball/faults +nexball/goals +ka/drops +ka/pickups +ka/bckills +ka/time +freezetag/revivals ",
297 "-lms,race,nexball/score");
300 void Cmd_HUD_SetFields(float argc)
304 float have_name, have_primary, have_secondary, have_separator;
307 // TODO: re enable with gametype dependant cvars?
308 if(argc < 2) // no arguments provided
309 argc = tokenizebyseparator(strcat("x ", autocvar_scoreboard_columns), " ");
312 argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
316 if(argv(1) == "default")
317 argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
318 else if(argv(1) == "all")
321 s = "ping pl color name |";
322 for(i = 0; i < MAX_SCORE; ++i)
325 if(i != ps_secondary)
326 if(scores_label[i] != "")
327 s = strcat(s, " ", scores_label[i]);
329 if(ps_secondary != ps_primary)
330 s = strcat(s, " ", scores_label[ps_secondary]);
331 s = strcat(s, " ", scores_label[ps_primary]);
332 argc = tokenizebyseparator(strcat("x ", s), " ");
339 hud_fontsize = HUD_GetFontsize("hud_fontsize");
341 for(i = 0; i < argc - 1; ++i)
347 if(substring(str, 0, 1) == "?")
350 str = substring(str, 1, strlen(str) - 1);
353 slash = strstrofs(str, "/", 0);
356 pattern = substring(str, 0, slash);
357 str = substring(str, slash + 1, strlen(str) - (slash + 1));
359 if not(isGametypeInFilter(gametype, teamplay, pattern))
363 strunzone(hud_title[hud_num_fields]);
364 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
365 hud_size[hud_num_fields] = stringwidth(str, FALSE, hud_fontsize);
366 str = strtolower(str);
369 hud_field[hud_num_fields] = SP_PING;
370 } else if(str == "pl") {
371 hud_field[hud_num_fields] = SP_PL;
372 } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
373 hud_field[hud_num_fields] = SP_KDRATIO;
374 } else if(str == "name" || str == "nick") {
375 hud_field[hud_num_fields] = SP_NAME;
377 } else if(str == "|") {
378 hud_field[hud_num_fields] = SP_SEPARATOR;
381 for(j = 0; j < MAX_SCORE; ++j)
382 if(str == strtolower(scores_label[j]))
383 goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
392 print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
396 hud_field[hud_num_fields] = j;
399 if(j == ps_secondary)
403 if(hud_num_fields >= MAX_HUD_FIELDS)
407 if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
409 if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
411 if(ps_primary == ps_secondary)
413 missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
415 if(hud_num_fields+missing < MAX_HUD_FIELDS)
419 strunzone(hud_title[hud_num_fields]);
420 for(i = hud_num_fields; i > 0; --i)
422 hud_title[i] = hud_title[i-1];
423 hud_size[i] = hud_size[i-1];
424 hud_field[i] = hud_field[i-1];
426 hud_title[0] = strzone(TranslateScoresLabel("name"));
427 hud_field[0] = SP_NAME;
429 print(sprintf(_("fixed missing field '%s'\n"), "name"));
433 strunzone(hud_title[hud_num_fields]);
434 for(i = hud_num_fields; i > 1; --i)
436 hud_title[i] = hud_title[i-1];
437 hud_size[i] = hud_size[i-1];
438 hud_field[i] = hud_field[i-1];
440 hud_title[1] = strzone("|");
441 hud_field[1] = SP_SEPARATOR;
442 hud_size[1] = stringwidth("|", FALSE, hud_fontsize);
444 print(sprintf(_("fixed missing field '%s'\n"), "|"));
447 else if(!have_separator)
449 strunzone(hud_title[hud_num_fields]);
450 hud_title[hud_num_fields] = strzone("|");
451 hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize);
452 hud_field[hud_num_fields] = SP_SEPARATOR;
454 print(sprintf(_("fixed missing field '%s'\n"), "|"));
458 strunzone(hud_title[hud_num_fields]);
459 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
460 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
461 hud_field[hud_num_fields] = ps_secondary;
463 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_secondary]));
467 strunzone(hud_title[hud_num_fields]);
468 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
469 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
470 hud_field[hud_num_fields] = ps_primary;
472 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_primary]));
476 hud_field[hud_num_fields] = SP_END;
480 vector hud_field_rgb;
481 string hud_field_icon0;
482 string hud_field_icon1;
483 string hud_field_icon2;
484 vector hud_field_icon0_rgb;
485 vector hud_field_icon1_rgb;
486 vector hud_field_icon2_rgb;
487 float hud_field_icon0_alpha;
488 float hud_field_icon1_alpha;
489 float hud_field_icon2_alpha;
490 string HUD_GetField(entity pl, float field)
492 float tmp, num, denom, f;
494 hud_field_rgb = '1 1 1';
495 hud_field_icon0 = "";
496 hud_field_icon1 = "";
497 hud_field_icon2 = "";
498 hud_field_icon0_rgb = '1 1 1';
499 hud_field_icon1_rgb = '1 1 1';
500 hud_field_icon2_rgb = '1 1 1';
501 hud_field_icon0_alpha = 1;
502 hud_field_icon1_alpha = 1;
503 hud_field_icon2_alpha = 1;
508 return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
509 //str = getplayerkey(pl.sv_entnum, "ping");
513 tmp = max(0, min(220, f-80)) / 220;
514 hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
520 f = pl.ping_packetloss;
521 tmp = pl.ping_movementloss;
522 if(f == 0 && tmp == 0)
524 str = ftos(ceil(f * 100));
526 str = strcat(str, "~", ftos(ceil(tmp * 100)));
527 tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
528 hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
532 if(ready_waiting && pl.ready)
534 hud_field_icon0 = "gfx/scoreboard/player_ready";
538 f = stof(getplayerkey(pl.sv_entnum, "colors"));
540 hud_field_icon0 = "gfx/scoreboard/playercolor_base";
541 hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
542 hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
543 hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
544 hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
547 return GetPlayerName(pl.sv_entnum);
550 f = pl.(scores[SP_KILLS]);
551 f -= pl.(scores[SP_SUICIDES]);
555 num = pl.(scores[SP_KILLS]);
556 denom = pl.(scores[SP_DEATHS]);
559 hud_field_rgb = '0 1 0';
560 str = sprintf("%d", num);
561 } else if(num <= 0) {
562 hud_field_rgb = '1 0 0';
563 str = sprintf("%.1f", num/denom);
565 str = sprintf("%.1f", num/denom);
569 tmp = pl.(scores[field]);
570 f = scores_flags[field];
571 if(field == ps_primary)
572 hud_field_rgb = '1 1 0';
573 else if(field == ps_secondary)
574 hud_field_rgb = '0 1 1';
576 hud_field_rgb = '1 1 1';
577 return ScoreString(f, tmp);
582 float xmin, xmax, ymin, ymax, sbwidth;
583 float hud_fixscoreboardcolumnwidth_len;
584 float hud_fixscoreboardcolumnwidth_iconlen;
585 float hud_fixscoreboardcolumnwidth_marginlen;
587 string HUD_FixScoreboardColumnWidth(float i, string str)
591 field = hud_field[i];
593 hud_fixscoreboardcolumnwidth_iconlen = 0;
595 if(hud_field_icon0 != "")
597 sz = drawgetimagesize(hud_field_icon0);
599 if(hud_fixscoreboardcolumnwidth_iconlen < f)
600 hud_fixscoreboardcolumnwidth_iconlen = f;
603 if(hud_field_icon1 != "")
605 sz = drawgetimagesize(hud_field_icon1);
607 if(hud_fixscoreboardcolumnwidth_iconlen < f)
608 hud_fixscoreboardcolumnwidth_iconlen = f;
611 if(hud_field_icon2 != "")
613 sz = drawgetimagesize(hud_field_icon2);
615 if(hud_fixscoreboardcolumnwidth_iconlen < f)
616 hud_fixscoreboardcolumnwidth_iconlen = f;
619 hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize_y / hud_fontsize_x; // fix icon aspect
621 if(hud_fixscoreboardcolumnwidth_iconlen != 0)
622 hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", FALSE, hud_fontsize);
624 hud_fixscoreboardcolumnwidth_marginlen = 0;
626 if(field == SP_NAME) // name gets all remaining space
629 namesize = sbwidth;// / hud_fontsize_x;
630 for(j = 0; j < hud_num_fields; ++j)
632 if (hud_field[i] != SP_SEPARATOR)
633 namesize -= hud_size[j] + hud_fontsize_x;
634 namesize += hud_fontsize_x;
635 hud_size[i] = namesize;
637 if (hud_fixscoreboardcolumnwidth_iconlen != 0)
638 namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
639 str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
640 hud_fixscoreboardcolumnwidth_len = stringwidth(str, TRUE, hud_fontsize);
643 hud_fixscoreboardcolumnwidth_len = stringwidth(str, FALSE, hud_fontsize);
645 f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
652 void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
655 rgb = GetTeamRGB(pl.team);
659 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
661 if((rgb == '1 1 1') && (!is_spec)) {
662 rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
663 rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
664 rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
668 tmp_y = hud_fontsize_y * 1.25;
671 // alternated rows highlighting
673 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
674 else if((scoreboard_highlight) && (!mod(pl_number,2)))
675 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
679 for(i = 0; i < hud_num_fields; ++i)
681 field = hud_field[i];
682 if(field == SP_SEPARATOR)
685 if(is_spec && field != SP_NAME && field != SP_PING) {
686 pos_x += hud_size[i] + hud_fontsize_x;
689 str = HUD_GetField(pl, field);
690 str = HUD_FixScoreboardColumnWidth(i, str);
692 pos_x += hud_size[i] + hud_fontsize_x;
694 if(field == SP_NAME) {
695 tmp_x = hud_size[i] - hud_fontsize_x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize_x;
697 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
699 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
701 tmp_x = hud_fixscoreboardcolumnwidth_len + hud_fontsize_x;
703 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
705 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
708 tmp_x = hud_size[i] + hud_fontsize_x;
709 if(hud_field_icon0 != "")
711 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);
713 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);
714 if(hud_field_icon1 != "")
716 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);
718 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);
719 if(hud_field_icon2 != "")
721 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);
723 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);
726 if(hud_field[i] == SP_SEPARATOR)
729 for(i = hud_num_fields-1; i > 0; --i)
731 field = hud_field[i];
732 if(field == SP_SEPARATOR)
735 if(is_spec && field != SP_NAME && field != SP_PING) {
736 pos_x -= hud_size[i] + hud_fontsize_x;
740 str = HUD_GetField(pl, field);
741 str = HUD_FixScoreboardColumnWidth(i, str);
743 if(field == SP_NAME) {
744 tmp_x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
746 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
748 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
750 tmp_x = hud_fixscoreboardcolumnwidth_len;
752 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
754 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
758 if(hud_field_icon0 != "")
760 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);
762 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);
763 if(hud_field_icon1 != "")
765 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);
767 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);
768 if(hud_field_icon2 != "")
770 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);
772 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);
773 pos_x -= hud_size[i] + hud_fontsize_x;
779 * HUD_Scoreboard_MakeTable
781 * Makes a table for a team (for all playing players in DM) and fills it
784 vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
786 float body_table_height, i;
787 vector tmp, column_dim;
790 body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
795 tmp_y = 1.25 * hud_fontsize_y;
799 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
801 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
804 tmp_y += autocvar_scoreboard_border_thickness;
805 tmp_y += body_table_height;
806 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
808 // separator header/table
809 pos_y += 1.25 * hud_fontsize_y;
810 tmp_y = autocvar_scoreboard_border_thickness;
811 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
813 pos_y += autocvar_scoreboard_border_thickness;
816 tmp_y = body_table_height;
818 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
820 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
822 // anyway, apply some color
823 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
825 // go back to the top to make alternated columns highlighting and to print the strings
826 pos_y -= 1.25 * hud_fontsize_y;
827 pos_y -= autocvar_scoreboard_border_thickness;
831 if (scoreboard_highlight)
833 column_dim_y = 1.25 * hud_fontsize_y; // header
834 column_dim_y += autocvar_scoreboard_border_thickness;
835 column_dim_y += body_table_height;
838 // print the strings of the columns headers and draw the columns
839 for(i = 0; i < hud_num_fields; ++i)
841 if(hud_field[i] == SP_SEPARATOR)
843 column_dim_x = hud_size[i] + hud_fontsize_x;
844 if (scoreboard_highlight)
847 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
849 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
850 pos_x += column_dim_x;
852 if(hud_field[i] == SP_SEPARATOR)
856 for(i = hud_num_fields-1; i > 0; --i)
858 if(hud_field[i] == SP_SEPARATOR)
861 pos_x -= hud_size[i];
863 if (scoreboard_highlight)
867 if (i == hud_num_fields-1)
868 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
870 column_dim_x = hud_size[i] + hud_fontsize_x;
871 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
875 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
876 tmp_x = (hud_size[i] - tmp_x);
877 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
878 pos_x -= hud_fontsize_x;
883 pos_y += 1.25 * hud_fontsize_y; // skip the header
884 pos_y += autocvar_scoreboard_border_thickness;
886 // fill the table and draw the rows
889 for(pl = players.sort_next; pl; pl = pl.sort_next)
891 if(pl.team != tm.team)
893 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i);
894 pos_y += 1.25 * hud_fontsize_y;
898 for(pl = players.sort_next; pl; pl = pl.sort_next)
900 if(pl.team == COLOR_SPECTATOR)
902 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i);
903 pos_y += 1.25 * hud_fontsize_y;
908 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
909 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
914 float HUD_WouldDrawScoreboard() {
915 if (autocvar__hud_configure)
917 else if (scoreboard_showscores)
919 else if (intermission == 1)
921 else if (intermission == 2)
923 else if (getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != GAME_CTS)
925 else if (spectatee_status == -1)
927 else if (scoreboard_showscores_force)
933 float average_accuracy;
934 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
937 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
939 if(autocvar_scoreboard_accuracy_doublerows)
944 float fontsize = height * 1/3;
945 float weapon_height = height * 2/3;
946 float weapon_width = sbwidth / weapon_cnt;
948 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
949 pos_y += 1.25 * hud_fontsize_y;
952 tmp_y = height * rows;
955 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
957 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
958 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
960 // column highlighting
961 for(i = 0; i < weapon_cnt/rows; ++i)
964 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);
968 for(i = 0; i < rows; ++i)
970 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);
973 average_accuracy = 0;
974 float weapons_with_stats;
975 weapons_with_stats = 0;
977 pos_x += weapon_width / 2;
979 if(getstati(STAT_SWITCHWEAPON) == WEP_MINSTANEX)
980 g_minstagib = 1; // TODO: real detection for minstagib?
982 float weapon_stats, weapon_number;
986 else if (acc_col_x[0] == -1)
987 for (i = 0; i < acc_levels; ++i)
988 acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i))));
990 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
992 self = get_weaponinfo(i);
995 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
997 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1000 if(weapon_stats >= 0)
1001 weapon_alpha = scoreboard_alpha_fg;
1003 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1006 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);
1008 if(weapon_stats >= 0) {
1009 weapons_with_stats += 1;
1010 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1013 s = sprintf(_("%d%%"), weapon_stats*100);
1016 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1020 // find the max level lower than weapon_stats
1023 while ( j && weapon_stats < acc_lev[j] )
1026 // inject color j+1 in color j, how much depending on how much weapon_stats is higher than level j
1028 factor = (weapon_stats - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
1030 rgb = rgb + factor * (acc_col[j+1] - rgb);
1033 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1035 pos_x += weapon_width * rows;
1036 if(rows == 2 && i == 6) {
1042 if(weapons_with_stats)
1043 average_accuracy = floor(average_accuracy / weapons_with_stats);
1046 pos_x -= weapon_width / 2;
1050 pos_y += 1.25 * hud_fontsize_y;
1054 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1057 RANKINGS_RECEIVED_CNT = 0;
1058 for (i=RANKINGS_CNT-1; i>=0; --i)
1060 ++RANKINGS_RECEIVED_CNT;
1062 if (RANKINGS_RECEIVED_CNT == 0)
1066 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
1068 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1069 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1070 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1072 pos_y += hud_fontsize_y;
1073 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1074 pos_y += hud_fontsize_y;
1077 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1080 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1082 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1083 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1086 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1093 n = grecordholder[i];
1094 p = race_PlaceName(i+1);
1095 if(grecordholder[i] == GetPlayerName(player_localentnum - 1))
1096 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1097 else if(!mod(i, 2) && scoreboard_highlight)
1098 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1099 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1100 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);
1101 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1102 pos_y += 1.25 * hud_fontsize_y;
1108 float hud_woulddrawscoreboard_prev;
1109 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1110 void HUD_DrawScoreboard()
1112 float hud_woulddrawscoreboard;
1113 hud_woulddrawscoreboard = scoreboard_active;
1114 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1115 hud_woulddrawscoreboard_change = time;
1116 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1119 if(hud_woulddrawscoreboard) {
1120 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1121 if (scoreboard_fadeinspeed)
1122 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1124 scoreboard_fade_alpha = 1;
1127 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1128 if (scoreboard_fadeoutspeed)
1129 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1131 scoreboard_fade_alpha = 0;
1134 if not(scoreboard_fade_alpha)
1137 HUD_UpdatePlayerTeams();
1139 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1140 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1141 scoreboard_highlight = autocvar_scoreboard_highlight;
1142 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1143 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1144 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1145 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1147 vector rgb, pos, tmp;
1150 xmin = autocvar_scoreboard_offset_left * vid_conwidth;
1151 ymin = autocvar_con_notify * autocvar_con_notifysize;
1153 xmax = (1 - autocvar_scoreboard_offset_right) * vid_conwidth;
1154 ymax = vid_conheight - ymin;
1156 sbwidth = xmax - xmin;
1158 // Initializes position
1164 drawstring(pos, _("Scoreboard"), '24 24 0', '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1166 centerprint_start_x = vid_conwidth - 0.5 * (pos_x + stringwidth(_("Scoreboard"), FALSE, '24 24 0'));
1167 centerprint_start_y = pos_y;
1171 // Draw the scoreboard
1172 vector bg_size = drawgetimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1176 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1178 if(tm.team == COLOR_SPECTATOR)
1181 rgb = GetTeamRGB(tm.team);
1182 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);
1184 if(ts_primary != ts_secondary)
1185 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);
1187 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1192 rgb_x = autocvar_scoreboard_color_bg_r;
1193 rgb_y = autocvar_scoreboard_color_bg_g;
1194 rgb_z = autocvar_scoreboard_color_bg_b;
1196 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1198 if(tm.team == COLOR_SPECTATOR)
1201 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1205 if(gametype == GAME_CTS || gametype == GAME_RACE) {
1206 if(race_speedaward) {
1207 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1208 pos_y += 1.25 * hud_fontsize_y;
1210 if(race_speedaward_alltimebest) {
1211 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1212 pos_y += 1.25 * hud_fontsize_y;
1214 pos = HUD_DrawScoreboardRankings(pos, pl, rgb, bg_size);
1216 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1218 pos = HUD_DrawScoreboardAccuracyStats(pos, GetTeamRGB(myteam), bg_size);
1220 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1227 for(pl = players.sort_next; pl; pl = pl.sort_next)
1229 if(pl.team != COLOR_SPECTATOR)
1231 pos_y += 1.25 * hud_fontsize_y;
1232 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), specs);
1238 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1239 pos_y += 1.25 * hud_fontsize_y;
1242 // Print info string
1245 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1246 tl = getstatf(STAT_TIMELIMIT);
1247 fl = getstatf(STAT_FRAGLIMIT);
1248 ll = getstatf(STAT_LEADLIMIT);
1249 if(gametype == GAME_LMS)
1252 str = strcat(str, sprintf(_(" for up to ^1%.1g minutes^7"), tl));
1257 str = strcat(str, sprintf(_(" for up to ^1%.1g minutes^7"), tl));
1261 str = strcat(str, _(" or"));
1264 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1265 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1266 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1267 TranslateScoresLabel(teamscores_label[ts_primary])));
1271 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1272 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1273 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1274 TranslateScoresLabel(scores_label[ps_primary])));
1279 if(tl > 0 || fl > 0)
1280 str = strcat(str, _(" or"));
1283 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1284 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1285 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1286 TranslateScoresLabel(teamscores_label[ts_primary])));
1290 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1291 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1292 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1293 TranslateScoresLabel(scores_label[ps_primary])));
1299 pos_y += 1.2 * hud_fontsize_y;
1300 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1302 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;