3 #include <client/miscfunctions.qh>
4 #include <client/autocvars.qh>
5 #include <common/mapinfo.qh>
6 #include <common/ent_cs.qh>
7 #include <common/scores.qh>
8 #include <server/mutators/mutator/gamemode_ctf.qh> // TODO: remove
12 bool mod_active; // is there any active mod icon?
14 void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
16 TC(int, layout); TC(int, i);
19 vector color = '0 0 0';
22 case 0: stat = STAT(REDALIVE); pic = "player_red"; color = '1 0 0'; break;
23 case 1: stat = STAT(BLUEALIVE); pic = "player_blue"; color = '0 0 1'; break;
24 case 2: stat = STAT(YELLOWALIVE); pic = "player_yellow"; color = '1 1 0'; break;
26 case 3: stat = STAT(PINKALIVE); pic = "player_pink"; color = '1 0 1'; break;
29 if(mySize.x/mySize.y > aspect_ratio)
31 i = aspect_ratio * mySize.y;
32 myPos.x = myPos.x + (mySize.x - i) / 2;
37 i = 1/aspect_ratio * mySize.x;
38 myPos.y = myPos.y + (mySize.y - i) / 2;
44 drawpic_aspect_skin(myPos, pic, vec2(0.7 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
45 drawstring_aspect(myPos + eX * 0.7 * mySize.x, ftos(stat), vec2(0.3 * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
48 drawstring_aspect(myPos, ftos(stat), mySize, color, panel_fg_alpha, DRAWFLAG_NORMAL);
51 // Clan Arena and Freeze Tag HUD modicons
52 void HUD_Mod_CA(vector myPos, vector mySize)
54 mod_active = 1; // required in each mod function that always shows something
57 if(gametype == MAPINFO_TYPE_CA)
58 layout = autocvar_hud_panel_modicons_ca_layout;
59 else //if(gametype == MAPINFO_TYPE_FREEZETAG)
60 layout = autocvar_hud_panel_modicons_freezetag_layout;
63 aspect_ratio = (layout) ? 2 : 1;
64 rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
65 columns = ceil(team_count/rows);
68 float row = 0, column = 0;
69 vector pos = '0 0 0', itemSize;
70 itemSize = vec2(mySize.x / columns, mySize.y / rows);
71 for(i=0; i<team_count; ++i)
73 pos.x = myPos.x + column * itemSize.x;
74 pos.y = myPos.y + row * itemSize.y;
76 DrawCAItem(pos, itemSize, aspect_ratio, layout, i);
87 // CTF HUD modicon section
88 int redflag_prevframe, blueflag_prevframe, yellowflag_prevframe, pinkflag_prevframe, neutralflag_prevframe; // status during previous frame
89 int redflag_prevstatus, blueflag_prevstatus, yellowflag_prevstatus, pinkflag_prevstatus, neutralflag_prevstatus; // last remembered status
90 float redflag_statuschange_time, blueflag_statuschange_time, yellowflag_statuschange_time, pinkflag_statuschange_time, neutralflag_statuschange_time; // time when the status changed
92 void HUD_Mod_CTF_Reset()
94 redflag_prevstatus = blueflag_prevstatus = yellowflag_prevstatus = pinkflag_prevstatus = neutralflag_prevstatus = 0;
95 redflag_prevframe = blueflag_prevframe = yellowflag_prevframe = pinkflag_prevframe = neutralflag_prevframe = 0;
96 redflag_statuschange_time = blueflag_statuschange_time = yellowflag_statuschange_time = pinkflag_statuschange_time = neutralflag_statuschange_time = 0;
99 int autocvar__teams_available;
100 void HUD_Mod_CTF(vector pos, vector mySize)
102 vector redflag_pos, blueflag_pos, yellowflag_pos, pinkflag_pos, neutralflag_pos;
104 float f; // every function should have that
106 int redflag, blueflag, yellowflag, pinkflag, neutralflag; // current status
107 float redflag_statuschange_elapsedtime = 0, blueflag_statuschange_elapsedtime = 0, yellowflag_statuschange_elapsedtime = 0, pinkflag_statuschange_elapsedtime = 0, neutralflag_statuschange_elapsedtime = 0; // time since the status changed
108 bool ctf_oneflag; // one-flag CTF mode enabled/disabled
109 bool ctf_stalemate; // currently in stalemate
110 int stat_items = STAT(CTF_FLAGSTATUS);
111 float fs, fs2, fs3, size1, size2;
114 int nteams = autocvar__teams_available;
116 redflag = (stat_items/CTF_RED_FLAG_TAKEN) & 3;
117 blueflag = (stat_items/CTF_BLUE_FLAG_TAKEN) & 3;
118 yellowflag = (stat_items/CTF_YELLOW_FLAG_TAKEN) & 3;
119 pinkflag = (stat_items/CTF_PINK_FLAG_TAKEN) & 3;
120 neutralflag = (stat_items/CTF_NEUTRAL_FLAG_TAKEN) & 3;
122 ctf_oneflag = (stat_items & CTF_FLAG_NEUTRAL);
124 ctf_stalemate = (stat_items & CTF_STALEMATE);
126 mod_active = (redflag || blueflag || yellowflag || pinkflag || neutralflag || (stat_items & CTF_SHIELDED));
128 if (autocvar__hud_configure) {
135 ctf_oneflag = neutralflag = 0; // disable neutral flag in hud editor?
138 // when status CHANGES, set old status into prevstatus and current status into status
139 #define X(team) MACRO_BEGIN { \
140 if (team##flag != team##flag_prevframe) { \
141 team##flag_statuschange_time = time; \
142 team##flag_prevstatus = team##flag_prevframe; \
143 team##flag_prevframe = team##flag; \
145 team##flag_statuschange_elapsedtime = time - team##flag_statuschange_time; \
154 const float BLINK_FACTOR = 0.15;
155 const float BLINK_BASE = 0.85;
157 // RMS = sqrt(BLINK_BASE^2 + 0.5 * BLINK_FACTOR^2)
159 // BLINK_BASE = sqrt(RMS^2 - 0.5 * BLINK_FACTOR^2)
161 const float BLINK_FREQ = 5; // circle frequency, = 2*pi*frequency in hertz
163 #define X(team, cond) \
164 string team##_icon = string_null, team##_icon_prevstatus = string_null; \
165 int team##_alpha, team##_alpha_prevstatus; \
166 team##_alpha = team##_alpha_prevstatus = 1; \
168 switch (team##flag) { \
169 case 1: team##_icon = "flag_" #team "_taken"; break; \
170 case 2: team##_icon = "flag_" #team "_lost"; break; \
171 case 3: team##_icon = "flag_" #team "_carrying"; team##_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
173 if ((stat_items & CTF_SHIELDED) && (cond)) { \
174 team##_icon = "flag_" #team "_shielded"; \
176 team##_icon = string_null; \
180 switch (team##flag_prevstatus) { \
181 case 1: team##_icon_prevstatus = "flag_" #team "_taken"; break; \
182 case 2: team##_icon_prevstatus = "flag_" #team "_lost"; break; \
183 case 3: team##_icon_prevstatus = "flag_" #team "_carrying"; team##_alpha_prevstatus = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
185 if (team##flag == 3) { \
186 team##_icon_prevstatus = "flag_" #team "_carrying"; /* make it more visible */\
187 } else if((stat_items & CTF_SHIELDED) && (cond)) { \
188 team##_icon_prevstatus = "flag_" #team "_shielded"; \
190 team##_icon_prevstatus = string_null; \
195 X(red, myteam != NUM_TEAM_1 && (nteams & BIT(0)));
196 X(blue, myteam != NUM_TEAM_2 && (nteams & BIT(1)));
197 X(yellow, myteam != NUM_TEAM_3 && (nteams & BIT(2)));
198 X(pink, myteam != NUM_TEAM_4 && (nteams & BIT(3)));
199 X(neutral, ctf_oneflag);
209 // hacky, but these aren't needed
210 red_icon = red_icon_prevstatus = blue_icon = blue_icon_prevstatus = yellow_icon = yellow_icon_prevstatus = pink_icon = pink_icon_prevstatus = string_null;
212 } else switch (tcount) {
214 case 2: fs = 0.5; fs2 = 0.5; fs3 = 0.5; break;
215 case 3: fs = 1; fs2 = 0.35; fs3 = 0.35; break;
216 case 4: fs = 0.75; fs2 = 0.25; fs3 = 0.5; break;
219 if (mySize_x > mySize_y) {
235 blueflag_pos = pos + eX * fs2 * size1;
236 yellowflag_pos = pos - eX * fs2 * size1;
237 pinkflag_pos = pos + eX * fs3 * size1;
241 redflag_pos = pos + eX * fs2 * size1;
243 yellowflag_pos = pos - eX * fs2 * size1;
244 pinkflag_pos = pos + eX * fs3 * size1;
248 redflag_pos = pos + eX * fs3 * size1;
249 blueflag_pos = pos - eX * fs2 * size1;
250 yellowflag_pos = pos;
251 pinkflag_pos = pos + eX * fs2 * size1;
255 redflag_pos = pos - eX * fs2 * size1;
256 blueflag_pos = pos + eX * fs3 * size1;
257 yellowflag_pos = pos + eX * fs2 * size1;
262 neutralflag_pos = pos;
263 flag_size = e1 * fs * size1 + e2 * size2;
265 #define X(team) MACRO_BEGIN { \
266 f = bound(0, team##flag_statuschange_elapsedtime * 2, 1); \
267 if (team##_icon && ctf_stalemate) \
268 drawpic_aspect_skin(team##flag_pos, "flag_stalemate", flag_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); \
269 if (team##_icon_prevstatus && f < 1) \
270 drawpic_aspect_skin_expanding(team##flag_pos, team##_icon_prevstatus, flag_size, '1 1 1', panel_fg_alpha * team##_alpha_prevstatus, DRAWFLAG_NORMAL, f); \
272 drawpic_aspect_skin(team##flag_pos, team##_icon, flag_size, '1 1 1', panel_fg_alpha * team##_alpha * f, DRAWFLAG_NORMAL); \
282 // Keyhunt HUD modicon section
285 void HUD_Mod_KH(vector pos, vector mySize)
287 mod_active = 1; // keyhunt should never hide the mod icons panel
289 // Read current state
290 int state = STAT(KH_KEYS);
294 int all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
295 all_keys = team1_keys = team2_keys = team3_keys = team4_keys = dropped_keys = carrying_keys = 0;
297 for(i = 0; i < 4; ++i)
299 key_state = (bitshift(state, i * -5) & 31) - 1;
312 case NUM_TEAM_1: ++team1_keys; break;
313 case NUM_TEAM_2: ++team2_keys; break;
314 case NUM_TEAM_3: ++team3_keys; break;
315 case NUM_TEAM_4: ++team4_keys; break;
316 case 29: ++dropped_keys; break;
322 // Calculate slot measurements
324 if(all_keys == 4 && mySize.x * 0.5 < mySize.y && mySize.y * 0.5 < mySize.x)
326 // Quadratic arrangement
327 slot_size = vec2(mySize.x * 0.5, mySize.y * 0.5);
329 KH_SLOTS[1] = pos + eX * slot_size.x;
330 KH_SLOTS[2] = pos + eY * slot_size.y;
331 KH_SLOTS[3] = pos + eX * slot_size.x + eY * slot_size.y;
335 if(mySize.x > mySize.y)
337 // Horizontal arrangement
338 slot_size = vec2(mySize.x / all_keys, mySize.y);
339 for(i = 0; i < all_keys; ++i)
340 KH_SLOTS[i] = pos + eX * slot_size.x * i;
344 // Vertical arrangement
345 slot_size = vec2(mySize.x, mySize.y / all_keys);
346 for(i = 0; i < all_keys; ++i)
347 KH_SLOTS[i] = pos + eY * slot_size.y * i;
351 // Make icons blink in case of RUN HERE
356 float blink = 0.6 + sin(2 * M_PI * time) * 0.4; // Oscillate between 0.2 and 1
359 case NUM_TEAM_1: if(team1_keys == all_keys) alpha = blink; break;
360 case NUM_TEAM_2: if(team2_keys == all_keys) alpha = blink; break;
361 case NUM_TEAM_3: if(team3_keys == all_keys) alpha = blink; break;
362 case NUM_TEAM_4: if(team4_keys == all_keys) alpha = blink; break;
371 if(myteam == NUM_TEAM_1 && carrying_keys)
373 drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
377 drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
380 if(myteam == NUM_TEAM_2 && carrying_keys)
382 drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
386 drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
389 if(myteam == NUM_TEAM_3 && carrying_keys)
391 drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
395 drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
398 if(myteam == NUM_TEAM_4 && carrying_keys)
400 drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
404 drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
406 while(dropped_keys--)
407 drawpic_aspect_skin(KH_SLOTS[i++], "kh_dropped", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
410 // Keepaway HUD mod icon
411 int kaball_prevstatus; // last remembered status
412 float kaball_statuschange_time; // time when the status changed
414 // we don't need to reset for keepaway since it immediately
415 // autocorrects prevstatus as to if the player has the ball or not
417 void HUD_Mod_Keepaway(vector pos, vector mySize)
419 mod_active = 1; // keepaway should always show the mod HUD
421 float BLINK_FACTOR = 0.15;
422 float BLINK_BASE = 0.85;
423 float BLINK_FREQ = 5;
424 float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
426 int stat_items = STAT(ITEMS);
427 int kaball = (stat_items/IT_KEY1) & 1;
429 if(kaball != kaball_prevstatus)
431 kaball_statuschange_time = time;
432 kaball_prevstatus = kaball;
435 vector kaball_pos, kaball_size;
437 if(mySize.x > mySize.y) {
438 kaball_pos = pos + eX * 0.25 * mySize.x;
439 kaball_size = vec2(0.5 * mySize.x, mySize.y);
441 kaball_pos = pos + eY * 0.25 * mySize.y;
442 kaball_size = vec2(mySize.x, 0.5 * mySize.y);
445 float kaball_statuschange_elapsedtime = time - kaball_statuschange_time;
446 float f = bound(0, kaball_statuschange_elapsedtime*2, 1);
448 if(kaball_prevstatus && f < 1)
449 drawpic_aspect_skin_expanding(kaball_pos, "keepawayball_carrying", kaball_size, '1 1 1', panel_fg_alpha * kaball_alpha, DRAWFLAG_NORMAL, f);
452 drawpic_aspect_skin(pos, "keepawayball_carrying", vec2(mySize.x, mySize.y), '1 1 1', panel_fg_alpha * kaball_alpha * f, DRAWFLAG_NORMAL);
456 // Nexball HUD mod icon
457 void HUD_Mod_NexBall(vector pos, vector mySize)
459 float nb_pb_starttime, dt, p;
462 stat_items = STAT(ITEMS);
463 nb_pb_starttime = STAT(NB_METERSTART);
465 if (stat_items & IT_KEY1)
470 //Manage the progress bar if any
471 if (nb_pb_starttime > 0)
473 dt = (time - nb_pb_starttime) % nb_pb_period;
474 // one period of positive triangle
475 p = 2 * dt / nb_pb_period;
479 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);
482 if (stat_items & IT_KEY1)
483 drawpic_aspect_skin(pos, "nexball_carrying", eX * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
486 // Race/CTS HUD mod icons
487 float crecordtime_prev; // last remembered crecordtime
488 float crecordtime_change_time; // time when crecordtime last changed
489 float srecordtime_prev; // last remembered srecordtime
490 float srecordtime_change_time; // time when srecordtime last changed
492 float race_status_time;
493 int race_status_prev;
494 string race_status_name_prev;
496 // Check if the given name already exist in race rankings? In that case, where? (otherwise return 0)
497 int race_CheckName(string net_name)
500 for (i=RANKINGS_CNT-1;i>=0;--i)
501 if(strdecolorize(grecordholder[i]) == strdecolorize(net_name))
506 void race_showTime(string text, vector pos, vector timeText_ofs, float theTime, vector textSize, float f)
508 drawstring_aspect(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
509 drawstring_aspect(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
511 drawstring_aspect_expanding(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
512 drawstring_aspect_expanding(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
516 void HUD_Mod_Race(vector pos, vector mySize)
518 entity me = playerslots[player_localnum];
519 float score = me.(scores(ps_primary));
521 if(!(scores_flags(ps_primary) & SFL_TIME) || teamplay) // race/cts record display on HUD
523 mod_active = 0; // hide it in this case!
524 return; // no records in the actual race
529 // clientside personal record
531 if(gametype == MAPINFO_TYPE_CTS)
535 float t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time")));
537 if(score && (score < t || !t)) {
538 db_put(ClientProgsDB, strcat(shortmapname, rr, "time"), ftos(score));
539 if(autocvar_cl_autodemo_delete_keeprecords)
541 float f = autocvar_cl_autodemo_delete;
543 cvar_set("cl_autodemo_delete", ftos(f)); // don't delete demo with new record!
547 if(t != crecordtime_prev) {
548 crecordtime_prev = t;
549 crecordtime_change_time = time;
552 vector textPos, medalPos;
554 if(mySize.x > mySize.y) {
556 squareSize = min(mySize.y, mySize.x/2);
557 vector ofs = vec2(0.5 * max(0, mySize.x/2 - squareSize), 0.5 * (mySize.y - squareSize));
559 ofs.x += 0.5 * mySize.x;
560 medalPos = pos + ofs;
563 squareSize = min(mySize.x, mySize.y/2);
564 vector ofs = vec2(0.5 * (mySize.x - squareSize), 0.5 * max(0, mySize.y/2 - squareSize));
566 ofs.y += 0.5 * mySize.y;
567 medalPos = pos + ofs;
569 vector textSize = vec2(squareSize, 0.25 * squareSize);
571 race_showTime(_("Personal best"), textPos, eY * 0.25 * squareSize, t, textSize, time - crecordtime_change_time);
574 t = race_server_record;
575 if(t != srecordtime_prev) {
576 srecordtime_prev = t;
577 srecordtime_change_time = time;
580 textPos += eY * 0.5 * squareSize;
581 race_showTime(_("Server best"), textPos, eY * 0.25 * squareSize, t, textSize, time - srecordtime_change_time);
583 if (race_status != race_status_prev || race_status_name != race_status_name_prev) {
584 race_status_time = time + 5;
585 race_status_prev = race_status;
586 if (race_status_name_prev)
587 strunzone(race_status_name_prev);
588 race_status_name_prev = strzone(race_status_name);
592 float a = bound(0, race_status_time - time, 1);
593 string s = textShortenToWidth(ColorTranslateRGB(race_status_name), squareSize, '1 1 0' * 0.1 * squareSize, stringwidth_colors);
597 rank = race_CheckName(race_status_name);
598 string rankname = count_ordinal(rank);
599 vector namepos = medalPos + '0 0.8 0' * squareSize;
600 vector rankpos = medalPos + '0 0.15 0' * squareSize;
603 drawpic_aspect_skin(medalPos, "race_newfail", '1 1 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
604 else if(race_status == 1) {
605 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);
606 drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
607 drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
608 } else if(race_status == 2) {
609 if(strdecolorize(race_status_name) == strdecolorize(entcs_GetName(player_localnum)) || !race_myrank || race_myrank < rank)
610 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);
612 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);
613 drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
614 drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
615 } else if(race_status == 3) {
616 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);
617 drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
618 drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
621 if (race_status_time - time <= 0) {
622 race_status_prev = -1;
625 strunzone(race_status_name);
626 race_status_name = string_null;
627 if(race_status_name_prev)
628 strunzone(race_status_name_prev);
629 race_status_name_prev = string_null;
633 void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
635 TC(int, layout); TC(int, i);
638 vector color = '0 0 0';
641 case 0: stat = STAT(DOM_PPS_RED); pic = "dom_icon_red"; color = '1 0 0'; break;
642 case 1: stat = STAT(DOM_PPS_BLUE); pic = "dom_icon_blue"; color = '0 0 1'; break;
643 case 2: stat = STAT(DOM_PPS_YELLOW); pic = "dom_icon_yellow"; color = '1 1 0'; break;
645 case 3: stat = STAT(DOM_PPS_PINK); pic = "dom_icon_pink"; color = '1 0 1'; break;
648 if(STAT(DOM_TOTAL_PPS))
649 pps_ratio = stat / STAT(DOM_TOTAL_PPS);
651 if(mySize.x/mySize.y > aspect_ratio)
653 i = aspect_ratio * mySize.y;
654 myPos.x = myPos.x + (mySize.x - i) / 2;
659 i = 1/aspect_ratio * mySize.x;
660 myPos.y = myPos.y + (mySize.y - i) / 2;
664 if (layout) // show text too
667 color *= 0.5 + pps_ratio * (1 - 0.5); // half saturated color at min, full saturated at max
668 if (layout == 2) // average pps
669 drawstring_aspect(myPos + eX * mySize.y, ftos_decimals(stat, 2), vec2((2/3) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
670 else // percentage of average pps
671 drawstring_aspect(myPos + eX * mySize.y, strcat( ftos(floor(pps_ratio*100 + 0.5)), "%" ), vec2((2/3) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
675 drawpic_aspect_skin(myPos, pic, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
678 drawsetcliparea(myPos.x, myPos.y + mySize.y * (1 - pps_ratio), mySize.y, mySize.y * pps_ratio);
679 drawpic_aspect_skin(myPos, strcat(pic, "-highlighted"), '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
684 void HUD_Mod_Dom(vector myPos, vector mySize)
686 mod_active = 1; // required in each mod function that always shows something
688 int layout = autocvar_hud_panel_modicons_dom_layout;
691 aspect_ratio = (layout) ? 3 : 1;
692 rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
693 columns = ceil(team_count/rows);
696 float row = 0, column = 0;
697 vector pos, itemSize;
698 itemSize = vec2(mySize.x / columns, mySize.y / rows);
699 for(i=0; i<team_count; ++i)
701 pos = myPos + vec2(column * itemSize.x, row * itemSize.y);
703 DrawDomItem(pos, itemSize, aspect_ratio, layout, i);
714 void HUD_Mod_GG(vector pos, vector mySize)
716 mod_active = 1; // required in each mod function that always shows something
717 int stat_weapon = STAT(GUNGAME_LEADING_WEAPON);
718 vector pic_pos, pic_size;
719 if (mySize.x > mySize.y)
721 pic_pos = pos + eX * 0.25 * mySize.x;
722 pic_size = vec2(0.5 * mySize.x, mySize.y);
726 pic_pos = pos + eY * 0.25 * mySize.y;
727 pic_size = vec2(mySize.x, 0.5 * mySize.y);
729 string weapon_pic = string_null;
730 FOREACH(Weapons, it != WEP_Null,
732 if (it.m_id == stat_weapon)
734 weapon_pic = it.model2;
742 drawpic_aspect_skin(pic_pos, weapon_pic, pic_size, '1 1 1', 1,
747 void HUD_Mod_SURV(vector mypos, vector mysize)
749 mod_active = 1; // required in each mod function that always shows something
750 float defenderhealth = STAT(SURV_DEFENDER_HEALTH);
752 float margin = mysize.y / 10; // Leave a small margin to be stylish
753 vector healthbarpos = mypos;
754 healthbarpos.x += margin;
755 healthbarpos.y += margin;
756 vector healthbarsize = mysize;
757 healthbarsize.x -= margin * 2;
758 healthbarsize.y -= margin * 2;
759 vector healthbarcolor;
760 healthbarcolor.z = 0;
761 if (defenderhealth > 0.5)
763 healthbarcolor.x = defenderhealth * -2 + 2;
764 healthbarcolor.y = 1;
768 healthbarcolor.x = 1;
769 healthbarcolor.y = defenderhealth;
771 HUD_Panel_DrawProgressBar(healthbarpos, healthbarsize, "progressbar",
772 defenderhealth, false, 0, healthbarcolor, 0.50, DRAWFLAG_NORMAL);
773 // Draw defender picture
774 int defenderteam = STAT(SURV_DEFENDER_TEAM);
775 string defenderpic = "";
776 vector defendercolor;
777 switch (defenderteam)
781 defenderpic = "player_red";
782 defendercolor = '1 0 0';
787 defenderpic = "player_blue";
788 defendercolor = '0 0 1';
793 defendercolor = '1 1 1';
797 vector picpos = mypos;
798 vector picsize = mysize;
799 picsize.x = picsize.y;
800 drawpic_aspect_skin(picpos, defenderpic, picsize, '1 1 1', 1,
802 // Draw number of defenders
803 int numalive = STAT(SURV_DEFENDERS_ALIVE);
804 vector alivepos = mypos;
805 alivepos.x += picsize.x;
806 vector alivesize = picsize;
807 drawstring_aspect(alivepos, ftos(numalive), alivesize, defendercolor, 1,
809 // Draw the time left
810 float roundtime = STAT(SURV_ROUND_TIME);
815 vector roundtimepos = mypos;
816 roundtimepos.x += picsize.x * 2;
817 vector roundtimesize = mysize;
818 roundtimesize.x = mysize.x - picsize.x * 2;
819 drawstring_aspect(roundtimepos, seconds_tostring(roundtime), roundtimesize,
820 '1 1 1', 1, DRAWFLAG_NORMAL);
821 if (autocvar_developer == 0)
826 int redalive = STAT(REDALIVE);
827 int bluealive = STAT(BLUEALIVE);
828 int yellowalive = STAT(YELLOWALIVE);
829 int pinkalive = STAT(PINKALIVE);
830 string message = strcat(ftos(redalive), "/", ftos(yellowalive));
831 vector redpos = mypos;
832 redpos.y += mysize.y;
833 vector statsize = mysize;
835 drawstring_aspect(redpos, message, statsize, '1 0 0', 1, DRAWFLAG_NORMAL);
836 message = strcat(ftos(bluealive), "/", ftos(pinkalive));
837 vector bluepos = mypos;
838 bluepos.x += mysize.x / 2;
839 bluepos.y += mysize.y;
840 drawstring_aspect(bluepos, message, statsize, '0 0 1', 1, DRAWFLAG_NORMAL);
843 void HUD_ModIcons_SetFunc()
845 HUD_ModIcons_GameType = gametype.m_modicons;
852 if(!autocvar__hud_configure)
854 if(!autocvar_hud_panel_modicons) return;
855 if(!HUD_ModIcons_GameType) return;
858 if(mod_active || autocvar__hud_configure)
859 mod_alpha = min(mod_alpha + frametime * 2, 1);
861 mod_alpha = max(mod_alpha - frametime * 2, 0);
865 panel_fade_alpha *= mod_alpha;
866 HUD_Panel_LoadCvars();
868 draw_beginBoldFont();
870 if (autocvar_hud_panel_modicons_dynamichud)
879 panel_pos += '1 1 0' * panel_bg_padding;
880 panel_size -= '2 2 0' * panel_bg_padding;
883 if(autocvar__hud_configure)
884 HUD_Mod_CTF(panel_pos, panel_size);
886 HUD_ModIcons_GameType(panel_pos, panel_size);