1 // Mod icons panel (#10)
3 bool mod_active; // is there any active mod icon?
5 void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
9 vector color = '0 0 0';
13 stat = STAT(REDALIVE);
14 pic = "player_red.tga";
18 stat = STAT(BLUEALIVE);
19 pic = "player_blue.tga";
23 stat = STAT(YELLOWALIVE);
24 pic = "player_yellow.tga";
29 stat = STAT(PINKALIVE);
30 pic = "player_pink.tga";
35 if(mySize.x/mySize.y > aspect_ratio)
37 i = aspect_ratio * mySize.y;
38 myPos.x = myPos.x + (mySize.x - i) / 2;
43 i = 1/aspect_ratio * mySize.x;
44 myPos.y = myPos.y + (mySize.y - i) / 2;
50 drawpic_aspect_skin(myPos, pic, eX * 0.7 * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
51 drawstring_aspect(myPos + eX * 0.7 * mySize.x, ftos(stat), eX * 0.3 * mySize.x + eY * mySize.y, color, panel_fg_alpha, DRAWFLAG_NORMAL);
54 drawstring_aspect(myPos, ftos(stat), mySize, color, panel_fg_alpha, DRAWFLAG_NORMAL);
57 // Clan Arena and Freeze Tag HUD modicons
58 void HUD_Mod_CA(vector myPos, vector mySize)
60 mod_active = 1; // required in each mod function that always shows something
63 if(gametype == MAPINFO_TYPE_CA)
64 layout = autocvar_hud_panel_modicons_ca_layout;
65 else //if(gametype == MAPINFO_TYPE_FREEZETAG)
66 layout = autocvar_hud_panel_modicons_freezetag_layout;
69 aspect_ratio = (layout) ? 2 : 1;
70 rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
71 columns = ceil(team_count/rows);
74 float row = 0, column = 0;
76 itemSize = eX * mySize.x*(1/columns) + eY * mySize.y*(1/rows);
77 for(i=0; i<team_count; ++i)
79 pos = myPos + eX * column * itemSize.x + eY * row * itemSize.y;
81 DrawCAItem(pos, itemSize, aspect_ratio, layout, i);
92 // CTF HUD modicon section
93 int redflag_prevframe, blueflag_prevframe, yellowflag_prevframe, pinkflag_prevframe, neutralflag_prevframe; // status during previous frame
94 int redflag_prevstatus, blueflag_prevstatus, yellowflag_prevstatus, pinkflag_prevstatus, neutralflag_prevstatus; // last remembered status
95 float redflag_statuschange_time, blueflag_statuschange_time, yellowflag_statuschange_time, pinkflag_statuschange_time, neutralflag_statuschange_time; // time when the status changed
97 void HUD_Mod_CTF_Reset()
99 redflag_prevstatus = blueflag_prevstatus = yellowflag_prevstatus = pinkflag_prevstatus = neutralflag_prevstatus = 0;
100 redflag_prevframe = blueflag_prevframe = yellowflag_prevframe = pinkflag_prevframe = neutralflag_prevframe = 0;
101 redflag_statuschange_time = blueflag_statuschange_time = yellowflag_statuschange_time = pinkflag_statuschange_time = neutralflag_statuschange_time = 0;
104 void HUD_Mod_CTF(vector pos, vector mySize)
106 vector redflag_pos, blueflag_pos, yellowflag_pos, pinkflag_pos, neutralflag_pos;
108 float f; // every function should have that
110 int redflag, blueflag, yellowflag, pinkflag, neutralflag; // current status
111 float redflag_statuschange_elapsedtime, blueflag_statuschange_elapsedtime, yellowflag_statuschange_elapsedtime, pinkflag_statuschange_elapsedtime, neutralflag_statuschange_elapsedtime; // time since the status changed
112 bool ctf_oneflag; // one-flag CTF mode enabled/disabled
113 int stat_items = STAT(CTF_FLAGSTATUS);
114 float fs, fs2, fs3, size1, size2;
117 redflag = (stat_items/CTF_RED_FLAG_TAKEN) & 3;
118 blueflag = (stat_items/CTF_BLUE_FLAG_TAKEN) & 3;
119 yellowflag = (stat_items/CTF_YELLOW_FLAG_TAKEN) & 3;
120 pinkflag = (stat_items/CTF_PINK_FLAG_TAKEN) & 3;
121 neutralflag = (stat_items/CTF_NEUTRAL_FLAG_TAKEN) & 3;
123 ctf_oneflag = (stat_items & CTF_FLAG_NEUTRAL);
125 mod_active = (redflag || blueflag || yellowflag || pinkflag || neutralflag);
127 if (autocvar__hud_configure) {
134 ctf_oneflag = neutralflag = 0; // disable neutral flag in hud editor?
137 // when status CHANGES, set old status into prevstatus and current status into status
138 #define X(team) do { \
139 if (team##flag != team##flag_prevframe) { \
140 team##flag_statuschange_time = time; \
141 team##flag_prevstatus = team##flag_prevframe; \
142 team##flag_prevframe = team##flag; \
144 team##flag_statuschange_elapsedtime = time - team##flag_statuschange_time; \
153 const float BLINK_FACTOR = 0.15;
154 const float BLINK_BASE = 0.85;
156 // RMS = sqrt(BLINK_BASE^2 + 0.5 * BLINK_FACTOR^2)
158 // BLINK_BASE = sqrt(RMS^2 - 0.5 * BLINK_FACTOR^2)
160 const float BLINK_FREQ = 5; // circle frequency, = 2*pi*frequency in hertz
162 #define X(team, cond) \
163 string team##_icon, team##_icon_prevstatus; \
164 int team##_alpha, team##_alpha_prevstatus; \
165 team##_alpha = team##_alpha_prevstatus = 1; \
167 switch (team##flag) { \
168 case 1: team##_icon = "flag_" #team "_taken"; break; \
169 case 2: team##_icon = "flag_" #team "_lost"; break; \
170 case 3: team##_icon = "flag_" #team "_carrying"; team##_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
172 if ((stat_items & CTF_SHIELDED) && (cond)) { \
173 team##_icon = "flag_" #team "_shielded"; \
175 team##_icon = string_null; \
179 switch (team##flag_prevstatus) { \
180 case 1: team##_icon_prevstatus = "flag_" #team "_taken"; break; \
181 case 2: team##_icon_prevstatus = "flag_" #team "_lost"; break; \
182 case 3: team##_icon_prevstatus = "flag_" #team "_carrying"; team##_alpha_prevstatus = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
184 if (team##flag == 3) { \
185 team##_icon_prevstatus = "flag_" #team "_carrying"; /* make it more visible */\
186 } else if((stat_items & CTF_SHIELDED) && (cond)) { \
187 team##_icon_prevstatus = "flag_" #team "_shielded"; \
189 team##_icon_prevstatus = string_null; \
194 X(red, myteam != NUM_TEAM_1);
195 X(blue, myteam != NUM_TEAM_2);
196 X(yellow, myteam != NUM_TEAM_3);
197 X(pink, myteam != NUM_TEAM_4);
202 // hacky, but these aren't needed
203 red_icon = red_icon_prevstatus = blue_icon = blue_icon_prevstatus = yellow_icon = yellow_icon_prevstatus = pink_icon = pink_icon_prevstatus = string_null;
205 } else switch (team_count) {
207 case 2: fs = 0.5; fs2 = 0.5; fs3 = 0.5; break;
208 case 3: fs = 1; fs2 = 0.35; fs3 = 0.35; break;
209 case 4: fs = 0.75; fs2 = 0.25; fs3 = 0.5; break;
212 if (mySize_x > mySize_y) {
228 blueflag_pos = pos + eX * fs2 * size1;
229 yellowflag_pos = pos - eX * fs2 * size1;
230 pinkflag_pos = pos + eX * fs3 * size1;
234 redflag_pos = pos + eX * fs2 * size1;
236 yellowflag_pos = pos - eX * fs2 * size1;
237 pinkflag_pos = pos + eX * fs3 * size1;
241 redflag_pos = pos + eX * fs3 * size1;
242 blueflag_pos = pos - eX * fs2 * size1;
243 yellowflag_pos = pos;
244 pinkflag_pos = pos + eX * fs2 * size1;
248 redflag_pos = pos - eX * fs2 * size1;
249 blueflag_pos = pos + eX * fs3 * size1;
250 yellowflag_pos = pos + eX * fs2 * size1;
255 neutralflag_pos = pos;
256 flag_size = e1 * fs * size1 + e2 * size2;
258 #define X(team) do { \
259 f = bound(0, team##flag_statuschange_elapsedtime * 2, 1); \
260 if (team##_icon_prevstatus && f < 1) \
261 drawpic_aspect_skin_expanding(team##flag_pos, team##_icon_prevstatus, flag_size, '1 1 1', panel_fg_alpha * team##_alpha_prevstatus, DRAWFLAG_NORMAL, f); \
263 drawpic_aspect_skin(team##flag_pos, team##_icon, flag_size, '1 1 1', panel_fg_alpha * team##_alpha * f, DRAWFLAG_NORMAL); \
273 // Keyhunt HUD modicon section
276 void HUD_Mod_KH(vector pos, vector mySize)
278 mod_active = 1; // keyhunt should never hide the mod icons panel
280 // Read current state
282 int state = STAT(KH_KEYS);
284 int all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
285 all_keys = team1_keys = team2_keys = team3_keys = team4_keys = dropped_keys = carrying_keys = 0;
287 for(i = 0; i < 4; ++i)
289 key_state = (bitshift(state, i * -5) & 31) - 1;
302 case NUM_TEAM_1: ++team1_keys; break;
303 case NUM_TEAM_2: ++team2_keys; break;
304 case NUM_TEAM_3: ++team3_keys; break;
305 case NUM_TEAM_4: ++team4_keys; break;
306 case 29: ++dropped_keys; break;
312 // Calculate slot measurements
316 if(all_keys == 4 && mySize.x * 0.5 < mySize.y && mySize.y * 0.5 < mySize.x)
318 // Quadratic arrangement
319 slot_size = eX * mySize.x * 0.5 + eY * mySize.y * 0.5;
321 KH_SLOTS[1] = pos + eX * slot_size.x;
322 KH_SLOTS[2] = pos + eY * slot_size.y;
323 KH_SLOTS[3] = pos + eX * slot_size.x + eY * slot_size.y;
327 if(mySize.x > mySize.y)
329 // Horizontal arrangement
330 slot_size = eX * mySize.x / all_keys + eY * mySize.y;
331 for(i = 0; i < all_keys; ++i)
332 KH_SLOTS[i] = pos + eX * slot_size.x * i;
336 // Vertical arrangement
337 slot_size = eX * mySize.x + eY * mySize.y / all_keys;
338 for(i = 0; i < all_keys; ++i)
339 KH_SLOTS[i] = pos + eY * slot_size.y * i;
343 // Make icons blink in case of RUN HERE
345 float blink = 0.6 + sin(2*M_PI*time) / 2.5; // Oscillate between 0.2 and 1
352 case NUM_TEAM_1: if(team1_keys == all_keys) alpha = blink; break;
353 case NUM_TEAM_2: if(team2_keys == all_keys) alpha = blink; break;
354 case NUM_TEAM_3: if(team3_keys == all_keys) alpha = blink; break;
355 case NUM_TEAM_4: if(team4_keys == all_keys) alpha = blink; break;
363 if(myteam == NUM_TEAM_1 && carrying_keys)
365 drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
369 drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
372 if(myteam == NUM_TEAM_2 && carrying_keys)
374 drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
378 drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
381 if(myteam == NUM_TEAM_3 && carrying_keys)
383 drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
387 drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
390 if(myteam == NUM_TEAM_4 && carrying_keys)
392 drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
396 drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
398 while(dropped_keys--)
399 drawpic_aspect_skin(KH_SLOTS[i++], "kh_dropped", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
402 // Keepaway HUD mod icon
403 int kaball_prevstatus; // last remembered status
404 float kaball_statuschange_time; // time when the status changed
406 // we don't need to reset for keepaway since it immediately
407 // autocorrects prevstatus as to if the player has the ball or not
409 void HUD_Mod_Keepaway(vector pos, vector mySize)
411 mod_active = 1; // keepaway should always show the mod HUD
413 float BLINK_FACTOR = 0.15;
414 float BLINK_BASE = 0.85;
415 float BLINK_FREQ = 5;
416 float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
418 int stat_items = getstati(STAT_ITEMS, 0, 24);
419 int kaball = (stat_items/IT_KEY1) & 1;
421 if(kaball != kaball_prevstatus)
423 kaball_statuschange_time = time;
424 kaball_prevstatus = kaball;
427 vector kaball_pos, kaball_size;
429 if(mySize.x > mySize.y) {
430 kaball_pos = pos + eX * 0.25 * mySize.x;
431 kaball_size = eX * 0.5 * mySize.x + eY * mySize.y;
433 kaball_pos = pos + eY * 0.25 * mySize.y;
434 kaball_size = eY * 0.5 * mySize.y + eX * mySize.x;
437 float kaball_statuschange_elapsedtime = time - kaball_statuschange_time;
438 float f = bound(0, kaball_statuschange_elapsedtime*2, 1);
440 if(kaball_prevstatus && f < 1)
441 drawpic_aspect_skin_expanding(kaball_pos, "keepawayball_carrying", kaball_size, '1 1 1', panel_fg_alpha * kaball_alpha, DRAWFLAG_NORMAL, f);
444 drawpic_aspect_skin(pos, "keepawayball_carrying", eX * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha * kaball_alpha * f, DRAWFLAG_NORMAL);
448 // Nexball HUD mod icon
449 void HUD_Mod_NexBall(vector pos, vector mySize)
451 float nb_pb_starttime, dt, p;
454 stat_items = getstati(STAT_ITEMS, 0, 24);
455 nb_pb_starttime = STAT(NB_METERSTART);
457 if (stat_items & IT_KEY1)
462 //Manage the progress bar if any
463 if (nb_pb_starttime > 0)
465 dt = (time - nb_pb_starttime) % nb_pb_period;
466 // one period of positive triangle
467 p = 2 * dt / nb_pb_period;
471 HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", p, (mySize.x <= mySize.y), 0, autocvar_hud_progressbar_nexball_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
474 if (stat_items & IT_KEY1)
475 drawpic_aspect_skin(pos, "nexball_carrying", eX * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
478 // Race/CTS HUD mod icons
479 float crecordtime_prev; // last remembered crecordtime
480 float crecordtime_change_time; // time when crecordtime last changed
481 float srecordtime_prev; // last remembered srecordtime
482 float srecordtime_change_time; // time when srecordtime last changed
484 float race_status_time;
485 int race_status_prev;
486 string race_status_name_prev;
487 void HUD_Mod_Race(vector pos, vector mySize)
489 mod_active = 1; // race should never hide the mod icons panel
491 me = playerslots[player_localnum];
493 float f; // yet another function has this
494 score = me.(scores[ps_primary]);
496 if(!(scores_flags[ps_primary] & SFL_TIME) || teamplay) // race/cts record display on HUD
497 return; // no records in the actual race
499 // clientside personal record
501 if(gametype == MAPINFO_TYPE_CTS)
505 t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time")));
507 if(score && (score < t || !t)) {
508 db_put(ClientProgsDB, strcat(shortmapname, rr, "time"), ftos(score));
509 if(autocvar_cl_autodemo_delete_keeprecords)
511 f = autocvar_cl_autodemo_delete;
513 cvar_set("cl_autodemo_delete", ftos(f)); // don't delete demo with new record!
517 if(t != crecordtime_prev) {
518 crecordtime_prev = t;
519 crecordtime_change_time = time;
522 vector textPos, medalPos;
524 if(mySize.x > mySize.y) {
526 squareSize = min(mySize.y, mySize.x/2);
527 textPos = pos + eX * 0.5 * max(0, mySize.x/2 - squareSize) + eY * 0.5 * (mySize.y - squareSize);
528 medalPos = pos + eX * 0.5 * max(0, mySize.x/2 - squareSize) + eX * 0.5 * mySize.x + eY * 0.5 * (mySize.y - squareSize);
531 squareSize = min(mySize.x, mySize.y/2);
532 textPos = pos + eY * 0.5 * max(0, mySize.y/2 - squareSize) + eX * 0.5 * (mySize.x - squareSize);
533 medalPos = pos + eY * 0.5 * max(0, mySize.y/2 - squareSize) + eY * 0.5 * mySize.y + eX * 0.5 * (mySize.x - squareSize);
536 f = time - crecordtime_change_time;
539 drawstring_aspect(textPos, _("Personal best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
540 drawstring_aspect(textPos + eY * 0.25 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
542 drawstring_aspect(textPos, _("Personal best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
543 drawstring_aspect(textPos + eY * 0.25 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
544 drawstring_aspect_expanding(pos, _("Personal best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
545 drawstring_aspect_expanding(pos + eY * 0.25 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
549 t = race_server_record;
550 if(t != srecordtime_prev) {
551 srecordtime_prev = t;
552 srecordtime_change_time = time;
554 f = time - srecordtime_change_time;
557 drawstring_aspect(textPos + eY * 0.5 * squareSize, _("Server best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
558 drawstring_aspect(textPos + eY * 0.75 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
560 drawstring_aspect(textPos + eY * 0.5 * squareSize, _("Server best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
561 drawstring_aspect(textPos + eY * 0.75 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
562 drawstring_aspect_expanding(textPos + eY * 0.5 * squareSize, _("Server best"), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
563 drawstring_aspect_expanding(textPos + eY * 0.75 * squareSize, TIME_ENCODED_TOSTRING(t), eX * squareSize + eY * 0.25 * squareSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
566 if (race_status != race_status_prev || race_status_name != race_status_name_prev) {
567 race_status_time = time + 5;
568 race_status_prev = race_status;
569 if (race_status_name_prev)
570 strunzone(race_status_name_prev);
571 race_status_name_prev = strzone(race_status_name);
576 a = bound(0, race_status_time - time, 1);
579 s = textShortenToWidth(race_status_name, squareSize, '1 1 0' * 0.1 * squareSize, stringwidth_colors);
583 rank = race_CheckName(race_status_name);
587 rankname = count_ordinal(rank);
590 namepos = medalPos + '0 0.8 0' * squareSize;
592 rankpos = medalPos + '0 0.15 0' * squareSize;
595 drawpic_aspect_skin(medalPos, "race_newfail", '1 1 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
596 else if(race_status == 1) {
597 drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newtime", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
598 drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
599 drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
600 } else if(race_status == 2) {
601 if(race_status_name == entcs_GetName(player_localnum) || !race_myrank || race_myrank < rank)
602 drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankgreen", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
604 drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankyellow", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
605 drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
606 drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
607 } else if(race_status == 3) {
608 drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrecordserver", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
609 drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
610 drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
613 if (race_status_time - time <= 0) {
614 race_status_prev = -1;
617 strunzone(race_status_name);
618 race_status_name = string_null;
619 if(race_status_name_prev)
620 strunzone(race_status_name_prev);
621 race_status_name_prev = string_null;
625 void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
629 vector color = '0 0 0';
633 stat = STAT(DOM_PPS_RED);
634 pic = "dom_icon_red";
638 stat = STAT(DOM_PPS_BLUE);
639 pic = "dom_icon_blue";
643 stat = STAT(DOM_PPS_YELLOW);
644 pic = "dom_icon_yellow";
649 stat = STAT(DOM_PPS_PINK);
650 pic = "dom_icon_pink";
654 float pps_ratio = stat / STAT(DOM_TOTAL_PPS);
656 if(mySize.x/mySize.y > aspect_ratio)
658 i = aspect_ratio * mySize.y;
659 myPos.x = myPos.x + (mySize.x - i) / 2;
664 i = 1/aspect_ratio * mySize.x;
665 myPos.y = myPos.y + (mySize.y - i) / 2;
669 if (layout) // show text too
672 color *= 0.5 + pps_ratio * (1 - 0.5); // half saturated color at min, full saturated at max
673 if (layout == 2) // average pps
674 drawstring_aspect(myPos + eX * mySize.y, ftos_decimals(stat, 2), eX * (2/3) * mySize.x + eY * mySize.y, color, panel_fg_alpha, DRAWFLAG_NORMAL);
675 else // percentage of average pps
676 drawstring_aspect(myPos + eX * mySize.y, strcat( ftos(floor(pps_ratio*100 + 0.5)), "%" ), eX * (2/3) * mySize.x + eY * mySize.y, color, panel_fg_alpha, DRAWFLAG_NORMAL);
680 drawpic_aspect_skin(myPos, pic, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
683 drawsetcliparea(myPos.x, myPos.y + mySize.y * (1 - pps_ratio), mySize.y, mySize.y * pps_ratio);
684 drawpic_aspect_skin(myPos, strcat(pic, "-highlighted"), '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
689 void HUD_Mod_Dom(vector myPos, vector mySize)
691 mod_active = 1; // required in each mod function that always shows something
693 int layout = autocvar_hud_panel_modicons_dom_layout;
696 aspect_ratio = (layout) ? 3 : 1;
697 rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
698 columns = ceil(team_count/rows);
701 float row = 0, column = 0;
702 vector pos, itemSize;
703 itemSize = eX * mySize.x*(1/columns) + eY * mySize.y*(1/rows);
704 for(i=0; i<team_count; ++i)
706 pos = myPos + eX * column * itemSize.x + eY * row * itemSize.y;
708 DrawDomItem(pos, itemSize, aspect_ratio, layout, i);
719 void HUD_ModIcons_SetFunc()
723 case MAPINFO_TYPE_KEYHUNT: HUD_ModIcons_GameType = HUD_Mod_KH; break;
724 case MAPINFO_TYPE_CTF: HUD_ModIcons_GameType = HUD_Mod_CTF; break;
725 case MAPINFO_TYPE_NEXBALL: HUD_ModIcons_GameType = HUD_Mod_NexBall; break;
726 case MAPINFO_TYPE_CTS:
727 case MAPINFO_TYPE_RACE: HUD_ModIcons_GameType = HUD_Mod_Race; break;
728 case MAPINFO_TYPE_CA:
729 case MAPINFO_TYPE_FREEZETAG: HUD_ModIcons_GameType = HUD_Mod_CA; break;
730 case MAPINFO_TYPE_DOMINATION: HUD_ModIcons_GameType = HUD_Mod_Dom; break;
731 case MAPINFO_TYPE_KEEPAWAY: HUD_ModIcons_GameType = HUD_Mod_Keepaway; break;
735 int mod_prev; // previous state of mod_active to check for a change
737 float mod_change; // "time" when mod_active changed
741 if(!autocvar__hud_configure)
743 if(!autocvar_hud_panel_modicons) return;
744 if(!HUD_ModIcons_GameType) return;
747 HUD_Panel_UpdateCvars();
749 draw_beginBoldFont();
751 if(mod_active != mod_prev) {
753 mod_prev = mod_active;
756 if(mod_active || autocvar__hud_configure)
757 mod_alpha = bound(0, (time - mod_change) * 2, 1);
759 mod_alpha = bound(0, 1 - (time - mod_change) * 2, 1);
762 HUD_Panel_DrawBg(mod_alpha);
766 panel_pos += '1 1 0' * panel_bg_padding;
767 panel_size -= '2 2 0' * panel_bg_padding;
770 if(autocvar__hud_configure)
771 HUD_Mod_CTF(panel_pos, panel_size);
773 HUD_ModIcons_GameType(panel_pos, panel_size);