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) 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(_("^3score^7 Total score\n\n"));
273 print(_("Before a field you can put a + or - sign, then a comma separated list\n"
274 "of game types, then a slash, to make the field show up only in these\n"
275 "or in all but these game types. You can also specify 'all' as a\n"
276 "field to show all fields available for the current game mode.\n\n"));
278 print(_("The special game type names 'teams' and 'noteams' can be used to\n"
279 "include/exclude ALL teams/noteams game modes.\n\n"));
281 print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
282 print(_("will display name, ping and pl aligned to the left, and the fields\n"
283 "right of the vertical bar aligned to the right.\n"));
284 print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
285 "other gamemodes except DM.\n"));
288 string HUD_DefaultColumnLayout()
290 return strcat( // fteqcc sucks
292 "-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"
293 "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ",
294 "+lms/lives +lms/rank ",
295 "+kh/caps +kh/pushes +kh/destroyed ",
296 "?+race/laps ?+race/time ?+race/fastest ",
297 "+as/objectives +nexball/faults +nexball/goals +ka/drops +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ",
298 "-lms,race,nexball/score");
301 void Cmd_HUD_SetFields(float argc)
305 float have_name, have_primary, have_secondary, have_separator;
308 // TODO: re enable with gametype dependant cvars?
309 if(argc < 2) // no arguments provided
310 argc = tokenizebyseparator(strcat("x ", autocvar_scoreboard_columns), " ");
313 argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
317 if(argv(1) == "default")
318 argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
319 else if(argv(1) == "all")
322 s = "ping pl color name |";
323 for(i = 0; i < MAX_SCORE; ++i)
326 if(i != ps_secondary)
327 if(scores_label[i] != "")
328 s = strcat(s, " ", scores_label[i]);
330 if(ps_secondary != ps_primary)
331 s = strcat(s, " ", scores_label[ps_secondary]);
332 s = strcat(s, " ", scores_label[ps_primary]);
333 argc = tokenizebyseparator(strcat("x ", s), " ");
340 hud_fontsize = HUD_GetFontsize("hud_fontsize");
342 for(i = 0; i < argc - 1; ++i)
348 if(substring(str, 0, 1) == "?")
351 str = substring(str, 1, strlen(str) - 1);
354 slash = strstrofs(str, "/", 0);
357 pattern = substring(str, 0, slash);
358 str = substring(str, slash + 1, strlen(str) - (slash + 1));
360 if not(isGametypeInFilter(gametype, teamplay, FALSE, pattern))
364 strunzone(hud_title[hud_num_fields]);
365 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
366 hud_size[hud_num_fields] = stringwidth(str, FALSE, hud_fontsize);
367 str = strtolower(str);
370 hud_field[hud_num_fields] = SP_PING;
371 } else if(str == "pl") {
372 hud_field[hud_num_fields] = SP_PL;
373 } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
374 hud_field[hud_num_fields] = SP_KDRATIO;
375 } else if(str == "name" || str == "nick") {
376 hud_field[hud_num_fields] = SP_NAME;
378 } else if(str == "|") {
379 hud_field[hud_num_fields] = SP_SEPARATOR;
382 for(j = 0; j < MAX_SCORE; ++j)
383 if(str == strtolower(scores_label[j]))
384 goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
393 print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
397 hud_field[hud_num_fields] = j;
400 if(j == ps_secondary)
404 if(hud_num_fields >= MAX_HUD_FIELDS)
408 if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
410 if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
412 if(ps_primary == ps_secondary)
414 missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
416 if(hud_num_fields+missing < MAX_HUD_FIELDS)
420 strunzone(hud_title[hud_num_fields]);
421 for(i = hud_num_fields; i > 0; --i)
423 hud_title[i] = hud_title[i-1];
424 hud_size[i] = hud_size[i-1];
425 hud_field[i] = hud_field[i-1];
427 hud_title[0] = strzone(TranslateScoresLabel("name"));
428 hud_field[0] = SP_NAME;
430 print(sprintf(_("fixed missing field '%s'\n"), "name"));
434 strunzone(hud_title[hud_num_fields]);
435 for(i = hud_num_fields; i > 1; --i)
437 hud_title[i] = hud_title[i-1];
438 hud_size[i] = hud_size[i-1];
439 hud_field[i] = hud_field[i-1];
441 hud_title[1] = strzone("|");
442 hud_field[1] = SP_SEPARATOR;
443 hud_size[1] = stringwidth("|", FALSE, hud_fontsize);
445 print(sprintf(_("fixed missing field '%s'\n"), "|"));
448 else if(!have_separator)
450 strunzone(hud_title[hud_num_fields]);
451 hud_title[hud_num_fields] = strzone("|");
452 hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize);
453 hud_field[hud_num_fields] = SP_SEPARATOR;
455 print(sprintf(_("fixed missing field '%s'\n"), "|"));
459 strunzone(hud_title[hud_num_fields]);
460 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
461 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
462 hud_field[hud_num_fields] = ps_secondary;
464 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_secondary]));
468 strunzone(hud_title[hud_num_fields]);
469 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
470 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
471 hud_field[hud_num_fields] = ps_primary;
473 print(sprintf(_("fixed missing field '%s'\n"), scores_label[ps_primary]));
477 hud_field[hud_num_fields] = SP_END;
481 vector hud_field_rgb;
482 string hud_field_icon0;
483 string hud_field_icon1;
484 string hud_field_icon2;
485 vector hud_field_icon0_rgb;
486 vector hud_field_icon1_rgb;
487 vector hud_field_icon2_rgb;
488 float hud_field_icon0_alpha;
489 float hud_field_icon1_alpha;
490 float hud_field_icon2_alpha;
491 string HUD_GetField(entity pl, float field)
493 float tmp, num, denom, f;
495 hud_field_rgb = '1 1 1';
496 hud_field_icon0 = "";
497 hud_field_icon1 = "";
498 hud_field_icon2 = "";
499 hud_field_icon0_rgb = '1 1 1';
500 hud_field_icon1_rgb = '1 1 1';
501 hud_field_icon2_rgb = '1 1 1';
502 hud_field_icon0_alpha = 1;
503 hud_field_icon1_alpha = 1;
504 hud_field_icon2_alpha = 1;
509 return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
510 //str = getplayerkey(pl.sv_entnum, "ping");
514 tmp = max(0, min(220, f-80)) / 220;
515 hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
521 f = pl.ping_packetloss;
522 tmp = pl.ping_movementloss;
523 if(f == 0 && tmp == 0)
525 str = ftos(ceil(f * 100));
527 str = strcat(str, "~", ftos(ceil(tmp * 100)));
528 tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
529 hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
533 if(ready_waiting && pl.ready)
535 hud_field_icon0 = "gfx/scoreboard/player_ready";
539 f = stof(getplayerkey(pl.sv_entnum, "colors"));
541 hud_field_icon0 = "gfx/scoreboard/playercolor_base";
542 hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
543 hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
544 hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
545 hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
548 return GetPlayerName(pl.sv_entnum);
551 f = pl.(scores[SP_KILLS]);
552 f -= pl.(scores[SP_SUICIDES]);
556 num = pl.(scores[SP_KILLS]);
557 denom = pl.(scores[SP_DEATHS]);
560 hud_field_rgb = '0 1 0';
561 str = sprintf("%d", num);
562 } else if(num <= 0) {
563 hud_field_rgb = '1 0 0';
564 str = sprintf("%.1f", num/denom);
566 str = sprintf("%.1f", num/denom);
570 tmp = pl.(scores[field]);
571 f = scores_flags[field];
572 if(field == ps_primary)
573 hud_field_rgb = '1 1 0';
574 else if(field == ps_secondary)
575 hud_field_rgb = '0 1 1';
577 hud_field_rgb = '1 1 1';
578 return ScoreString(f, tmp);
583 float xmin, xmax, ymin, ymax, sbwidth;
584 float hud_fixscoreboardcolumnwidth_len;
585 float hud_fixscoreboardcolumnwidth_iconlen;
586 float hud_fixscoreboardcolumnwidth_marginlen;
588 string HUD_FixScoreboardColumnWidth(float i, string str)
592 field = hud_field[i];
594 hud_fixscoreboardcolumnwidth_iconlen = 0;
596 if(hud_field_icon0 != "")
598 sz = drawgetimagesize(hud_field_icon0);
600 if(hud_fixscoreboardcolumnwidth_iconlen < f)
601 hud_fixscoreboardcolumnwidth_iconlen = f;
604 if(hud_field_icon1 != "")
606 sz = drawgetimagesize(hud_field_icon1);
608 if(hud_fixscoreboardcolumnwidth_iconlen < f)
609 hud_fixscoreboardcolumnwidth_iconlen = f;
612 if(hud_field_icon2 != "")
614 sz = drawgetimagesize(hud_field_icon2);
616 if(hud_fixscoreboardcolumnwidth_iconlen < f)
617 hud_fixscoreboardcolumnwidth_iconlen = f;
620 hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize_y / hud_fontsize_x; // fix icon aspect
622 if(hud_fixscoreboardcolumnwidth_iconlen != 0)
623 hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", FALSE, hud_fontsize);
625 hud_fixscoreboardcolumnwidth_marginlen = 0;
627 if(field == SP_NAME) // name gets all remaining space
630 namesize = sbwidth;// / hud_fontsize_x;
631 for(j = 0; j < hud_num_fields; ++j)
633 if (hud_field[i] != SP_SEPARATOR)
634 namesize -= hud_size[j] + hud_fontsize_x;
635 namesize += hud_fontsize_x;
636 hud_size[i] = namesize;
638 if (hud_fixscoreboardcolumnwidth_iconlen != 0)
639 namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
640 str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
641 hud_fixscoreboardcolumnwidth_len = stringwidth(str, TRUE, hud_fontsize);
644 hud_fixscoreboardcolumnwidth_len = stringwidth(str, FALSE, hud_fontsize);
646 f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
653 void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
656 rgb = GetTeamRGB(pl.team);
660 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
662 if((rgb == '1 1 1') && (!is_spec)) {
663 rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
664 rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
665 rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
669 tmp_y = hud_fontsize_y * 1.25;
672 // alternated rows highlighting
674 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
675 else if((scoreboard_highlight) && (!mod(pl_number,2)))
676 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
680 for(i = 0; i < hud_num_fields; ++i)
682 field = hud_field[i];
683 if(field == SP_SEPARATOR)
686 if(is_spec && field != SP_NAME && field != SP_PING) {
687 pos_x += hud_size[i] + hud_fontsize_x;
690 str = HUD_GetField(pl, field);
691 str = HUD_FixScoreboardColumnWidth(i, str);
693 pos_x += hud_size[i] + hud_fontsize_x;
695 if(field == SP_NAME) {
696 tmp_x = hud_size[i] - hud_fontsize_x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize_x;
698 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
700 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
702 tmp_x = hud_fixscoreboardcolumnwidth_len + hud_fontsize_x;
704 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
706 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
709 tmp_x = hud_size[i] + hud_fontsize_x;
710 if(hud_field_icon0 != "")
712 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);
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, DRAWFLAG_NORMAL);
715 if(hud_field_icon1 != "")
717 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);
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, DRAWFLAG_NORMAL);
720 if(hud_field_icon2 != "")
722 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);
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, DRAWFLAG_NORMAL);
727 if(hud_field[i] == SP_SEPARATOR)
730 for(i = hud_num_fields-1; i > 0; --i)
732 field = hud_field[i];
733 if(field == SP_SEPARATOR)
736 if(is_spec && field != SP_NAME && field != SP_PING) {
737 pos_x -= hud_size[i] + hud_fontsize_x;
741 str = HUD_GetField(pl, field);
742 str = HUD_FixScoreboardColumnWidth(i, str);
744 if(field == SP_NAME) {
745 tmp_x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
747 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
749 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
751 tmp_x = hud_fixscoreboardcolumnwidth_len;
753 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
755 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
759 if(hud_field_icon0 != "")
761 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);
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, DRAWFLAG_NORMAL);
764 if(hud_field_icon1 != "")
766 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);
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, DRAWFLAG_NORMAL);
769 if(hud_field_icon2 != "")
771 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);
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, DRAWFLAG_NORMAL);
774 pos_x -= hud_size[i] + hud_fontsize_x;
780 * HUD_Scoreboard_MakeTable
782 * Makes a table for a team (for all playing players in DM) and fills it
785 vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
787 float body_table_height, i;
788 vector tmp, column_dim;
791 body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
796 tmp_y = 1.25 * hud_fontsize_y;
800 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
802 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
805 tmp_y += autocvar_scoreboard_border_thickness;
806 tmp_y += body_table_height;
807 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
809 // separator header/table
810 pos_y += 1.25 * hud_fontsize_y;
811 tmp_y = autocvar_scoreboard_border_thickness;
812 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
814 pos_y += autocvar_scoreboard_border_thickness;
817 tmp_y = body_table_height;
819 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
821 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
823 // anyway, apply some color
824 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
826 // go back to the top to make alternated columns highlighting and to print the strings
827 pos_y -= 1.25 * hud_fontsize_y;
828 pos_y -= autocvar_scoreboard_border_thickness;
832 if (scoreboard_highlight)
834 column_dim_y = 1.25 * hud_fontsize_y; // header
835 column_dim_y += autocvar_scoreboard_border_thickness;
836 column_dim_y += body_table_height;
839 // print the strings of the columns headers and draw the columns
840 for(i = 0; i < hud_num_fields; ++i)
842 if(hud_field[i] == SP_SEPARATOR)
844 column_dim_x = hud_size[i] + hud_fontsize_x;
845 if (scoreboard_highlight)
848 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
850 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
851 pos_x += column_dim_x;
853 if(hud_field[i] == SP_SEPARATOR)
857 for(i = hud_num_fields-1; i > 0; --i)
859 if(hud_field[i] == SP_SEPARATOR)
862 pos_x -= hud_size[i];
864 if (scoreboard_highlight)
868 if (i == hud_num_fields-1)
869 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
871 column_dim_x = hud_size[i] + hud_fontsize_x;
872 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
876 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
877 tmp_x = (hud_size[i] - tmp_x);
878 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
879 pos_x -= hud_fontsize_x;
884 pos_y += 1.25 * hud_fontsize_y; // skip the header
885 pos_y += autocvar_scoreboard_border_thickness;
887 // fill the table and draw the rows
890 for(pl = players.sort_next; pl; pl = pl.sort_next)
892 if(pl.team != tm.team)
894 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i);
895 pos_y += 1.25 * hud_fontsize_y;
899 for(pl = players.sort_next; pl; pl = pl.sort_next)
901 if(pl.team == COLOR_SPECTATOR)
903 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i);
904 pos_y += 1.25 * hud_fontsize_y;
909 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
910 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
915 float HUD_WouldDrawScoreboard() {
916 if (autocvar__hud_configure)
918 else if (scoreboard_showscores)
920 else if (intermission == 1)
922 else if (intermission == 2)
924 else if (getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != GAME_CTS)
926 else if (spectatee_status == -1)
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;