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"));
57 void Cmd_HUD_SetFields(float argc);
62 ps_primary = ps_secondary = ts_primary = ts_secondary = -1;
63 for(i = 0; i < MAX_SCORE; ++i)
65 f = (scores_flags[i] & SFL_SORT_PRIO_MASK);
66 if(f == SFL_SORT_PRIO_PRIMARY)
68 if(f == SFL_SORT_PRIO_SECONDARY)
71 if(ps_secondary == -1)
72 ps_secondary = ps_primary;
74 for(i = 0; i < MAX_TEAMSCORE; ++i)
76 f = (teamscores_flags[i] & SFL_SORT_PRIO_MASK);
77 if(f == SFL_SORT_PRIO_PRIMARY)
79 if(f == SFL_SORT_PRIO_SECONDARY)
82 if(ts_secondary == -1)
83 ts_secondary = ts_primary;
88 void HUD_UpdatePlayerPos(entity pl);
89 float SetTeam(entity pl, float Team);
91 void HUD_UpdatePlayerTeams()
98 for(pl = players.sort_next; pl; pl = pl.sort_next)
101 Team = GetPlayerColor(pl.sv_entnum);
102 if(SetTeam(pl, Team))
105 HUD_UpdatePlayerPos(pl);
109 pl = players.sort_next;
114 print(strcat("PNUM: ", ftos(num), "\n"));
119 float HUD_CompareScore(float vl, float vr, float f)
121 if(f & SFL_ZERO_IS_WORST)
123 if(vl == 0 && vr != 0)
125 if(vl != 0 && vr == 0)
129 return IS_INCREASING(f);
131 return IS_DECREASING(f);
135 float HUD_ComparePlayerScores(entity left, entity right)
138 vl = GetPlayerColor(left.sv_entnum);
139 vr = GetPlayerColor(right.sv_entnum);
151 if(vl == NUM_SPECTATOR)
153 // FIRST the one with scores (spectators), THEN the ones without (downloaders)
155 if(!left.gotscores && right.gotscores)
160 r = HUD_CompareScore(left.scores[ps_primary], right.scores[ps_primary], scores_flags[ps_primary]);
164 r = HUD_CompareScore(left.scores[ps_secondary], right.scores[ps_secondary], scores_flags[ps_secondary]);
168 for(i = 0; i < MAX_SCORE; ++i)
170 r = HUD_CompareScore(left.scores[i], right.scores[i], scores_flags[i]);
175 if (left.sv_entnum < right.sv_entnum)
181 void HUD_UpdatePlayerPos(entity player)
183 for(other = player.sort_next; other && HUD_ComparePlayerScores(player, other); other = player.sort_next)
185 SORT_SWAP(player, other);
187 for(other = player.sort_prev; other != players && HUD_ComparePlayerScores(other, player); other = player.sort_prev)
189 SORT_SWAP(other, player);
193 float HUD_CompareTeamScores(entity left, entity right)
197 if(left.team == NUM_SPECTATOR)
199 if(right.team == NUM_SPECTATOR)
202 r = HUD_CompareScore(left.teamscores[ts_primary], right.teamscores[ts_primary], teamscores_flags[ts_primary]);
206 r = HUD_CompareScore(left.teamscores[ts_secondary], right.teamscores[ts_secondary], teamscores_flags[ts_secondary]);
210 for(i = 0; i < MAX_SCORE; ++i)
212 r = HUD_CompareScore(left.teamscores[i], right.teamscores[i], teamscores_flags[i]);
217 if (left.team < right.team)
223 void HUD_UpdateTeamPos(entity Team)
225 for(other = Team.sort_next; other && HUD_CompareTeamScores(Team, other); other = Team.sort_next)
227 SORT_SWAP(Team, other);
229 for(other = Team.sort_prev; other != teams && HUD_CompareTeamScores(other, Team); other = Team.sort_prev)
231 SORT_SWAP(other, Team);
237 print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
238 print(_("^3|---------------------------------------------------------------|\n"));
239 print(_("Usage:\n"));
240 print(_("^2scoreboard_columns_set default\n"));
241 print(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
242 print(_("The following field names are recognized (case insensitive):\n"));
243 print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
245 print(_("^3name^7 or ^3nick^7 Name of a player\n"));
246 print(_("^3ping^7 Ping time\n"));
247 print(_("^3pl^7 Packet loss\n"));
248 print(_("^3kills^7 Number of kills\n"));
249 print(_("^3deaths^7 Number of deaths\n"));
250 print(_("^3suicides^7 Number of suicides\n"));
251 print(_("^3frags^7 kills - suicides\n"));
252 print(_("^3kd^7 The kill-death ratio\n"));
253 print(_("^3sum^7 frags - deaths\n"));
254 print(_("^3caps^7 How often a flag (CTF) or a key (KeyHunt) was captured\n"));
255 print(_("^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
256 print(_("^3captime^7 Time of fastest cap (CTF)\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 "+tdm/kills +tdm/deaths +tdm/suicides ",
296 "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes ",
297 "+lms/lives +lms/rank ",
298 "+kh/caps +kh/pushes +kh/destroyed ",
299 "?+race/laps ?+race/time ?+race/fastest ",
300 "+as/objectives +nexball/faults +nexball/goals +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ",
301 "-lms,race,nexball/score");
304 void Cmd_HUD_SetFields(float argc)
308 float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
311 // TODO: re enable with gametype dependant cvars?
312 if(argc < 3) // no arguments provided
313 argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
316 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
320 if(argv(2) == "default")
321 argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
322 else if(argv(2) == "all")
325 s = "ping pl name |";
326 for(i = 0; i < MAX_SCORE; ++i)
329 if(i != ps_secondary)
330 if(scores_label[i] != "")
331 s = strcat(s, " ", scores_label[i]);
333 if(ps_secondary != ps_primary)
334 s = strcat(s, " ", scores_label[ps_secondary]);
335 s = strcat(s, " ", scores_label[ps_primary]);
336 argc = tokenizebyseparator(strcat("0 1 ", s), " ");
343 hud_fontsize = HUD_GetFontsize("hud_fontsize");
345 draw_beginBoldFont();
346 for(i = 1; i < argc - 1; ++i)
352 if(substring(str, 0, 1) == "?")
355 str = substring(str, 1, strlen(str) - 1);
358 slash = strstrofs(str, "/", 0);
361 pattern = substring(str, 0, slash);
362 str = substring(str, slash + 1, strlen(str) - (slash + 1));
364 if (!isGametypeInFilter(gametype, teamplay, FALSE, pattern))
368 strunzone(hud_title[hud_num_fields]);
369 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(str));
370 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
371 str = strtolower(str);
374 hud_field[hud_num_fields] = SP_PING;
375 } else if(str == "pl") {
376 hud_field[hud_num_fields] = SP_PL;
377 } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
378 hud_field[hud_num_fields] = SP_KDRATIO;
379 } else if(str == "sum" || str == "diff" || str == "f-d") {
380 hud_field[hud_num_fields] = SP_SUM;
381 } else if(str == "name" || str == "nick") {
382 hud_field[hud_num_fields] = SP_NAME;
384 } else if(str == "|") {
385 hud_field[hud_num_fields] = SP_SEPARATOR;
388 for(j = 0; j < MAX_SCORE; ++j)
389 if(str == strtolower(scores_label[j]))
390 goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
399 printf("^1Error:^7 Unknown score field: '%s'\n", str);
403 hud_field[hud_num_fields] = j;
406 if(j == ps_secondary)
410 if(hud_num_fields >= MAX_HUD_FIELDS)
414 if(scores_flags[ps_primary] & SFL_ALLOW_HIDE)
416 if(scores_flags[ps_secondary] & SFL_ALLOW_HIDE)
418 if(ps_primary == ps_secondary)
420 missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
422 if(hud_num_fields+missing < MAX_HUD_FIELDS)
426 strunzone(hud_title[hud_num_fields]);
427 for(i = hud_num_fields; i > 0; --i)
429 hud_title[i] = hud_title[i-1];
430 hud_size[i] = hud_size[i-1];
431 hud_field[i] = hud_field[i-1];
433 hud_title[0] = strzone(TranslateScoresLabel("name"));
434 hud_field[0] = SP_NAME;
436 print("fixed missing field 'name'\n");
440 strunzone(hud_title[hud_num_fields]);
441 for(i = hud_num_fields; i > 1; --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[1] = strzone("|");
448 hud_field[1] = SP_SEPARATOR;
449 hud_size[1] = stringwidth("|", FALSE, hud_fontsize);
451 print("fixed missing field '|'\n");
454 else if(!have_separator)
456 strunzone(hud_title[hud_num_fields]);
457 hud_title[hud_num_fields] = strzone("|");
458 hud_size[hud_num_fields] = stringwidth("|", FALSE, hud_fontsize);
459 hud_field[hud_num_fields] = SP_SEPARATOR;
461 print("fixed missing field '|'\n");
465 strunzone(hud_title[hud_num_fields]);
466 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_secondary]));
467 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
468 hud_field[hud_num_fields] = ps_secondary;
470 printf("fixed missing field '%s'\n", scores_label[ps_secondary]);
474 strunzone(hud_title[hud_num_fields]);
475 hud_title[hud_num_fields] = strzone(TranslateScoresLabel(scores_label[ps_primary]));
476 hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
477 hud_field[hud_num_fields] = ps_primary;
479 printf("fixed missing field '%s'\n", scores_label[ps_primary]);
483 hud_field[hud_num_fields] = SP_END;
488 vector hud_field_rgb;
489 string hud_field_icon0;
490 string hud_field_icon1;
491 string hud_field_icon2;
492 vector hud_field_icon0_rgb;
493 vector hud_field_icon1_rgb;
494 vector hud_field_icon2_rgb;
495 float hud_field_icon0_alpha;
496 float hud_field_icon1_alpha;
497 float hud_field_icon2_alpha;
498 string HUD_GetField(entity pl, float field)
500 float tmp, num, denom, f;
502 hud_field_rgb = '1 1 1';
503 hud_field_icon0 = "";
504 hud_field_icon1 = "";
505 hud_field_icon2 = "";
506 hud_field_icon0_rgb = '1 1 1';
507 hud_field_icon1_rgb = '1 1 1';
508 hud_field_icon2_rgb = '1 1 1';
509 hud_field_icon0_alpha = 1;
510 hud_field_icon1_alpha = 1;
511 hud_field_icon2_alpha = 1;
516 return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
517 //str = getplayerkeyvalue(pl.sv_entnum, "ping");
521 tmp = max(0, min(220, f-80)) / 220;
522 hud_field_rgb = '1 1 1' - '0 1 1'*tmp;
528 f = pl.ping_packetloss;
529 tmp = pl.ping_movementloss;
530 if(f == 0 && tmp == 0)
532 str = ftos(ceil(f * 100));
534 str = strcat(str, "~", ftos(ceil(tmp * 100)));
535 tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
536 hud_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
540 if(ready_waiting && pl.ready)
542 hud_field_icon0 = "gfx/scoreboard/player_ready";
546 f = stof(getplayerkeyvalue(pl.sv_entnum, "colors"));
548 hud_field_icon0 = "gfx/scoreboard/playercolor_base";
549 hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
550 hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
551 hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
552 hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
555 return GetPlayerName(pl.sv_entnum);
558 f = pl.(scores[SP_KILLS]);
559 f -= pl.(scores[SP_SUICIDES]);
563 num = pl.(scores[SP_KILLS]);
564 denom = pl.(scores[SP_DEATHS]);
567 hud_field_rgb = '0 1 0';
568 str = sprintf("%d", num);
569 } else if(num <= 0) {
570 hud_field_rgb = '1 0 0';
571 str = sprintf("%.1f", num/denom);
573 str = sprintf("%.1f", num/denom);
577 f = pl.(scores[SP_KILLS]);
578 f -= pl.(scores[SP_DEATHS]);
581 hud_field_rgb = '0 1 0';
583 hud_field_rgb = '1 1 1';
585 hud_field_rgb = '1 0 0';
590 tmp = pl.(scores[field]);
591 f = scores_flags[field];
592 if(field == ps_primary)
593 hud_field_rgb = '1 1 0';
594 else if(field == ps_secondary)
595 hud_field_rgb = '0 1 1';
597 hud_field_rgb = '1 1 1';
598 return ScoreString(f, tmp);
603 float xmin, xmax, ymin, ymax, sbwidth;
604 float hud_fixscoreboardcolumnwidth_len;
605 float hud_fixscoreboardcolumnwidth_iconlen;
606 float hud_fixscoreboardcolumnwidth_marginlen;
608 string HUD_FixScoreboardColumnWidth(float i, string str)
612 field = hud_field[i];
614 hud_fixscoreboardcolumnwidth_iconlen = 0;
616 if(hud_field_icon0 != "")
618 sz = draw_getimagesize(hud_field_icon0);
620 if(hud_fixscoreboardcolumnwidth_iconlen < f)
621 hud_fixscoreboardcolumnwidth_iconlen = f;
624 if(hud_field_icon1 != "")
626 sz = draw_getimagesize(hud_field_icon1);
628 if(hud_fixscoreboardcolumnwidth_iconlen < f)
629 hud_fixscoreboardcolumnwidth_iconlen = f;
632 if(hud_field_icon2 != "")
634 sz = draw_getimagesize(hud_field_icon2);
636 if(hud_fixscoreboardcolumnwidth_iconlen < f)
637 hud_fixscoreboardcolumnwidth_iconlen = f;
640 hud_fixscoreboardcolumnwidth_iconlen *= hud_fontsize_y / hud_fontsize_x; // fix icon aspect
642 if(hud_fixscoreboardcolumnwidth_iconlen != 0)
643 hud_fixscoreboardcolumnwidth_marginlen = stringwidth(" ", FALSE, hud_fontsize);
645 hud_fixscoreboardcolumnwidth_marginlen = 0;
647 if(field == SP_NAME) // name gets all remaining space
650 namesize = sbwidth;// / hud_fontsize_x;
651 for(j = 0; j < hud_num_fields; ++j)
653 if (hud_field[i] != SP_SEPARATOR)
654 namesize -= hud_size[j] + hud_fontsize_x;
655 namesize += hud_fontsize_x;
656 hud_size[i] = namesize;
658 if (hud_fixscoreboardcolumnwidth_iconlen != 0)
659 namesize -= hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
660 str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
661 hud_fixscoreboardcolumnwidth_len = stringwidth(str, TRUE, hud_fontsize);
664 hud_fixscoreboardcolumnwidth_len = stringwidth(str, FALSE, hud_fontsize);
666 f = hud_fixscoreboardcolumnwidth_len + hud_fixscoreboardcolumnwidth_marginlen + hud_fixscoreboardcolumnwidth_iconlen;
673 void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
676 rgb = Team_ColorRGB(pl.team);
680 is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
682 if((rgb == '1 1 1') && (!is_spec)) {
683 rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
684 rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
685 rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
689 tmp_y = hud_fontsize_y * 1.25;
692 // alternated rows highlighting
694 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
695 else if((scoreboard_highlight) && (!mod(pl_number,2)))
696 drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
700 for(i = 0; i < hud_num_fields; ++i)
702 field = hud_field[i];
703 if(field == SP_SEPARATOR)
706 if(is_spec && field != SP_NAME && field != SP_PING) {
707 pos_x += hud_size[i] + hud_fontsize_x;
710 str = HUD_GetField(pl, field);
711 str = HUD_FixScoreboardColumnWidth(i, str);
713 pos_x += hud_size[i] + hud_fontsize_x;
715 if(field == SP_NAME) {
716 tmp_x = hud_size[i] - hud_fontsize_x*hud_fixscoreboardcolumnwidth_iconlen - hud_fixscoreboardcolumnwidth_marginlen + hud_fontsize_x;
718 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
720 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
722 tmp_x = hud_fixscoreboardcolumnwidth_len + hud_fontsize_x;
724 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
726 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
729 tmp_x = hud_size[i] + hud_fontsize_x;
730 if(hud_field_icon0 != "")
732 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);
734 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);
735 if(hud_field_icon1 != "")
737 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);
739 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);
740 if(hud_field_icon2 != "")
742 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);
744 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);
747 if(hud_field[i] == SP_SEPARATOR)
750 for(i = hud_num_fields-1; i > 0; --i)
752 field = hud_field[i];
753 if(field == SP_SEPARATOR)
756 if(is_spec && field != SP_NAME && field != SP_PING) {
757 pos_x -= hud_size[i] + hud_fontsize_x;
761 str = HUD_GetField(pl, field);
762 str = HUD_FixScoreboardColumnWidth(i, str);
764 if(field == SP_NAME) {
765 tmp_x = hud_fixscoreboardcolumnwidth_len; // left or right aligned? let's put it right...
767 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
769 drawcolorcodedstring(pos - tmp, str, hud_fontsize, scoreboard_alpha_name, DRAWFLAG_NORMAL);
771 tmp_x = hud_fixscoreboardcolumnwidth_len;
773 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name_self, DRAWFLAG_NORMAL);
775 drawstring(pos - tmp, str, hud_fontsize, hud_field_rgb, scoreboard_alpha_name, DRAWFLAG_NORMAL);
779 if(hud_field_icon0 != "")
781 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);
783 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);
784 if(hud_field_icon1 != "")
786 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);
788 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);
789 if(hud_field_icon2 != "")
791 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);
793 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);
794 pos_x -= hud_size[i] + hud_fontsize_x;
800 * HUD_Scoreboard_MakeTable
802 * Makes a table for a team (for all playing players in DM) and fills it
805 vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
807 float body_table_height, i;
808 vector tmp = '0 0 0', column_dim = '0 0 0';
811 body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
813 pos_y += autocvar_scoreboard_border_thickness;
817 tmp_y = 1.25 * hud_fontsize_y;
821 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, (rgb * autocvar_scoreboard_color_bg_team) + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
823 drawpic(pos, "gfx/scoreboard/scoreboard_tableheader", tmp, rgb + '0.5 0.5 0.5', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
826 tmp_y += autocvar_scoreboard_border_thickness;
827 tmp_y += body_table_height;
828 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL); // more transparency for the scoreboard
830 // separator header/table
831 pos_y += 1.25 * hud_fontsize_y;
832 tmp_y = autocvar_scoreboard_border_thickness;
833 drawfill(pos, tmp, '0 0 0', scoreboard_alpha_bg, DRAWFLAG_NORMAL);
835 pos_y += autocvar_scoreboard_border_thickness;
838 tmp_y = body_table_height;
840 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
842 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
844 // anyway, apply some color
845 //drawfill(pos, tmp + '2 0 0', rgb, 0.1, DRAWFLAG_NORMAL);
847 // go back to the top to make alternated columns highlighting and to print the strings
848 pos_y -= 1.25 * hud_fontsize_y;
849 pos_y -= autocvar_scoreboard_border_thickness;
853 if (scoreboard_highlight)
855 column_dim_y = 1.25 * hud_fontsize_y; // header
856 column_dim_y += autocvar_scoreboard_border_thickness;
857 column_dim_y += body_table_height;
860 // print the strings of the columns headers and draw the columns
861 draw_beginBoldFont();
862 for(i = 0; i < hud_num_fields; ++i)
864 if(hud_field[i] == SP_SEPARATOR)
866 column_dim_x = hud_size[i] + hud_fontsize_x;
867 if (scoreboard_highlight)
870 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
872 drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
873 pos_x += column_dim_x;
875 if(hud_field[i] == SP_SEPARATOR)
879 for(i = hud_num_fields-1; i > 0; --i)
881 if(hud_field[i] == SP_SEPARATOR)
884 pos_x -= hud_size[i];
886 if (scoreboard_highlight)
890 if (i == hud_num_fields-1)
891 column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
893 column_dim_x = hud_size[i] + hud_fontsize_x;
894 drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
898 tmp_x = stringwidth(hud_title[i], FALSE, hud_fontsize);
899 tmp_x = (hud_size[i] - tmp_x);
900 drawstring(pos + tmp, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
901 pos_x -= hud_fontsize_x;
907 pos_y += 1.25 * hud_fontsize_y; // skip the header
908 pos_y += autocvar_scoreboard_border_thickness;
910 // fill the table and draw the rows
913 for(pl = players.sort_next; pl; pl = pl.sort_next)
915 if(pl.team != tm.team)
917 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
918 pos_y += 1.25 * hud_fontsize_y;
922 for(pl = players.sort_next; pl; pl = pl.sort_next)
924 if(pl.team == NUM_SPECTATOR)
926 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
927 pos_y += 1.25 * hud_fontsize_y;
932 pos_y += 1.25 * hud_fontsize_y; // move to the end of the table
933 pos_y += 1.25 * hud_fontsize_y; // move empty row (out of the table)
938 float HUD_WouldDrawScoreboard() {
939 if (autocvar__hud_configure)
941 else if (HUD_Radar_Clickable())
943 else if (scoreboard_showscores)
945 else if (intermission == 1)
947 else if (intermission == 2)
949 else if (spectatee_status != -1 && getstati(STAT_HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS)
951 else if (scoreboard_showscores_force)
956 float average_accuracy;
957 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
960 float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
962 if(autocvar_scoreboard_accuracy_doublerows)
967 float fontsize = height * 1/3;
968 float weapon_height = height * 2/3;
969 float weapon_width = sbwidth / weapon_cnt;
970 float g_minstagib = 0;
972 drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
973 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
974 vector tmp = '0 0 0';
976 tmp_y = height * rows;
979 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
981 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
982 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
984 // column highlighting
985 for(i = 0; i < weapon_cnt/rows; ++i)
988 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);
992 for(i = 0; i < rows; ++i)
994 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);
997 average_accuracy = 0;
998 float weapons_with_stats;
999 weapons_with_stats = 0;
1001 pos_x += weapon_width / 2;
1003 if(switchweapon == WEP_MINSTANEX)
1004 g_minstagib = 1; // TODO: real detection for minstagib?
1007 if(autocvar_scoreboard_accuracy_nocolors)
1010 Accuracy_LoadColors();
1012 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
1014 self = get_weaponinfo(i);
1017 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
1019 weapon_stats = weapon_accuracy[i-WEP_FIRST];
1022 if(weapon_stats >= 0)
1023 weapon_alpha = scoreboard_alpha_fg;
1025 weapon_alpha = 0.2 * scoreboard_alpha_fg;
1028 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);
1030 if(weapon_stats >= 0) {
1031 weapons_with_stats += 1;
1032 average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
1035 s = sprintf(_("%d%%"), weapon_stats*100);
1038 padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
1040 if(!autocvar_scoreboard_accuracy_nocolors)
1041 rgb = Accuracy_GetColor(weapon_stats);
1043 drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1045 pos_x += weapon_width * rows;
1046 if(rows == 2 && i == 6) {
1052 if(weapons_with_stats)
1053 average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5);
1056 pos_x -= weapon_width / 2;
1060 pos_y += 1.25 * hud_fontsize_y;
1064 vector HUD_DrawKeyValue(vector pos, string key, string value) {
1066 pos_x += hud_fontsize_x * 0.25;
1067 drawstring(pos, key, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1068 pos_x = xmax - stringwidth(value, FALSE, hud_fontsize) - hud_fontsize_x * 0.25;
1069 drawstring(pos, value, hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1071 pos_y+= hud_fontsize_y;
1076 vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
1077 float stat_secrets_found, stat_secrets_total;
1078 float stat_monsters_killed, stat_monsters_total;
1082 // get monster stats
1083 stat_monsters_killed = getstatf(STAT_MONSTERS_KILLED);
1084 stat_monsters_total = getstatf(STAT_MONSTERS_TOTAL);
1086 // get secrets stats
1087 stat_secrets_found = getstatf(STAT_SECRETS_FOUND);
1088 stat_secrets_total = getstatf(STAT_SECRETS_TOTAL);
1090 // get number of rows
1091 if(stat_secrets_total)
1093 if(stat_monsters_total)
1096 // if no rows, return
1100 // draw table header
1101 drawstring(pos, _("Map stats:"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1102 pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
1105 vector tmp = '0 0 0';
1107 tmp_y = hud_fontsize_y * rows;
1110 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1112 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1113 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1116 if(stat_monsters_total)
1118 val = sprintf("%d/%d", stat_monsters_killed, stat_monsters_total);
1119 pos = HUD_DrawKeyValue(pos, _("Monsters killed:"), val);
1123 if(stat_secrets_total)
1125 val = sprintf("%d/%d", stat_secrets_found, stat_secrets_total);
1126 pos = HUD_DrawKeyValue(pos, _("Secrets found:"), val);
1130 pos_y += 1.25 * hud_fontsize_y;
1135 vector HUD_DrawScoreboardRankings(vector pos, entity pl, vector rgb, vector bg_size)
1138 RANKINGS_RECEIVED_CNT = 0;
1139 for (i=RANKINGS_CNT-1; i>=0; --i)
1141 ++RANKINGS_RECEIVED_CNT;
1143 if (RANKINGS_RECEIVED_CNT == 0)
1147 is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
1149 hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
1150 hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
1151 hl_rgb_z = autocvar_scoreboard_color_bg_b + 0.5;
1153 pos_y += hud_fontsize_y;
1154 drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1155 pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness;
1156 vector tmp = '0 0 0';
1158 tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
1161 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb * autocvar_scoreboard_color_bg_team, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1163 drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", bg_size, tmp, rgb, scoreboard_alpha_bg, DRAWFLAG_NORMAL);
1164 drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
1167 for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
1174 n = grecordholder[i];
1175 p = count_ordinal(i+1);
1176 if(grecordholder[i] == GetPlayerName(player_localnum))
1177 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
1178 else if(!mod(i, 2) && scoreboard_highlight)
1179 drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
1180 drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1181 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);
1182 drawcolorcodedstring(pos + '8 0 0' * hud_fontsize_y, n, '1 1 0' * hud_fontsize_y, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1183 pos_y += 1.25 * hud_fontsize_y;
1185 pos_y += autocvar_scoreboard_border_thickness;
1190 float hud_woulddrawscoreboard_prev;
1191 float hud_woulddrawscoreboard_change; // "time" at which HUD_WouldDrawScoreboard() changed
1192 void HUD_DrawScoreboard()
1194 float hud_woulddrawscoreboard;
1195 hud_woulddrawscoreboard = scoreboard_active;
1196 if(hud_woulddrawscoreboard != hud_woulddrawscoreboard_prev) {
1197 hud_woulddrawscoreboard_change = time;
1198 hud_woulddrawscoreboard_prev = hud_woulddrawscoreboard;
1201 if(hud_woulddrawscoreboard) {
1202 float scoreboard_fadeinspeed = autocvar_scoreboard_fadeinspeed;
1203 if (scoreboard_fadeinspeed)
1204 scoreboard_fade_alpha = bound (0, (time - hud_woulddrawscoreboard_change) * scoreboard_fadeinspeed, 1);
1206 scoreboard_fade_alpha = 1;
1209 float scoreboard_fadeoutspeed = autocvar_scoreboard_fadeoutspeed;
1210 if (scoreboard_fadeoutspeed)
1211 scoreboard_fade_alpha = bound (0, (1/scoreboard_fadeoutspeed - (time - hud_woulddrawscoreboard_change)) * scoreboard_fadeoutspeed, 1);
1213 scoreboard_fade_alpha = 0;
1216 if (!scoreboard_fade_alpha)
1219 HUD_UpdatePlayerTeams();
1221 scoreboard_alpha_bg = autocvar_scoreboard_alpha_bg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1222 scoreboard_alpha_fg = autocvar_scoreboard_alpha_fg * scoreboard_fade_alpha * (1 - autocvar__menu_alpha);
1223 scoreboard_highlight = autocvar_scoreboard_highlight;
1224 scoreboard_highlight_alpha = autocvar_scoreboard_highlight_alpha * scoreboard_alpha_fg;
1225 scoreboard_highlight_alpha_self = autocvar_scoreboard_highlight_alpha_self * scoreboard_alpha_fg;
1226 scoreboard_alpha_name = autocvar_scoreboard_alpha_name * scoreboard_alpha_fg;
1227 scoreboard_alpha_name_self = autocvar_scoreboard_alpha_name_self * scoreboard_alpha_fg;
1229 vector rgb, pos, tmp;
1233 xmin = (autocvar_scoreboard_offset_left * vid_conwidth);
1234 ymin = max((autocvar_con_notify * autocvar_con_notifysize), (autocvar_scoreboard_offset_vertical * vid_conwidth));
1236 xmax = ((1 - autocvar_scoreboard_offset_right) * vid_conwidth);
1237 ymax = (vid_conheight - ymin);
1239 sbwidth = xmax - xmin;
1241 // Initializes position
1247 vector sb_heading_fontsize;
1248 sb_heading_fontsize = hud_fontsize * 2;
1249 draw_beginBoldFont();
1250 drawstring(pos, _("Scoreboard"), sb_heading_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1253 pos_y += sb_heading_fontsize_y + hud_fontsize_y * 0.25;
1255 // Draw the scoreboard
1256 vector bg_size = draw_getimagesize("gfx/scoreboard/scoreboard_bg") * autocvar_scoreboard_bg_scale;
1260 vector team_score_baseoffset;
1261 team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25);
1262 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1264 if(tm.team == NUM_SPECTATOR)
1267 draw_beginBoldFont();
1268 rgb = Team_ColorRGB(tm.team);
1269 str = ftos(tm.(teamscores[ts_primary]));
1270 drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1272 if(ts_primary != ts_secondary)
1274 str = ftos(tm.(teamscores[ts_secondary]));
1275 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);
1279 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1285 rgb_x = autocvar_scoreboard_color_bg_r;
1286 rgb_y = autocvar_scoreboard_color_bg_g;
1287 rgb_z = autocvar_scoreboard_color_bg_b;
1294 rgb_x = autocvar_scoreboard_color_bg_r;
1295 rgb_y = autocvar_scoreboard_color_bg_g;
1296 rgb_z = autocvar_scoreboard_color_bg_b;
1298 for(tm = teams.sort_next; tm; tm = tm.sort_next)
1300 if(tm.team == NUM_SPECTATOR)
1303 pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
1307 if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) {
1308 if(race_speedaward) {
1309 drawcolorcodedstring(pos, sprintf(_("Speed award: %d ^7(%s^7)"), race_speedaward, race_speedaward_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1310 pos_y += 1.25 * hud_fontsize_y;
1312 if(race_speedaward_alltimebest) {
1313 drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1314 pos_y += 1.25 * hud_fontsize_y;
1316 pos = HUD_DrawScoreboardRankings(pos, playerslots[player_localnum], rgb, bg_size);
1318 else if(autocvar_scoreboard_accuracy && spectatee_status == 0 && !warmup_stage && gametype != MAPINFO_TYPE_NEXBALL) {
1320 pos = HUD_DrawScoreboardAccuracyStats(pos, Team_ColorRGB(myteam), bg_size);
1322 pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
1327 pos = HUD_DrawMapStats(pos, Team_ColorRGB(myteam), bg_size);
1329 pos = HUD_DrawMapStats(pos, rgb, bg_size);
1335 for(pl = players.sort_next; pl; pl = pl.sort_next)
1337 if(pl.team != NUM_SPECTATOR)
1339 pos_y += 1.25 * hud_fontsize_y;
1340 HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
1346 draw_beginBoldFont();
1347 drawstring(tmp, _("Spectators"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1349 pos_y += 1.25 * hud_fontsize_y;
1352 // Print info string
1354 str = sprintf(_("playing ^3%s^7 on ^2%s^7"), MapInfo_Type_ToText(gametype), shortmapname);
1355 tl = getstatf(STAT_TIMELIMIT);
1356 fl = getstatf(STAT_FRAGLIMIT);
1357 ll = getstatf(STAT_LEADLIMIT);
1358 if(gametype == MAPINFO_TYPE_LMS)
1361 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1366 str = strcat(str, sprintf(_(" for up to ^1%1.0f minutes^7"), tl));
1370 str = strcat(str, _(" or"));
1373 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], fl),
1374 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1375 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1376 TranslateScoresLabel(teamscores_label[ts_primary])));
1380 str = strcat(str, sprintf(_(" until ^3%s %s^7"), ScoreString(scores_flags[ps_primary], fl),
1381 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1382 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1383 TranslateScoresLabel(scores_label[ps_primary])));
1388 if(tl > 0 || fl > 0)
1389 str = strcat(str, _(" or"));
1392 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(teamscores_flags[ts_primary], ll),
1393 (teamscores_label[ts_primary] == "score") ? CTX(_("SCO^points")) :
1394 (teamscores_label[ts_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1395 TranslateScoresLabel(teamscores_label[ts_primary])));
1399 str = strcat(str, sprintf(_(" until a lead of ^3%s %s^7"), ScoreString(scores_flags[ps_primary], ll),
1400 (scores_label[ps_primary] == "score") ? CTX(_("SCO^points")) :
1401 (scores_label[ps_primary] == "fastest") ? CTX(_("SCO^is beaten")) :
1402 TranslateScoresLabel(scores_label[ps_primary])));
1407 pos_y += 1.2 * hud_fontsize_y;
1408 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1410 // print information about respawn status
1411 float respawn_time = getstatf(STAT_RESPAWN_TIME);
1415 if(respawn_time < 0)
1417 // a negative number means we are awaiting respawn, time value is still the same
1418 respawn_time *= -1; // remove mark now that we checked it
1419 respawn_time = max(time, respawn_time); // don't show a negative value while the server is respawning the player (lag)
1421 str = sprintf(_("^1Respawning in ^3%s^1..."),
1422 (autocvar_scoreboard_respawntime_decimals ?
1423 count_seconds_decs(respawn_time - time, autocvar_scoreboard_respawntime_decimals)
1425 count_seconds(respawn_time - time)
1429 else if(time < respawn_time)
1431 str = sprintf(_("You are dead, wait ^3%s^7 before respawning"),
1432 (autocvar_scoreboard_respawntime_decimals ?
1433 count_seconds_decs(respawn_time - time, autocvar_scoreboard_respawntime_decimals)
1435 count_seconds(respawn_time - time)
1439 else if(time >= respawn_time)
1440 str = sprintf(_("You are dead, press ^2%s^7 to respawn"), getcommandkey("jump", "+jump"));
1442 pos_y += 1.2 * hud_fontsize_y;
1443 drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
1446 scoreboard_bottom = pos_y + 2 * hud_fontsize_y;