- // Calculate slot measurements
- vector slot_size;
- if(all_keys == 4 && mySize.x * 0.5 < mySize.y && mySize.y * 0.5 < mySize.x)
- {
- // Quadratic arrangement
- slot_size = vec2(mySize.x * 0.5, mySize.y * 0.5);
- KH_SLOTS[0] = pos;
- KH_SLOTS[1] = pos + eX * slot_size.x;
- KH_SLOTS[2] = pos + eY * slot_size.y;
- KH_SLOTS[3] = pos + eX * slot_size.x + eY * slot_size.y;
- }
- else
- {
- if(mySize.x > mySize.y)
- {
- // Horizontal arrangement
- slot_size = vec2(mySize.x / all_keys, mySize.y);
- for(i = 0; i < all_keys; ++i)
- KH_SLOTS[i] = pos + eX * slot_size.x * i;
- }
- else
- {
- // Vertical arrangement
- slot_size = vec2(mySize.x, mySize.y / all_keys);
- for(i = 0; i < all_keys; ++i)
- KH_SLOTS[i] = pos + eY * slot_size.y * i;
- }
- }
-
- // Make icons blink in case of RUN HERE
-
- float alpha = 1;
- if(carrying_keys)
- {
- float blink = 0.6 + sin(2 * M_PI * time) * 0.4; // Oscillate between 0.2 and 1
- switch(myteam)
- {
- case NUM_TEAM_1: if(team1_keys == all_keys) alpha = blink; break;
- case NUM_TEAM_2: if(team2_keys == all_keys) alpha = blink; break;
- case NUM_TEAM_3: if(team3_keys == all_keys) alpha = blink; break;
- case NUM_TEAM_4: if(team4_keys == all_keys) alpha = blink; break;
- }
- }
-
- // Draw icons
-
- i = 0;
-
- while(team1_keys--)
- if(myteam == NUM_TEAM_1 && carrying_keys)
- {
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
- --carrying_keys;
- }
- else
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
- while(team2_keys--)
- if(myteam == NUM_TEAM_2 && carrying_keys)
- {
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
- --carrying_keys;
- }
- else
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
- while(team3_keys--)
- if(myteam == NUM_TEAM_3 && carrying_keys)
- {
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
- --carrying_keys;
- }
- else
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
- while(team4_keys--)
- if(myteam == NUM_TEAM_4 && carrying_keys)
- {
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
- --carrying_keys;
- }
- else
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
- while(dropped_keys--)
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_dropped", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-}
-
-// Keepaway HUD mod icon
-int kaball_prevstatus; // last remembered status
-float kaball_statuschange_time; // time when the status changed
-
-// we don't need to reset for keepaway since it immediately
-// autocorrects prevstatus as to if the player has the ball or not
-
-void HUD_Mod_Keepaway(vector pos, vector mySize)
-{
- mod_active = 1; // keepaway should always show the mod HUD
-
- float BLINK_FACTOR = 0.15;
- float BLINK_BASE = 0.85;
- float BLINK_FREQ = 5;
- float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
-
- int stat_items = STAT(ITEMS);
- int kaball = (stat_items/IT_KEY1) & 1;
-
- if(kaball != kaball_prevstatus)
- {
- kaball_statuschange_time = time;
- kaball_prevstatus = kaball;
- }
-
- vector kaball_pos, kaball_size;
-
- if(mySize.x > mySize.y) {
- kaball_pos = pos + eX * 0.25 * mySize.x;
- kaball_size = vec2(0.5 * mySize.x, mySize.y);
- } else {
- kaball_pos = pos + eY * 0.25 * mySize.y;
- kaball_size = vec2(mySize.x, 0.5 * mySize.y);
- }
-
- float kaball_statuschange_elapsedtime = time - kaball_statuschange_time;
- float f = bound(0, kaball_statuschange_elapsedtime*2, 1);
-
- if(kaball_prevstatus && f < 1)
- drawpic_aspect_skin_expanding(kaball_pos, "keepawayball_carrying", kaball_size, '1 1 1', panel_fg_alpha * kaball_alpha, DRAWFLAG_NORMAL, f);
-
- if(kaball)
- drawpic_aspect_skin(pos, "keepawayball_carrying", vec2(mySize.x, mySize.y), '1 1 1', panel_fg_alpha * kaball_alpha * f, DRAWFLAG_NORMAL);
-}
-
-
-// Nexball HUD mod icon
-void HUD_Mod_NexBall(vector pos, vector mySize)
-{
- float nb_pb_starttime, dt, p;
- int stat_items;
-
- stat_items = STAT(ITEMS);
- nb_pb_starttime = STAT(NB_METERSTART);
-
- if (stat_items & IT_KEY1)
- mod_active = 1;
- else
- mod_active = 0;
-
- //Manage the progress bar if any
- if (nb_pb_starttime > 0)
- {
- dt = (time - nb_pb_starttime) % nb_pb_period;
- // one period of positive triangle
- p = 2 * dt / nb_pb_period;
- if (p > 1)
- p = 2 - p;
-
- 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);
- }
-
- if (stat_items & IT_KEY1)
- drawpic_aspect_skin(pos, "nexball_carrying", eX * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
-}
-
-// Race/CTS HUD mod icons
-float crecordtime_prev; // last remembered crecordtime
-float crecordtime_change_time; // time when crecordtime last changed
-float srecordtime_prev; // last remembered srecordtime
-float srecordtime_change_time; // time when srecordtime last changed
-
-float race_status_time;
-int race_status_prev;
-string race_status_name_prev;
-
-// Check if the given name already exist in race rankings? In that case, where? (otherwise return 0)
-int race_CheckName(string net_name)
-{
- int i;
- for (i=RANKINGS_CNT-1;i>=0;--i)
- if(strdecolorize(grecordholder[i]) == strdecolorize(net_name))
- return i+1;
- return 0;
-}
-
-void race_showTime(string text, vector pos, vector timeText_ofs, float theTime, vector textSize, float f)
-{
- drawstring_aspect(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- drawstring_aspect(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- if (f < 1) {
- drawstring_aspect_expanding(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
- drawstring_aspect_expanding(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
- }
-}
-
-void HUD_Mod_Race(vector pos, vector mySize)
-{
- entity me = playerslots[player_localnum];
- float score = me.(scores(ps_primary));
-
- if(!(scores_flags(ps_primary) & SFL_TIME) || teamplay) // race/cts record display on HUD
- {
- mod_active = 0; // hide it in this case!
- return; // no records in the actual race
- }
-
- mod_active = 1;
-
- // clientside personal record
- string rr;
- if(gametype == MAPINFO_TYPE_CTS)
- rr = CTS_RECORD;
- else
- rr = RACE_RECORD;
- float t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time")));
-
- if(score && (score < t || !t)) {
- db_put(ClientProgsDB, strcat(shortmapname, rr, "time"), ftos(score));
- if(autocvar_cl_autodemo_delete_keeprecords)
- {
- float f = autocvar_cl_autodemo_delete;
- f &= ~1;
- cvar_set("cl_autodemo_delete", ftos(f)); // don't delete demo with new record!
- }
- }
-
- if(t != crecordtime_prev) {
- crecordtime_prev = t;
- crecordtime_change_time = time;
- }
-
- vector textPos, medalPos;
- float squareSize;
- if(mySize.x > mySize.y) {
- // text on left side
- squareSize = min(mySize.y, mySize.x/2);
- vector ofs = vec2(0.5 * max(0, mySize.x/2 - squareSize), 0.5 * (mySize.y - squareSize));
- textPos = pos + ofs;
- ofs.x += 0.5 * mySize.x;
- medalPos = pos + ofs;
- } else {
- // text on top
- squareSize = min(mySize.x, mySize.y/2);
- vector ofs = vec2(0.5 * (mySize.x - squareSize), 0.5 * max(0, mySize.y/2 - squareSize));
- textPos = pos + ofs;
- ofs.y += 0.5 * mySize.y;
- medalPos = pos + ofs;
- }
- vector textSize = vec2(squareSize, 0.25 * squareSize);
-
- race_showTime(_("Personal best"), textPos, eY * 0.25 * squareSize, t, textSize, time - crecordtime_change_time);
-
- // server record
- t = race_server_record;
- if(t != srecordtime_prev) {
- srecordtime_prev = t;
- srecordtime_change_time = time;
- }
-
- textPos += eY * 0.5 * squareSize;
- race_showTime(_("Server best"), textPos, eY * 0.25 * squareSize, t, textSize, time - srecordtime_change_time);
-
- if (race_status != race_status_prev || race_status_name != race_status_name_prev) {
- race_status_time = time + 5;
- race_status_prev = race_status;
- strcpy(race_status_name_prev, race_status_name);
- }
-
- // race "awards"
- float a = bound(0, race_status_time - time, 1);
- string s = textShortenToWidth(ColorTranslateRGB(race_status_name), squareSize, '1 1 0' * 0.1 * squareSize, stringwidth_colors);
-
- float rank = 0;
- if(race_status > 0)
- rank = race_CheckName(race_status_name);
- string rankname = count_ordinal(rank);
- vector namepos = medalPos + '0 0.8 0' * squareSize;
- vector rankpos = medalPos + '0 0.15 0' * squareSize;
-
- if(race_status == 0)
- drawpic_aspect_skin(medalPos, "race_newfail", '1 1 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
- else if(race_status == 1) {
- 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);
- drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
- drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
- } else if(race_status == 2) {
- if(strdecolorize(race_status_name) == strdecolorize(entcs_GetName(player_localnum)) || !race_myrank || race_myrank < rank)
- 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);
- else
- 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);
- drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
- drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
- } else if(race_status == 3) {
- 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);
- drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
- drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
- }
-
- if (race_status_time - time <= 0) {
- race_status_prev = -1;
- race_status = -1;
- strfree(race_status_name);
- strfree(race_status_name_prev);
- }
-}
-
-void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
-{
- TC(int, layout); TC(int, i);
- float stat = -1;
- string pic = "";
- vector color = '0 0 0';
- switch(i)
- {
- case 0: stat = STAT(DOM_PPS_RED); pic = "dom_icon_red"; color = '1 0 0'; break;
- case 1: stat = STAT(DOM_PPS_BLUE); pic = "dom_icon_blue"; color = '0 0 1'; break;
- case 2: stat = STAT(DOM_PPS_YELLOW); pic = "dom_icon_yellow"; color = '1 1 0'; break;
- default:
- case 3: stat = STAT(DOM_PPS_PINK); pic = "dom_icon_pink"; color = '1 0 1'; break;
- }
- float pps_ratio = 0;
- if(STAT(DOM_TOTAL_PPS))
- pps_ratio = stat / STAT(DOM_TOTAL_PPS);
-
- if(mySize.x/mySize.y > aspect_ratio)
- {
- i = aspect_ratio * mySize.y;
- myPos.x = myPos.x + (mySize.x - i) / 2;
- mySize.x = i;
- }
- else
- {
- i = 1/aspect_ratio * mySize.x;
- myPos.y = myPos.y + (mySize.y - i) / 2;
- mySize.y = i;
- }
-
- if (layout) // show text too
- {
- //draw the text
- color *= 0.5 + pps_ratio * (1 - 0.5); // half saturated color at min, full saturated at max
- if (layout == 2) // average pps
- drawstring_aspect(myPos + eX * mySize.y, ftos_decimals(stat, 2), vec2((2/3) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
- else // percentage of average pps
- 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);
- }
-
- //draw the icon
- drawpic_aspect_skin(myPos, pic, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- if (stat > 0)
- {
- drawsetcliparea(myPos.x, myPos.y + mySize.y * (1 - pps_ratio), mySize.y, mySize.y * pps_ratio);
- drawpic_aspect_skin(myPos, strcat(pic, "-highlighted"), '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- drawresetcliparea();
- }
-}
-
-void HUD_Mod_Dom(vector myPos, vector mySize)
-{
- mod_active = 1; // required in each mod function that always shows something
-
- int layout = autocvar_hud_panel_modicons_dom_layout;
- int rows, columns;
- float aspect_ratio;
- aspect_ratio = (layout) ? 3 : 1;
- rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
- columns = ceil(team_count/rows);
-
- int i;
- float row = 0, column = 0;
- vector pos, itemSize;
- itemSize = vec2(mySize.x / columns, mySize.y / rows);
- for(i=0; i<team_count; ++i)
- {
- pos = myPos + vec2(column * itemSize.x, row * itemSize.y);
-
- DrawDomItem(pos, itemSize, aspect_ratio, layout, i);
-
- ++row;
- if(row >= rows)
- {
- row = 0;
- ++column;
- }
- }