]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/hud/panel/modicons.qc
Merge branch 'master' into Mario/csqc_muzzleflash
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud / panel / modicons.qc
1 #include "modicons.qh"
2
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 <common/gamemodes/_mod.qh>
9
10 // Mod icons (#10)
11
12 void HUD_ModIcons_Export(int fh)
13 {
14         // allow saving cvars that aesthetically change the panel into hud skin files
15         HUD_Write_Cvar("hud_panel_modicons_ca_layout");
16         HUD_Write_Cvar("hud_panel_modicons_dom_layout");
17         HUD_Write_Cvar("hud_panel_modicons_freezetag_layout");
18 }
19
20 void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
21 {
22         TC(int, layout); TC(int, i);
23         int stat = -1;
24         string pic = "";
25         vector color = '0 0 0';
26         switch(i)
27         {
28                 case 0: stat = STAT(REDALIVE); pic = "player_red"; color = '1 0 0'; break;
29                 case 1: stat = STAT(BLUEALIVE); pic = "player_blue"; color = '0 0 1'; break;
30                 case 2: stat = STAT(YELLOWALIVE); pic = "player_yellow"; color = '1 1 0'; break;
31                 default:
32                 case 3: stat = STAT(PINKALIVE); pic = "player_pink"; color = '1 0 1'; break;
33         }
34
35         if(mySize.x/mySize.y > aspect_ratio)
36         {
37                 i = aspect_ratio * mySize.y;
38                 myPos.x = myPos.x + (mySize.x - i) / 2;
39                 mySize.x = i;
40         }
41         else
42         {
43                 i = 1/aspect_ratio * mySize.x;
44                 myPos.y = myPos.y + (mySize.y - i) / 2;
45                 mySize.y = i;
46         }
47
48         if(layout)
49         {
50                 drawpic_aspect_skin(myPos, pic, vec2(0.5 * mySize.x, mySize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
51                 drawstring_aspect(myPos + eX * 0.5 * mySize.x, ftos(stat), vec2(0.5 * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
52         }
53         else
54                 drawstring_aspect(myPos, ftos(stat), mySize, color, panel_fg_alpha, DRAWFLAG_NORMAL);
55 }
56
57 // Clan Arena and Freeze Tag HUD modicons
58 void HUD_Mod_CA(vector myPos, vector mySize)
59 {
60         mod_active = 1; // required in each mod function that always shows something
61
62         int layout;
63         if(ISGAMETYPE(CA))
64                 layout = autocvar_hud_panel_modicons_ca_layout;
65         else //if(ISGAMETYPE(FREEZETAG))
66                 layout = autocvar_hud_panel_modicons_freezetag_layout;
67         int rows, columns;
68         float aspect_ratio;
69         aspect_ratio = (layout) ? 2 : 1;
70         rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
71         columns = ceil(team_count/rows);
72
73         int i;
74         float row = 0, column = 0;
75         vector pos = '0 0 0', itemSize;
76         itemSize = vec2(mySize.x / columns, mySize.y / rows);
77         for(i=0; i<team_count; ++i)
78         {
79                 pos.x = myPos.x + column * itemSize.x;
80                 pos.y = myPos.y + row * itemSize.y;
81
82                 DrawCAItem(pos, itemSize, aspect_ratio, layout, i);
83
84                 ++row;
85                 if(row >= rows)
86                 {
87                         row = 0;
88                         ++column;
89                 }
90         }
91 }
92
93 // Race/CTS HUD mod icons
94 float crecordtime_prev; // last remembered crecordtime
95 float crecordtime_change_time; // time when crecordtime last changed
96 float srecordtime_prev; // last remembered srecordtime
97 float srecordtime_change_time; // time when srecordtime last changed
98
99 float race_status_time;
100 int race_status_prev;
101 string race_status_name_prev;
102
103 // Check if the given name already exist in race rankings? In that case, where? (otherwise return 0)
104 int race_CheckName(string net_name)
105 {
106         int rank = 0;
107         string zoned_name = strzone(strdecolorize(entcs_GetName(player_localnum)));
108         for (int i = RANKINGS_CNT - 1; i >= 0; --i)
109                 if (strdecolorize(grecordholder[i]) == zoned_name)
110                 {
111                         rank = i + 1;
112                         break;
113                 }
114         strfree(zoned_name);
115         return rank;
116 }
117
118 void race_showTime(string text, vector pos, vector timeText_ofs, float theTime, vector textSize, float f)
119 {
120         drawstring_aspect(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
121         drawstring_aspect(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
122         if (f < 1) {
123                 drawstring_aspect_expanding(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
124                 drawstring_aspect_expanding(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
125         }
126 }
127
128 void HUD_Mod_Race(vector pos, vector mySize)
129 {
130         entity me = playerslots[player_localnum];
131         float score = me.(scores(ps_primary));
132
133         if(!(scores_flags(ps_primary) & SFL_TIME) || teamplay) // race/cts record display on HUD
134         {
135                 mod_active = 0; // hide it in this case!
136                 return; // no records in the actual race
137         }
138
139         mod_active = 1;
140
141         // clientside personal record
142         string rr;
143         if(ISGAMETYPE(CTS))
144                 rr = CTS_RECORD;
145         else
146                 rr = RACE_RECORD;
147         float t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time")));
148
149         if(score && (score < t || !t)) {
150                 db_put(ClientProgsDB, strcat(shortmapname, rr, "time"), ftos(score));
151                 if(autocvar_cl_autodemo_delete_keeprecords)
152                 {
153                         float f = autocvar_cl_autodemo_delete;
154                         f &= ~1;
155                         cvar_set("cl_autodemo_delete", ftos(f)); // don't delete demo with new record!
156                 }
157         }
158
159         if(t != crecordtime_prev) {
160                 crecordtime_prev = t;
161                 crecordtime_change_time = time;
162         }
163
164         vector textPos, medalPos;
165         float squareSize;
166         if(mySize.x > mySize.y) {
167                 // text on left side
168                 squareSize = min(mySize.y, mySize.x/2);
169                 vector ofs = vec2(0.5 * max(0, mySize.x/2 - squareSize), 0.5 * (mySize.y - squareSize));
170                 textPos = pos + ofs;
171                 ofs.x += 0.5 * mySize.x;
172                 medalPos = pos + ofs;
173         } else {
174                 // text on top
175                 squareSize = min(mySize.x, mySize.y/2);
176                 vector ofs = vec2(0.5 * (mySize.x - squareSize), 0.5 * max(0, mySize.y/2 - squareSize));
177                 textPos = pos + ofs;
178                 ofs.y += 0.5 * mySize.y;
179                 medalPos = pos + ofs;
180         }
181         vector textSize = vec2(squareSize, 0.25 * squareSize);
182
183         race_showTime(_("Personal best"), textPos, eY * 0.25 * squareSize, t, textSize, time - crecordtime_change_time);
184
185         // server record
186         t = race_server_record;
187         if(t != srecordtime_prev) {
188                 srecordtime_prev = t;
189                 srecordtime_change_time = time;
190         }
191
192         textPos += eY * 0.5 * squareSize;
193         race_showTime(_("Server best"), textPos, eY * 0.25 * squareSize, t, textSize, time - srecordtime_change_time);
194
195         if (race_status != race_status_prev || race_status_name != race_status_name_prev) {
196                 race_status_time = time + 5;
197                 race_status_prev = race_status;
198                 strcpy(race_status_name_prev, race_status_name);
199         }
200
201         // race "awards"
202         float a = bound(0, race_status_time - time, 1);
203         string s = textShortenToWidth(ColorTranslateRGB(race_status_name), squareSize, '1 1 0' * 0.1 * squareSize, stringwidth_colors);
204
205         float rank = 0;
206         if(race_status > 0)
207                 rank = race_CheckName(race_status_name);
208         string rankname = count_ordinal(rank);
209         vector namepos = medalPos + '0 0.8 0' * squareSize;
210         vector rankpos = medalPos + '0 0.15 0' * squareSize;
211
212         if(race_status == 0)
213                 drawpic_aspect_skin(medalPos, "race_newfail", '1 1 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
214         else if(race_status == 1) {
215                 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);
216                 drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
217                 drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
218         } else if(race_status == 2) {
219                 if(strdecolorize(race_status_name) == strdecolorize(entcs_GetName(player_localnum)) || !race_myrank || race_myrank < rank)
220                         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);
221                 else
222                         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);
223                 drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
224                 drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
225         } else if(race_status == 3) {
226                 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);
227                 drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
228                 drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
229         }
230
231         if (race_status_time - time <= 0) {
232                 race_status_prev = -1;
233                 race_status = -1;
234                 strfree(race_status_name);
235                 strfree(race_status_name_prev);
236         }
237 }
238
239 void HUD_ModIcons_SetFunc()
240 {
241         HUD_ModIcons_GameType = gametype.m_modicons;
242 }
243
244 float mod_alpha;
245
246 void HUD_ModIcons()
247 {
248         if(!autocvar__hud_configure)
249         {
250                 if(!autocvar_hud_panel_modicons) return;
251                 if(!HUD_ModIcons_GameType) return;
252         }
253
254         if(mod_active || autocvar__hud_configure)
255                 mod_alpha = min(mod_alpha + frametime * 2, 1);
256         else
257                 mod_alpha = max(mod_alpha - frametime * 2, 0);
258
259         //if(mod_alpha <= 0)
260         //      return;
261         panel_fade_alpha *= mod_alpha;
262         HUD_Panel_LoadCvars();
263
264         draw_beginBoldFont();
265
266         if (autocvar_hud_panel_modicons_dynamichud)
267                 HUD_Scale_Enable();
268         else
269                 HUD_Scale_Disable();
270
271         HUD_Panel_DrawBg();
272
273         if(panel_bg_padding)
274         {
275                 panel_pos += '1 1 0' * panel_bg_padding;
276                 panel_size -= '2 2 0' * panel_bg_padding;
277         }
278
279         if(autocvar__hud_configure)
280                 HUD_Mod_CTF(panel_pos, panel_size);
281         else
282                 HUD_ModIcons_GameType(panel_pos, panel_size);
283
284         draw_endBoldFont();
285 }