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 const 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 "captime": return CTX(_("SCO^captime"));
23 case "deaths": return CTX(_("SCO^deaths"));
24 case "destroyed": return CTX(_("SCO^destroyed"));
25 case "drops": return CTX(_("SCO^drops"));
26 case "faults": return CTX(_("SCO^faults"));
27 case "fckills": return CTX(_("SCO^fckills"));
28 case "goals": return CTX(_("SCO^goals"));
29 case "kckills": return CTX(_("SCO^kckills"));
30 case "kdratio": return CTX(_("SCO^kdratio"));
31 case "k/d": return CTX(_("SCO^k/d"));
32 case "kd": return CTX(_("SCO^kd"));
33 case "kdr": return CTX(_("SCO^kdr"));
34 case "kills": return CTX(_("SCO^kills"));
35 case "laps": return CTX(_("SCO^laps"));
36 case "lives": return CTX(_("SCO^lives"));
37 case "losses": return CTX(_("SCO^losses"));
38 case "name": return CTX(_("SCO^name"));
39 case "sum": return CTX(_("SCO^sum"));
40 case "nick": return CTX(_("SCO^nick"));
41 case "objectives": return CTX(_("SCO^objectives"));
42 case "pickups": return CTX(_("SCO^pickups"));
43 case "ping": return CTX(_("SCO^ping"));
44 case "pl": return CTX(_("SCO^pl"));
45 case "pushes": return CTX(_("SCO^pushes"));
46 case "rank": return CTX(_("SCO^rank"));
47 case "returns": return CTX(_("SCO^returns"));
48 case "revivals": return CTX(_("SCO^revivals"));
49 case "score": return CTX(_("SCO^score"));
50 case "suicides": return CTX(_("SCO^suicides"));
51 case "takes": return CTX(_("SCO^takes"));
52 case "ticks": return CTX(_("SCO^ticks"));
58 void HUD_FinaleOverlay()
61 pos_x = (vid_conwidth - 1)/2;
65 //drawpic(pos, "gfx/finale", '0 0 0', '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
67 //drawstring(pos, "END", hud_fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
71 void Cmd_HUD_SetFields(float argc);
76 ps_primary = ps_secondary = ts_primary = ts_secondary = -1;
77 for(i = 0; i < MAX_SCORE; ++i)
79 f = (scores_flags[i] & SFL_SORT_PRIO_MASK);
80 if(f == SFL_SORT_PRIO_PRIMARY)
82 if(f == SFL_SORT_PRIO_SECONDARY)
85 if(ps_secondary == -1)
86 ps_secondary = ps_primary;
88 for(i = 0; i < MAX_TEAMSCORE; ++i)
90 f = (teamscores_flags[i] & SFL_SORT_PRIO_MASK);
91 if(f == SFL_SORT_PRIO_PRIMARY)
93 if(f == SFL_SORT_PRIO_SECONDARY)
96 if(ts_secondary == -1)
97 ts_secondary = ts_primary;
102 void HUD_UpdatePlayerPos(entity pl);
103 float SetTeam(entity pl, float Team);
105 void HUD_UpdatePlayerTeams()
112 for(pl = players.sort_next; pl; pl = pl.sort_next)
115 Team = GetPlayerColor(pl.sv_entnum);
116 if(SetTeam(pl, Team))
119 HUD_UpdatePlayerPos(pl);
123 pl = players.sort_next;
128 print(strcat("PNUM: ", ftos(num), "\n"));
133 float HUD_CompareScore(float vl, float vr, float f)
135 if(f & SFL_ZERO_IS_WORST)
137 if(vl == 0 && vr != 0)
139 if(vl != 0 && vr == 0)
143 return IS_INCREASING(f);
145 return IS_DECREASING(f);
149 float HUD_ComparePlayerScores(entity left, entity right)
152 vl = GetPlayerColor(left.sv_entnum);
153 vr = GetPlayerColor(right.sv_entnum);
165 if(vl == NUM_SPECTATOR)
167 // FIRST the one with scores (spectators), THEN the ones without (downloaders)
169 if(!left.gotscores && right.gotscores)
174 r = HUD_CompareScore(left.scores[ps_primary], right.scores[ps_primary], scores_flags[ps_primary]);
178 r = HUD_CompareScore(left.scores[ps_secondary], right.scores[ps_secondary], scores_flags[ps_secondary]);
182 for(i = 0; i < MAX_SCORE; ++i)
184 r = HUD_CompareScore(left.scores[i], right.scores[i], scores_flags[i]);
189 if (left.sv_entnum < right.sv_entnum)
195 void HUD_UpdatePlayerPos(entity player)
197 for(other = player.sort_next; other && HUD_ComparePlayerScores(player, other); other = player.sort_next)
199 SORT_SWAP(player, other);
201 for(other = player.sort_prev; other != players && HUD_ComparePlayerScores(other, player); other = player.sort_prev)
203 SORT_SWAP(other, player);
207 float HUD_CompareTeamScores(entity left, entity right)
211 if(left.team == NUM_SPECTATOR)
213 if(right.team == NUM_SPECTATOR)
216 r = HUD_CompareScore(left.teamscores[ts_primary], right.teamscores[ts_primary], teamscores_flags[ts_primary]);
220 r = HUD_CompareScore(left.teamscores[ts_secondary], right.teamscores[ts_secondary], teamscores_flags[ts_secondary]);
224 for(i = 0; i < MAX_SCORE; ++i)
226 r = HUD_CompareScore(left.teamscores[i], right.teamscores[i], teamscores_flags[i]);
231 if (left.team < right.team)
237 void HUD_UpdateTeamPos(entity Team)
239 for(other = Team.sort_next; other && HUD_CompareTeamScores(Team, other); other = Team.sort_next)
241 SORT_SWAP(Team, other);
243 for(other = Team.sort_prev; other != teams && HUD_CompareTeamScores(other, Team); other = Team.sort_prev)
245 SORT_SWAP(other, Team);
251 print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
252 print(_("^3|---------------------------------------------------------------|\n"));
253 print(_("Usage:\n"));
254 print(_("^2scoreboard_columns_set default\n"));
255 print(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
256 print(_("The following field names are recognized (case insensitive):\n"));
257 print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
259 print(_("^3name^7 or ^3nick^7 Name of a player\n"));
260 print(_("^3ping^7 Ping time\n"));
261 print(_("^3pl^7 Packet loss\n"));
262 print(_("^3kills^7 Number of kills\n"));
263 print(_("^3deaths^7 Number of deaths\n"));
264 print(_("^3suicides^7 Number of suicides\n"));
265 print(_("^3frags^7 kills - suicides\n"));
266 print(_("^3kd^7 The kill-death ratio\n"));
267 print(_("^3sum^7 frags - deaths\n"));
268 print(_("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n"));
269 print(_("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
270 print(_("^3captime^7 Time of fastest cap (CTF)\n"));
271 print(_("^3fckills^7 Number of flag carrier kills\n"));
272 print(_("^3returns^7 Number of flag returns\n"));
273 print(_("^3drops^7 Number of flag drops\n"));
274 print(_("^3lives^7 Number of lives (LMS)\n"));
275 print(_("^3rank^7 Player rank\n"));
276 print(_("^3pushes^7 Number of players pushed into void\n"));
277 print(_("^3destroyed^7 Number of keys destroyed by pushing them into void\n"));
278 print(_("^3kckills^7 Number of keys carrier kills\n"));
279 print(_("^3losses^7 Number of times a key was lost\n"));
280 print(_("^3laps^7 Number of laps finished (race/cts)\n"));
281 print(_("^3time^7 Total time raced (race/cts)\n"));
282 print(_("^3fastest^7 Time of fastest lap (race/cts)\n"));
283 print(_("^3ticks^7 Number of ticks (DOM)\n"));
284 print(_("^3takes^7 Number of domination points taken (DOM)\n"));
285 print(_("^3bckills^7 Number of ball carrier kills\n"));
286 print(_("^3bctime^7 Total amount of time holding the ball in Keepaway\n"));
287 print(_("^3score^7 Total score\n\n"));
289 print(_("Before a field you can put a + or - sign, then a comma separated list\n"
290 "of game types, then a slash, to make the field show up only in these\n"
291 "or in all but these game types. You can also specify 'all' as a\n"
292 "field to show all fields available for the current game mode.\n\n"));
294 print(_("The special game type names 'teams' and 'noteams' can be used to\n"
295 "include/exclude ALL teams/noteams game modes.\n\n"));
297 print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
298 print(_("will display name, ping and pl aligned to the left, and the fields\n"
299 "right of the vertical bar aligned to the right.\n"));
300 print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
301 "other gamemodes except DM.\n"));
304 string HUD_DefaultColumnLayout()
306 return strcat( // fteqcc sucks
308 "-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"
309 "+tdm/kills +tdm/deaths +tdm/suicides ",
310 "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns ",
311 "+lms/lives +lms/rank ",
312 "+kh/caps +kh/pushes +kh/destroyed ",
313 "?+race/laps ?+race/time ?+race/fastest ",
314 "+as/objectives +nexball/faults +nexball/goals +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ",
315 "-lms,race,nexball/score");
318 void Cmd_HUD_SetFields(float argc)
322 float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
325 // TODO: re enable with gametype dependant cvars?
326 if(argc < 3) // no arguments provided
327 argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
330 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
334 if(argv(2) == "default")
335 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
336 else if(argv(2) == "all")
339 s = "ping pl name |";
340 for(i = 0; i < MAX_SCORE; ++i)
343 if(i != ps_secondary)
344 if(scores_label[i] != "")
345 s = strcat(s, " ", scores_label[i]);
347 if(ps_secondary != ps_primary)
348 s = strcat(s, " ", scores_label[ps_secondary]);
349 s = strcat(s, " ", scores_label[ps_primary]);
350 argc = tokenizebyseparator(strcat("0 1 ", s), " ");
357 hud_fontsize = HUD_GetFontsize("hud_fontsize");
359 draw_beginBoldFont();
360 for(i = 1; i < argc - 1; ++i)
366 if(substring(str, 0, 1) == "?")
369 str = substring(str, 1, strlen(str) - 1);
372 slash = strstrofs(str, "/", 0);
375 pattern = substring(str, 0, slash);
376 str = substring(str, slash + 1, strlen(str) - (slash + 1));
378 if (!isGametypeInFilter(gametype, teamplay, FALSE, pattern))
382 strunzone(hud_title[hud_num_fields]);
383 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
384 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
385 str = strtolower(str);
388 hud_field[hud_num_fields] = SP_PING;
389 } else if(str == "pl") {
390 hud_field[hud_num_fields] = SP_PL;
391 } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
392 hud_field[hud_num_fields] = SP_KDRATIO;
393 } else if(str == "sum" || str == "diff" || str == "f-d") {
394 hud_field[hud_num_fields] = SP_SUM;
395 } else if(str == "name" || str == "nick") {
396 hud_field[hud_num_fields] = SP_NAME;
398 } else if(str == "|") {
399 hud_field[hud_num_fields] = SP_SEPARATOR;
402 for(j = 0; j < MAX_SCORE; ++j)
403 if(str == strtolower(scores_label[j]))
404 goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
413 printf("^1Error:^7 Unknown score field: '%s'\n", str);
417 hud_field[hud_num_fields] = j;
420 if(j == ps_secondary)
424 if(hud_num_fields >= MAX_HUD_FIELDS)
428 if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
430 if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
432 if(ps_primary == ps_secondary)
434 missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
436 if(hud_num_fields+missing < MAX_HUD_FIELDS)
440 strunzone(hud_title[hud_num_fields]);
441 for(i = hud_num_fields; i > 0; --i)
443 hud_title[i] = hud_title[i-1];
444 hud_size[i] = hud_size[i-1];
445 hud_field[i] = hud_field[i-1];
447 hud_title[0] = strzone(TranslateScoresLabel("name"));
448 hud_field[0] = SP_NAME;
450 print("fixed missing field 'name'\n");
454 strunzone(hud_title[hud_num_fields]);
455 for(i = hud_num_fields; i > 1; --i)
457 hud_title[i] = hud_title[i-1];
458 hud_size[i] = hud_size[i-1];
459 hud_field[i] = hud_field[i-1];
461 hud_title[1] = strzone("|");
462 hud_field[1] = SP_SEPARATOR;
463 hud_size[1] = stringwidth("|", FALSE, hud_fontsize);
465 print("fixed missing field '|'\n");
468 else if(!have_separator)
470 strunzone(hud_title[hud_num_fields]);
471 hud_title[hud_num_fields] = strzone("|");
472 hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize);
473 hud_field[hud_num_fields] = SP_SEPARATOR;
475 print("fixed missing field '|'\n");
479 strunzone(hud_title[hud_num_fields]);
480 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
481 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
482 hud_field[hud_num_fields] = ps_secondary;
484 printf("fixed missing field '%s'\n", scores_label[ps_secondary]);
488 strunzone(hud_title[hud_num_fields]);
489 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
490 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
491 hud_field[hud_num_fields] = ps_primary;
493 printf("fixed missing field '%s'\n", scores_label[ps_primary]);
497 hud_field[hud_num_fields] = SP_END;
502 vector hud_field_rgb;
503 string hud_field_icon0;
504 string hud_field_icon1;
505 string hud_field_icon2;
506 vector hud_field_icon0_rgb;
507 vector hud_field_icon1_rgb;
508 vector hud_field_icon2_rgb;
509 float hud_field_icon0_alpha;
510 float hud_field_icon1_alpha;
511 float hud_field_icon2_alpha;
512 string HUD_GetField(entity pl, float field)
514 float tmp, num, denom, f;
516 hud_field_rgb = '1 1 1';
517 hud_field_icon0 = "";
518 hud_field_icon1 = "";
519 hud_field_icon2 = "";
520 hud_field_icon0_rgb = '1 1 1';
521 hud_field_icon1_rgb = '1 1 1';
522 hud_field_icon2_rgb = '1 1 1';
523 hud_field_icon0_alpha = 1;
524 hud_field_icon1_alpha = 1;
525 hud_field_icon2_alpha = 1;
530 return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
531 //str = getplayerkeyvalue(pl.sv_entnum, "ping");
535 tmp = max(0, min(220, f-80)) / 220;
536 hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
542 f = pl.ping_packetloss;
543 tmp = pl.ping_movementloss;
544 if(f == 0 && tmp == 0)
546 str = ftos(ceil(f * 100));
548 str = strcat(str, "~", ftos(ceil(tmp * 100)));
549 tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
550 hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
554 if(ready_waiting && pl.ready)
556 hud_field_icon0 = "gfx/scoreboard/player_ready";
560 f = stof(getplayerkeyvalue(pl.sv_entnum, "colors"));
562 hud_field_icon0 = "gfx/scoreboard/playercolor_base";
563 hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
564 hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
565 hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
566 hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
569 return GetPlayerName(pl.sv_entnum);
572 f = pl.(scores[SP_KILLS]);
573 f -= pl.(scores[SP_SUICIDES]);
577 num = pl.(scores[SP_KILLS]);
578 denom = pl.(scores[SP_DEATHS]);
581 hud_field_rgb = '0 1 0';
582 str = sprintf("%d", num);
583 } else if(num <= 0) {
584 hud_field_rgb = '1 0 0';
585 str = sprintf("%.1f", num/denom);
587 str = sprintf("%.1f", num/denom);
591 f = pl.(scores[SP_KILLS]);
592 f -= pl.(scores[SP_DEATHS]);
595 hud_field_rgb = '0 1 0';
597 hud_field_rgb = '1 1 1';
599 hud_field_rgb = '1 0 0';
604 tmp = pl.(scores[field]);
605 f = scores_flags[field];
606 if(field == ps_primary)
607 hud_field_rgb = '1 1 0';
608 else if(field == ps_secondary)
609 hud_field_rgb = '0 1 1';
611 hud_field_rgb = '1 1 1';
612 return ScoreString(f, tmp);
617 float xmin, xmax, ymin, ymax, sbwidth;
618 float hud_fixscoreboardcolumnwidth_len;
619 float hud_fixscoreboardcolumnwidth_iconlen;
620 float hud_fixscoreboardcolumnwidth_marginlen;
622 string HUD_FixScoreboardColumnWidth(float i, string str)
626 field = hud_field[i];
628 hud_fixscoreboardcolumnwidth_iconlen = 0;
630 if(hud_field_icon0 != "")
632 sz = draw_getimagesize(hud_field_icon0);
634 if(hud_fixscoreboardcolumnwidth_iconlen < f)
635 hud_fixscoreboardcolumnwidth_iconlen = f;
638 if(hud_field_icon1 != "")
640 sz = draw_getimagesize(hud_field_icon1);
642 if(hud_fixscoreboardcolumnwidth_iconlen < f)
643 hud_fixscoreboardcolumnwidth_iconlen = f;
646 if(hud_field_icon2 != "")
648 sz = draw_getimagesize(hud_field_icon2);
650 if(hud_fixscoreboardcolumnwidth_iconlen < f)
651 hud_fixscoreboardcolumnwidth_iconlen = f;
654 hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize_y / hud_fontsize_x; // fix icon aspect
656 if(hud_fixscoreboardcolumnwidth_iconlen != 0)
657 hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", FALSE, hud_fontsize);
659 hud_fixscoreboardcolumnwidth_marginlen = 0;
661 if(field == SP_NAME) // name gets all remaining space
664 namesize = sbwidth;// / hud_fontsize_x;
665 for(j = 0; j < hud_num_fields; ++j)
667 if (hud_field[i] != SP_SEPARATOR)
668 namesize -= hud_size[j] + hud_fontsize_x;
669 namesize += hud_fontsize_x;
670 hud_size[i] = namesize;
672 if (hud_fixscoreboardcolumnwidth_iconlen != 0)
673 namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
674 str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
675 hud_fixscoreboardcolumnwidth_len = stringwidth(str, TRUE, hud_fontsize);
678 hud_fixscoreboardcolumnwidth_len = stringwidth(str, FALSE, hud_fontsize);
680 f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
687 void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
690 rgb = Team_ColorRGB(pl.team);
694 is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
696 if((rgb == '1 1 1') && (!is_spec)) {
697 rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
698 rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
699 rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
703 tmp_y = hud_fontsize_y * 1.25;
706 // alternated rows highlighting
708 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
709 else if((scoreboard_highlight) && (!mod(pl_number,2)))
710 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
714 for(i = 0; i < hud_num_fields; ++i)
716 field = hud_field[i];
717 if(field == SP_SEPARATOR)
720 if(is_spec && field != SP_NAME && field != SP_PING) {
721 pos_x += hud_size[i] + hud_fontsize_x;
724 str = HUD_GetField(pl, field);
725 str = HUD_FixScoreboardColumnWidth(i, str);
727 pos_x += hud_size[i] + hud_fontsize_x;
729 if(field == SP_NAME) {
730 tmp_x = hud_size[i] - hud_fontsize_x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize_x;
732 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
734 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
736 tmp_x = hud_fixscoreboardcolumnwidth_len + hud_fontsize_x;
738 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
740 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
743 tmp_x = hud_size[i] + hud_fontsize_x;
744 if(hud_field_icon0 != "")
746 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);
748 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);
749 if(hud_field_icon1 != "")
751 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);
753 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);
754 if(hud_field_icon2 != "")
756 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);
758 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);
761 if(hud_field[i] == SP_SEPARATOR)
764 for(i = hud_num_fields-1; i > 0; --i)
766 field = hud_field[i];
767 if(field == SP_SEPARATOR)
770 if(is_spec && field != SP_NAME && field != SP_PING) {
771 pos_x -= hud_size[i] + hud_fontsize_x;
775 str = HUD_GetField(pl, field);
776 str = HUD_FixScoreboardColumnWidth(i, str);
778 if(field == SP_NAME) {
779 tmp_x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
781 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
783 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
785 tmp_x = hud_fixscoreboardcolumnwidth_len;
787 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
789 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
793 if(hud_field_icon0 != "")
795 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);
797 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);
798 if(hud_field_icon1 != "")
800 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);
802 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);
803 if(hud_field_icon2 != "")
805 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);
807 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);
808 pos_x -= hud_size[i] + hud_fontsize_x;
814 * HUD_Scoreboard_MakeTable
816 * Makes a table for a team (for all playing players in DM) and fills it
819 vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
821 float body_table_height, i;
822 vector tmp = '0 0 0', column_dim = '0 0 0';
825 body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
827 pos_y += autocvar_scoreboard_border_thickness;
831 tmp_y = 1.25 * hud_fontsize_y;
835 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
837 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
840 tmp_y += autocvar_scoreboard_border_thickness;
841 tmp_y += body_table_height;
842 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
844 // separator header/table
845 pos_y += 1.25 * hud_fontsize_y;
846 tmp_y = autocvar_scoreboard_border_thickness;
847 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
849 pos_y += autocvar_scoreboard_border_thickness;
852 tmp_y = body_table_height;
854 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
856 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
858 // anyway, apply some color
859 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
861 // go back to the top to make alternated columns highlighting and to print the strings
862 pos_y -= 1.25 * hud_fontsize_y;
863 pos_y -= autocvar_scoreboard_border_thickness;
867 if (scoreboard_highlight)
869 column_dim_y = 1.25 * hud_fontsize_y; // header
870 column_dim_y += autocvar_scoreboard_border_thickness;
871 column_dim_y += body_table_height;
874 // print the strings of the columns headers and draw the columns
875 draw_beginBoldFont();
876 for(i = 0; i < hud_num_fields; ++i)
878 if(hud_field[i] == SP_SEPARATOR)
880 column_dim_x = hud_size[i] + hud_fontsize_x;
881 if (scoreboard_highlight)
884 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
886 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
887 pos_x += column_dim_x;
889 if(hud_field[i] == SP_SEPARATOR)
893 for(i = hud_num_fields-1; i > 0; --i)
895 if(hud_field[i] == SP_SEPARATOR)
898 pos_x -= hud_size[i];
900 if (scoreboard_highlight)
904 if (i == hud_num_fields-1)
905 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
907 column_dim_x = hud_size[i] + hud_fontsize_x;
908 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
912 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
913 tmp_x = (hud_size[i] - tmp_x);
914 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
915 pos_x -= hud_fontsize_x;
921 pos_y += 1.25 * hud_fontsize_y; // skip the header
922 pos_y += autocvar_scoreboard_border_thickness;
924 // fill the table and draw the rows
927 for(pl = players.sort_next; pl; pl = pl.sort_next)
929 if(pl.team != tm.team)
931 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
932 pos_y += 1.25 * hud_fontsize_y;
936 for(pl = players.sort_next; pl; pl = pl.sort_next)
938 if(pl.team == NUM_SPECTATOR)
940 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
941 pos_y += 1.25 * hud_fontsize_y;
946 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
947 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
952 float HUD_WouldDrawScoreboard() {
953 if (autocvar__hud_configure)
955 else if (scoreboard_showscores)
957 else if (intermission == 1)
959 else if (intermission == 2)
961 else if (spectatee_status != -1 && getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS)
963 else if (scoreboard_showscores_force)
968 float average_accuracy;
969 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
972 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
974 if(autocvar_scoreboard_accuracy_doublerows)
979 float fontsize = height * 1/3;
980 float weapon_height = height * 2/3;
981 float weapon_width = sbwidth / weapon_cnt;
982 float g_minstagib = 0;
984 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
985 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
986 vector tmp = '0 0 0';
988 tmp_y = height * rows;
991 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
993 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
994 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
996 // column highlighting
997 for(i = 0; i < weapon_cnt/rows; ++i)
1000 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);
1004 for(i = 0; i < rows; ++i)
1006 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);
1009 average_accuracy = 0;
1010 float weapons_with_stats;
1011 weapons_with_stats = 0;
1013 pos_x += weapon_width / 2;
1015 if(switchweapon == WEP_MINSTANEX)
1016 g_minstagib = 1; // TODO: real detection for minstagib?
1019 if(autocvar_scoreboard_accuracy_nocolors)
1022 Accuracy_LoadColors();
1024 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
1026 self = get_weaponinfo(i);
1029 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
1031 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1034 if(weapon_stats >= 0)
1035 weapon_alpha = scoreboard_alpha_fg;
1037 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1040 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);
1042 if(weapon_stats >= 0) {
1043 weapons_with_stats += 1;
1044 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1047 s = sprintf(_("%d%%"), weapon_stats*100);
1050 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1052 if(!autocvar_scoreboard_accuracy_nocolors)
1053 rgb = Accuracy_GetColor(weapon_stats);
1055 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1057 pos_x += weapon_width * rows;
1058 if(rows == 2 && i == 6) {
1064 if(weapons_with_stats)
1065 average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5);
1068 pos_x -= weapon_width / 2;
1072 pos_y += 1.25 * hud_fontsize_y;
1076 vector HUD_DrawKeyValue(vector pos, string key, string value) {
1078 pos_x += hud_fontsize_x * 0.25;
1079 drawstring(pos, key, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1080 pos_x = xmax - stringwidth(value, FALSE, hud_fontsize) - hud_fontsize_x * 0.25;
1081 drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1083 pos_y+= hud_fontsize_y;
1088 vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
1089 float stat_secrets_found, stat_secrets_total;
1093 // get secrets stats
1094 stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
1095 stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
1097 // get number of rows
1098 rows = (stat_secrets_total ? 1 : 0);
1100 // if no rows, return
1104 // draw table header
1105 drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1106 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
1109 vector tmp = '0 0 0';
1111 tmp_y = hud_fontsize_y * rows;
1114 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1116 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1117 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1120 val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
1121 pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
1124 pos_y += 1.25 * hud_fontsize_y;
1129 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1132 RANKINGS_RECEIVED_CNT = 0;
1133 for (i=RANKINGS_CNT-1; i>=0; --i)
1135 ++RANKINGS_RECEIVED_CNT;
1137 if (RANKINGS_RECEIVED_CNT == 0)
1141 is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
1143 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1144 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1145 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1147 pos_y += hud_fontsize_y;
1148 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1149 pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness;
1150 vector tmp = '0 0 0';
1152 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1155 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1157 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1158 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1161 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1168 n = grecordholder[i];
1169 p = count_ordinal(i+1);
1170 if(grecordholder[i] == GetPlayerName(player_localnum))
1171 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1172 else if(!mod(i, 2) && scoreboard_highlight)
1173 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1174 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1175 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);
1176 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1177 pos_y += 1.25 * hud_fontsize_y;
1179 pos_y += autocvar_scoreboard_border_thickness;
1184 float hud_woulddrawscoreboard_prev;
1185 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1186 void HUD_DrawScoreboard()
1188 float hud_woulddrawscoreboard;
1189 hud_woulddrawscoreboard = scoreboard_active;
1190 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1191 hud_woulddrawscoreboard_change = time;
1192 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1195 if(hud_woulddrawscoreboard) {
1196 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1197 if (scoreboard_fadeinspeed)
1198 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1200 scoreboard_fade_alpha = 1;
1203 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1204 if (scoreboard_fadeoutspeed)
1205 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1207 scoreboard_fade_alpha = 0;
1210 if (!scoreboard_fade_alpha)
1213 HUD_UpdatePlayerTeams();
1215 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1216 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1217 scoreboard_highlight = autocvar_scoreboard_highlight;
1218 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1219 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1220 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1221 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1223 vector rgb, pos, tmp;
1227 xmin = (autocvar_scoreboard_offset_left * vid_conwidth);
1228 ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth));
1230 xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth);
1231 ymax = (vid_conheight - ymin);
1233 sbwidth = xmax - xmin;
1235 // Initializes position
1241 vector sb_heading_fontsize;
1242 sb_heading_fontsize = hud_fontsize * 2;
1243 draw_beginBoldFont();
1244 drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1247 pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25;
1249 // Draw the scoreboard
1250 vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1254 vector team_score_baseoffset;
1255 team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25);
1256 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1258 if(tm.team == NUM_SPECTATOR)
1261 draw_beginBoldFont();
1262 rgb = Team_ColorRGB(tm.team);
1263 str = ftos(tm.(teamscores[ts_primary]));
1264 drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1266 if(ts_primary != ts_secondary)
1268 str = ftos(tm.(teamscores[ts_secondary]));
1269 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);
1273 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1279 rgb_x = autocvar_scoreboard_color_bg_r;
1280 rgb_y = autocvar_scoreboard_color_bg_g;
1281 rgb_z = autocvar_scoreboard_color_bg_b;
1288 rgb_x = autocvar_scoreboard_color_bg_r;
1289 rgb_y = autocvar_scoreboard_color_bg_g;
1290 rgb_z = autocvar_scoreboard_color_bg_b;
1292 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1294 if(tm.team == NUM_SPECTATOR)
1297 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1301 if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) {
1302 if(race_speedaward) {
1303 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1304 pos_y += 1.25 * hud_fontsize_y;
1306 if(race_speedaward_alltimebest) {
1307 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1308 pos_y += 1.25 * hud_fontsize_y;
1310 pos = HUD_DrawScoreboardRankings(pos, playerslots[player_localnum], rgb, bg_size);
1312 else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
1314 pos = HUD_DrawScoreboardAccuracyStats(pos, Team_ColorRGB(myteam), bg_size);
1316 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1321 pos = HUD_DrawMapStats(pos, Team_ColorRGB(myteam), bg_size);
1323 pos = HUD_DrawMapStats(pos, rgb, bg_size);
1329 for(pl = players.sort_next; pl; pl = pl.sort_next)
1331 if(pl.team != NUM_SPECTATOR)
1333 pos_y += 1.25 * hud_fontsize_y;
1334 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
1340 draw_beginBoldFont();
1341 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1343 pos_y += 1.25 * hud_fontsize_y;
1346 // Print info string
1348 str = sprintf(_("playing on ^2%s^7"), shortmapname);
1349 tl = getstatf(STAT_TIMELIMIT);
1350 fl = getstatf(STAT_FRAGLIMIT);
1351 ll = getstatf(STAT_LEADLIMIT);
1352 if(gametype == MAPINFO_TYPE_LMS)
1355 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1360 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1364 str = strcat(str, _(" or"));
1367 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1368 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1369 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1370 TranslateScoresLabel(teamscores_label[ts_primary])));
1374 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1375 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1376 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1377 TranslateScoresLabel(scores_label[ps_primary])));
1382 if(tl > 0 || fl > 0)
1383 str = strcat(str, _(" or"));
1386 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1387 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1388 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1389 TranslateScoresLabel(teamscores_label[ts_primary])));
1393 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1394 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1395 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1396 TranslateScoresLabel(scores_label[ps_primary])));
1401 pos_y += 1.2 * hud_fontsize_y;
1402 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1404 // print information about respawn status
1405 float respawn_time = getstatf(STAT_RESPAWN_TIME);
1408 if(respawn_time < 0)
1410 // a negative number means we are awaiting respawn, time value is still the same
1411 respawn_time *= -1; // remove mark now that we checked it
1412 respawn_time = max(time, respawn_time); // don't show a negative value while the server is respawning the player (lag)
1414 str = sprintf(_("^1Respawning in ^3%s^1..."),
1415 (autocvar_scoreboard_respawntime_decimals ?
1416 count_seconds_decs(respawn_time - time, autocvar_scoreboard_respawntime_decimals)
1418 count_seconds(respawn_time - time)
1422 else if(time < respawn_time)
1424 str = sprintf(_("You are dead, wait ^3%s^7 before respawning"),
1425 (autocvar_scoreboard_respawntime_decimals ?
1426 count_seconds_decs(respawn_time - time, autocvar_scoreboard_respawntime_decimals)
1428 count_seconds(respawn_time - time)
1432 else if(time >= respawn_time)
1433 str = sprintf(_("You are dead, press ^2%s^7 to respawn"), getcommandkey("jump", "+jump"));
1435 pos_y += 1.2 * hud_fontsize_y;
1436 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1439 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;