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(hud_title[hud_num_fields], 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
795 pos_y += autocvar_scoreboard_border_thickness;
799 tmp_y = 1.25 * hud_fontsize_y;
803 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
805 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
808 tmp_y += autocvar_scoreboard_border_thickness;
809 tmp_y += body_table_height;
810 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
812 // separator header/table
813 pos_y += 1.25 * hud_fontsize_y;
814 tmp_y = autocvar_scoreboard_border_thickness;
815 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
817 pos_y += autocvar_scoreboard_border_thickness;
820 tmp_y = body_table_height;
822 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
824 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
826 // anyway, apply some color
827 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
829 // go back to the top to make alternated columns highlighting and to print the strings
830 pos_y -= 1.25 * hud_fontsize_y;
831 pos_y -= autocvar_scoreboard_border_thickness;
835 if (scoreboard_highlight)
837 column_dim_y = 1.25 * hud_fontsize_y; // header
838 column_dim_y += autocvar_scoreboard_border_thickness;
839 column_dim_y += body_table_height;
842 // print the strings of the columns headers and draw the columns
843 for(i = 0; i < hud_num_fields; ++i)
845 if(hud_field[i] == SP_SEPARATOR)
847 column_dim_x = hud_size[i] + hud_fontsize_x;
848 if (scoreboard_highlight)
851 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
853 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
854 pos_x += column_dim_x;
856 if(hud_field[i] == SP_SEPARATOR)
860 for(i = hud_num_fields-1; i > 0; --i)
862 if(hud_field[i] == SP_SEPARATOR)
865 pos_x -= hud_size[i];
867 if (scoreboard_highlight)
871 if (i == hud_num_fields-1)
872 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
874 column_dim_x = hud_size[i] + hud_fontsize_x;
875 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
879 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
880 tmp_x = (hud_size[i] - tmp_x);
881 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
882 pos_x -= hud_fontsize_x;
887 pos_y += 1.25 * hud_fontsize_y; // skip the header
888 pos_y += autocvar_scoreboard_border_thickness;
890 // fill the table and draw the rows
893 for(pl = players.sort_next; pl; pl = pl.sort_next)
895 if(pl.team != tm.team)
897 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i);
898 pos_y += 1.25 * hud_fontsize_y;
902 for(pl = players.sort_next; pl; pl = pl.sort_next)
904 if(pl.team == COLOR_SPECTATOR)
906 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), i);
907 pos_y += 1.25 * hud_fontsize_y;
912 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
913 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
918 float HUD_WouldDrawScoreboard() {
919 if (autocvar__hud_configure)
921 else if (scoreboard_showscores)
923 else if (intermission == 1)
925 else if (intermission == 2)
927 else if (spectatee_status != -1 && getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != GAME_CTS)
929 else if (scoreboard_showscores_force)
935 float average_accuracy;
936 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
939 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
941 if(autocvar_scoreboard_accuracy_doublerows)
946 float fontsize = height * 1/3;
947 float weapon_height = height * 2/3;
948 float weapon_width = sbwidth / weapon_cnt;
950 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
951 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
954 tmp_y = height * rows;
957 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
959 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
960 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
962 // column highlighting
963 for(i = 0; i < weapon_cnt/rows; ++i)
966 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);
970 for(i = 0; i < rows; ++i)
972 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);
975 average_accuracy = 0;
976 float weapons_with_stats;
977 weapons_with_stats = 0;
979 pos_x += weapon_width / 2;
981 if(getstati(STAT_SWITCHWEAPON) == WEP_MINSTANEX)
982 g_minstagib = 1; // TODO: real detection for minstagib?
984 float weapon_stats, weapon_number;
988 else if (acc_col_x[0] == -1)
989 for (i = 0; i < acc_levels; ++i)
990 acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i))));
992 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
994 self = get_weaponinfo(i);
997 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
999 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1002 if(weapon_stats >= 0)
1003 weapon_alpha = scoreboard_alpha_fg;
1005 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1008 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);
1010 if(weapon_stats >= 0) {
1011 weapons_with_stats += 1;
1012 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1015 s = sprintf(_("%d%%"), weapon_stats*100);
1018 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1022 // find the max level lower than weapon_stats
1025 while ( j && weapon_stats < acc_lev[j] )
1028 // inject color j+1 in color j, how much depending on how much weapon_stats is higher than level j
1030 factor = (weapon_stats - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
1032 rgb = rgb + factor * (acc_col[j+1] - rgb);
1035 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1037 pos_x += weapon_width * rows;
1038 if(rows == 2 && i == 6) {
1044 if(weapons_with_stats)
1045 average_accuracy = floor(average_accuracy / weapons_with_stats);
1048 pos_x -= weapon_width / 2;
1052 pos_y += 1.25 * hud_fontsize_y;
1056 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1059 RANKINGS_RECEIVED_CNT = 0;
1060 for (i=RANKINGS_CNT-1; i>=0; --i)
1062 ++RANKINGS_RECEIVED_CNT;
1064 if (RANKINGS_RECEIVED_CNT == 0)
1068 is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
1070 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1071 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1072 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1074 pos_y += hud_fontsize_y;
1075 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1076 pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness;
1079 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1082 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1084 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1085 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1088 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1095 n = grecordholder[i];
1096 p = race_PlaceName(i+1);
1097 if(grecordholder[i] == GetPlayerName(player_localentnum - 1))
1098 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1099 else if(!mod(i, 2) && scoreboard_highlight)
1100 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1101 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1102 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);
1103 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1104 pos_y += 1.25 * hud_fontsize_y;
1106 pos_y += autocvar_scoreboard_border_thickness;
1111 float hud_woulddrawscoreboard_prev;
1112 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1113 void HUD_DrawScoreboard()
1115 float hud_woulddrawscoreboard;
1116 hud_woulddrawscoreboard = scoreboard_active;
1117 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1118 hud_woulddrawscoreboard_change = time;
1119 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1122 if(hud_woulddrawscoreboard) {
1123 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1124 if (scoreboard_fadeinspeed)
1125 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1127 scoreboard_fade_alpha = 1;
1130 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1131 if (scoreboard_fadeoutspeed)
1132 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1134 scoreboard_fade_alpha = 0;
1137 if not(scoreboard_fade_alpha)
1140 HUD_UpdatePlayerTeams();
1142 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1143 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1144 scoreboard_highlight = autocvar_scoreboard_highlight;
1145 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1146 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1147 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1148 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1150 vector rgb, pos, tmp;
1154 xmin = autocvar_scoreboard_offset_left * vid_conwidth;
1155 ymin = autocvar_con_notify * autocvar_con_notifysize;
1157 xmax = (1 - autocvar_scoreboard_offset_right) * vid_conwidth;
1158 ymax = vid_conheight - ymin;
1160 sbwidth = xmax - xmin;
1162 // Initializes position
1168 vector sb_heading_fontsize;
1169 sb_heading_fontsize = hud_fontsize * 2;
1170 drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1172 centerprint_start_x = vid_conwidth - 0.5 * (pos_x + stringwidth(_("Scoreboard"), FALSE, sb_heading_fontsize));
1173 centerprint_start_y = pos_y;
1175 pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25;
1177 // Draw the scoreboard
1178 vector bg_size = drawgetimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1182 vector team_score_baseoffset;
1183 team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25);
1184 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1186 if(tm.team == COLOR_SPECTATOR)
1189 rgb = GetTeamRGB(tm.team);
1190 str = ftos(tm.(teamscores[ts_primary]));
1191 drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1193 if(ts_primary != ts_secondary)
1195 str = ftos(tm.(teamscores[ts_secondary]));
1196 drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize) + eY * hud_fontsize_y * 1.5, str, hud_fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1198 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1203 rgb_x = autocvar_scoreboard_color_bg_r;
1204 rgb_y = autocvar_scoreboard_color_bg_g;
1205 rgb_z = autocvar_scoreboard_color_bg_b;
1207 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1209 if(tm.team == COLOR_SPECTATOR)
1212 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1216 if(gametype == GAME_CTS || gametype == GAME_RACE) {
1217 if(race_speedaward) {
1218 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1219 pos_y += 1.25 * hud_fontsize_y;
1221 if(race_speedaward_alltimebest) {
1222 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1223 pos_y += 1.25 * hud_fontsize_y;
1225 pos = HUD_DrawScoreboardRankings(pos, pl, rgb, bg_size);
1227 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1229 pos = HUD_DrawScoreboardAccuracyStats(pos, GetTeamRGB(myteam), bg_size);
1231 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1238 for(pl = players.sort_next; pl; pl = pl.sort_next)
1240 if(pl.team != COLOR_SPECTATOR)
1242 pos_y += 1.25 * hud_fontsize_y;
1243 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localentnum - 1), specs);
1249 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1250 pos_y += 1.25 * hud_fontsize_y;
1253 // Print info string
1255 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1256 tl = getstatf(STAT_TIMELIMIT);
1257 fl = getstatf(STAT_FRAGLIMIT);
1258 ll = getstatf(STAT_LEADLIMIT);
1259 if(gametype == GAME_LMS)
1262 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1267 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1271 str = strcat(str, _(" or"));
1274 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1275 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1276 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1277 TranslateScoresLabel(teamscores_label[ts_primary])));
1281 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1282 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1283 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1284 TranslateScoresLabel(scores_label[ps_primary])));
1289 if(tl > 0 || fl > 0)
1290 str = strcat(str, _(" or"));
1293 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1294 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1295 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1296 TranslateScoresLabel(teamscores_label[ts_primary])));
1300 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1301 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1302 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1303 TranslateScoresLabel(scores_label[ps_primary])));
1309 pos_y += 1.2 * hud_fontsize_y;
1310 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1312 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;