]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mutators/mutator/itemstime/itemstime.qc
Update default video settings
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / mutator / itemstime / itemstime.qc
1 #include "itemstime.qh"
2
3 REGISTER_MUTATOR(itemstime, true);
4
5 #ifdef GAMEQC
6 REGISTER_NET_TEMP(itemstime)
7 #endif
8
9 #ifdef SVQC
10 void IT_Write(entity e, int i, float f) {
11     if (!IS_REAL_CLIENT(e)) return;
12     msg_entity = e;
13     WriteHeader(MSG_ONE, itemstime);
14     WriteByte(MSG_ONE, i);
15     WriteFloat(MSG_ONE, f);
16 }
17 #endif
18
19 #ifdef CSQC
20 // reserve one more spot for superweapons time
21 float ItemsTime_time[REGISTRY_MAX(Items) + 1];
22 float ItemsTime_availableTime[REGISTRY_MAX(Items) + 1];
23 NET_HANDLE(itemstime, bool isNew)
24 {
25     int i = ReadByte();
26     float f = ReadFloat();
27     return = true;
28     ItemsTime_time[i] = f;
29 }
30 #endif
31
32 #ifdef CSQC
33
34 STATIC_INIT(ItemsTime_Init) {
35         FOREACH(Items, true, {
36                 ItemsTime_time[it.m_id] = -1;
37         });
38         ItemsTime_time[REGISTRY_MAX(Items)] = -1;
39 }
40
41 int autocvar_hud_panel_itemstime = 2;
42 float autocvar_hud_panel_itemstime_dynamicsize = 1;
43 float autocvar_hud_panel_itemstime_ratio = 2;
44 //bool autocvar_hud_panel_itemstime_dynamichud    = true;
45 int autocvar_hud_panel_itemstime_iconalign;
46 bool autocvar_hud_panel_itemstime_progressbar = 0;
47 float autocvar_hud_panel_itemstime_progressbar_maxtime = 30;
48 string autocvar_hud_panel_itemstime_progressbar_name = "progressbar";
49 float autocvar_hud_panel_itemstime_progressbar_reduced;
50 bool autocvar_hud_panel_itemstime_hidespawned = 1;
51 bool autocvar_hud_panel_itemstime_hidebig = false;
52 int autocvar_hud_panel_itemstime_text = 1;
53 #define hud_panel_itemstime_hidebig autocvar_hud_panel_itemstime_hidebig
54 #else
55 #define hud_panel_itemstime_hidebig false
56 #endif
57
58 bool Item_ItemsTime_SpectatorOnly(GameItem it)
59 {
60     return (false
61     || it == ITEM_ArmorMega     || (it == ITEM_ArmorBig && !hud_panel_itemstime_hidebig)
62     || it == ITEM_HealthMega    || (it == ITEM_HealthBig && !hud_panel_itemstime_hidebig)
63     );
64 }
65
66 bool Item_ItemsTime_Allow(GameItem it)
67 {
68     return (false
69     || it.instanceOfPowerup
70     || Item_ItemsTime_SpectatorOnly(it)
71     );
72 }
73
74 #ifdef SVQC
75
76 // reserve one more spot for superweapons time
77 float it_times[REGISTRY_MAX(Items) + 1];
78
79 STATIC_INIT(ItemsTime_Init) {
80         FOREACH(Items, Item_ItemsTime_Allow(it), {
81                 it_times[it.m_id] = -1;
82         });
83         it_times[REGISTRY_MAX(Items)] = -1;
84 }
85
86 void Item_ItemsTime_ResetTimes()
87 {
88     FOREACH(Items, Item_ItemsTime_Allow(it), {
89         it_times[it.m_id] = (it_times[it.m_id] == -1) ? -1 : 0;
90     });
91     it_times[REGISTRY_MAX(Items)] = (it_times[REGISTRY_MAX(Items)] == -1) ? -1 : 0;
92 }
93
94 void Item_ItemsTime_ResetTimesForPlayer(entity e)
95 {
96     FOREACH(Items, Item_ItemsTime_Allow(it), {
97         IT_Write(e, it.m_id, (it_times[it.m_id] == -1) ? -1 : 0);
98     });
99     IT_Write(e, REGISTRY_MAX(Items), (it_times[REGISTRY_MAX(Items)] == -1) ? -1 : 0);
100 }
101
102 void Item_ItemsTime_SetTimesForPlayer(entity e)
103 {
104     FOREACH(Items, Item_ItemsTime_Allow(it), {
105         IT_Write(e, it.m_id, it_times[it.m_id]);
106     });
107     IT_Write(e, REGISTRY_MAX(Items), it_times[REGISTRY_MAX(Items)]);
108 }
109
110 void Item_ItemsTime_SetTime(entity e, float t)
111 {
112     if (!autocvar_sv_itemstime)
113         return;
114
115     GameItem item = e.itemdef;
116     if (item.instanceOfGameItem)
117     {
118                 if (!item.instanceOfWeaponPickup)
119                         it_times[item.m_id] = t;
120                 else if (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS)
121                         it_times[REGISTRY_MAX(Items)] = t;
122     }
123 }
124
125 void Item_ItemsTime_SetTimesForAllPlayers()
126 {
127     FOREACH_CLIENT(IS_REAL_CLIENT(it) && (warmup_stage || !IS_PLAYER(it) || autocvar_sv_itemstime == 2), { Item_ItemsTime_SetTimesForPlayer(it); });
128 }
129
130 float Item_ItemsTime_UpdateTime(entity e, float t)
131 {
132     bool isavailable = (t == 0);
133     IL_EACH(g_items, it != e,
134     {
135         if(!(it.itemdef == e.itemdef || ((STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS) && (STAT(WEAPONS, it) & WEPSET_SUPERWEAPONS))))
136             continue;
137         if (it.scheduledrespawntime <= time)
138             isavailable = true;
139         else if (t == 0 || it.scheduledrespawntime < t)
140             t = it.scheduledrespawntime;
141     });
142     if (isavailable)
143         t = -t; // let know the client there's another available item
144     return t;
145 }
146
147 MUTATOR_HOOKFUNCTION(itemstime, reset_map_global)
148 {
149     Item_ItemsTime_ResetTimes();
150     // ALL the times need to be reset before .reset()ing each item
151     // since Item_Reset schedules respawn of superweapons and powerups
152     IL_EACH(g_items, it.reset,
153     {
154         Item_ItemsTime_SetTime(it, 0);
155     });
156     Item_ItemsTime_SetTimesForAllPlayers();
157 }
158
159 MUTATOR_HOOKFUNCTION(itemstime, MakePlayerObserver)
160 {
161     entity player = M_ARGV(0, entity);
162
163     Item_ItemsTime_SetTimesForPlayer(player);
164 }
165
166 MUTATOR_HOOKFUNCTION(itemstime, ClientConnect, CBC_ORDER_LAST)
167 {
168     entity player = M_ARGV(0, entity);
169
170         if(IS_PLAYER(player))
171         {
172                 // client became player on connection skipping putObserverInServer step
173                 if (IS_REAL_CLIENT(player))
174                 if (warmup_stage || autocvar_sv_itemstime == 2)
175                         Item_ItemsTime_SetTimesForPlayer(player);
176         }
177 }
178
179 MUTATOR_HOOKFUNCTION(itemstime, PlayerSpawn)
180 {
181     if (warmup_stage || autocvar_sv_itemstime == 2) return;
182     entity player = M_ARGV(0, entity);
183
184     Item_ItemsTime_ResetTimesForPlayer(player);
185 }
186
187 #endif
188
189 #ifdef CSQC
190
191 // ItemsTime (#22)
192
193 void HUD_ItemsTime_Export(int fh)
194 {
195         // allow saving cvars that aesthetically change the panel into hud skin files
196         HUD_Write_Cvar("hud_panel_itemstime_iconalign");
197         HUD_Write_Cvar("hud_panel_itemstime_progressbar");
198         HUD_Write_Cvar("hud_panel_itemstime_progressbar_name");
199         HUD_Write_Cvar("hud_panel_itemstime_progressbar_reduced");
200         HUD_Write_Cvar("hud_panel_itemstime_text");
201         HUD_Write_Cvar("hud_panel_itemstime_ratio");
202         HUD_Write_Cvar("hud_panel_itemstime_dynamicsize");
203 }
204
205 void DrawItemsTimeItem(vector myPos, vector mySize, float ar, string item_icon, float item_time, bool item_available, float item_availableTime)
206 {
207     float t = 0;
208     vector color = '0 0 0';
209     float picalpha;
210
211     if (autocvar_hud_panel_itemstime_hidespawned == 2)
212         picalpha = 1;
213     else if (item_available)
214         picalpha = blink(0.85, 0.15, 5);
215     else
216         picalpha = 0.5;
217     t = floor(item_time - time + 0.999);
218     if (t < 5)
219         color = '0.7 0 0';
220     else if (t < 10)
221         color = '0.7 0.7 0';
222     else
223         color = '1 1 1';
224
225     vector picpos, numpos;
226     if (autocvar_hud_panel_itemstime_iconalign)
227     {
228         numpos = myPos;
229         picpos = myPos + eX * (ar - 1) * mySize_y;
230     }
231     else
232     {
233         numpos = myPos + eX * mySize_y;
234         picpos = myPos;
235     }
236
237     if (t > 0 && autocvar_hud_panel_itemstime_progressbar)
238     {
239         vector p_pos, p_size;
240         if (autocvar_hud_panel_itemstime_progressbar_reduced)
241         {
242             p_pos = numpos;
243             p_size = vec2(((ar - 1)/ar) * mySize.x, mySize.y);
244         }
245         else
246         {
247             p_pos = myPos;
248             p_size = mySize;
249         }
250         HUD_Panel_DrawProgressBar(p_pos, p_size, autocvar_hud_panel_itemstime_progressbar_name, t/autocvar_hud_panel_itemstime_progressbar_maxtime, 0, autocvar_hud_panel_itemstime_iconalign, color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
251     }
252
253     if(autocvar_hud_panel_itemstime_text)
254     {
255         if(t > 0)
256             drawstring_aspect(numpos, ftos(t), vec2(((ar - 1)/ar) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
257         else if(precache_pic("gfx/hud/default/checkmark")) // COMPAT: check if this image exists, as 0.8.1 clients lack it
258             drawpic_aspect_skin(numpos, "checkmark", vec2((ar - 1) * mySize.y, mySize.y), '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL);
259         else // legacy code, if the image is missing just center the icon
260             picpos.x = myPos.x + mySize.x / 2 - mySize.y / 2;
261     }
262     if (item_availableTime)
263         drawpic_aspect_skin_expanding(picpos, item_icon, '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL, item_availableTime);
264     drawpic_aspect_skin(picpos, item_icon, '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL);
265 }
266
267 float Item_ItemsTime_GetTime(int item)
268 {
269     if(autocvar__hud_configure)
270     {
271         switch(item)
272         {
273             case ITEM_ArmorMega.m_id: return time + 0;
274             case ITEM_HealthMega.m_id: return time + 8;
275             case ITEM_Strength.m_id: return time + 0;
276             case ITEM_Shield.m_id: return time + 4;
277         }
278
279         return -1; // don't show others
280     }
281     else
282         return ItemsTime_time[item];
283 }
284
285 void HUD_ItemsTime()
286 {
287     if (!autocvar__hud_configure)
288     {
289         if (!(
290             (autocvar_hud_panel_itemstime == 1 && spectatee_status != 0)
291         ||      (autocvar_hud_panel_itemstime == 2 && (spectatee_status != 0 || warmup_stage || STAT(ITEMSTIME) == 2))
292             )) { return; }
293     }
294
295     int count = 0;
296     if (autocvar_hud_panel_itemstime_hidespawned == 1)
297     {
298         FOREACH(Items, Item_ItemsTime_Allow(it), {
299             count += (Item_ItemsTime_GetTime(it.m_id) > time || -Item_ItemsTime_GetTime(it.m_id) > time);
300         });
301         count += (Item_ItemsTime_GetTime(REGISTRY_MAX(Items)) > time || -Item_ItemsTime_GetTime(REGISTRY_MAX(Items)) > time);
302     }
303     else if (autocvar_hud_panel_itemstime_hidespawned == 2)
304     {
305         FOREACH(Items, Item_ItemsTime_Allow(it), {
306             count += (Item_ItemsTime_GetTime(it.m_id) > time);
307         });
308         count += (Item_ItemsTime_GetTime(REGISTRY_MAX(Items)) > time);
309     }
310     else
311     {
312         FOREACH(Items, Item_ItemsTime_Allow(it), {
313             count += (Item_ItemsTime_GetTime(it.m_id) != -1);
314         });
315         count += (Item_ItemsTime_GetTime(REGISTRY_MAX(Items)) != -1);
316     }
317     if (count == 0)
318         return;
319
320     HUD_Panel_LoadCvars();
321
322     vector pos, mySize;
323     pos = panel_pos;
324     mySize = panel_size;
325
326     if (panel_bg_padding)
327     {
328         pos += '1 1 0' * panel_bg_padding;
329         mySize -= '2 2 0' * panel_bg_padding;
330     }
331
332     float rows, columns;
333     float ar = max(2, autocvar_hud_panel_itemstime_ratio) + 1;
334     rows = HUD_GetRowCount(count, mySize, ar);
335     columns = ceil(count/rows);
336
337     vector itemstime_size = vec2(mySize.x / columns, mySize.y / rows);
338
339     vector offset = '0 0 0';
340     float newSize;
341     if (autocvar_hud_panel_itemstime_dynamicsize)
342     {
343         if (autocvar__hud_configure)
344         if (hud_configure_menu_open != 2)
345             HUD_Panel_DrawBg(); // also draw the bg of the entire panel
346
347         // reduce panel to avoid spacing items
348         if (itemstime_size.x / itemstime_size.y < ar)
349         {
350             newSize = rows * itemstime_size.x / ar;
351             pos.y += (mySize.y - newSize) / 2;
352             mySize.y = newSize;
353             itemstime_size.y = mySize.y / rows;
354         }
355         else
356         {
357             newSize = columns * itemstime_size.y * ar;
358             pos.x += (mySize.x - newSize) / 2;
359             mySize.x = newSize;
360             itemstime_size.x = mySize.x / columns;
361         }
362         panel_pos = pos - '1 1 0' * panel_bg_padding;
363         panel_size = mySize + '2 2 0' * panel_bg_padding;
364     }
365     else
366     {
367         if (itemstime_size.x/itemstime_size.y > ar)
368         {
369             newSize = ar * itemstime_size.y;
370             offset.x = itemstime_size.x - newSize;
371             pos.x += offset.x/2;
372             itemstime_size.x = newSize;
373         }
374         else
375         {
376             newSize = 1/ar * itemstime_size.x;
377             offset.y = itemstime_size.y - newSize;
378             pos.y += offset.y/2;
379             itemstime_size.y = newSize;
380         }
381     }
382
383     HUD_Scale_Enable();
384     HUD_Panel_DrawBg();
385
386     float row = 0, column = 0;
387     bool item_available;
388     int id = 0;
389     string icon = "";
390     FOREACH(Items, Item_ItemsTime_Allow(it) && Item_ItemsTime_GetTime(it.m_id) != -1, {
391         id = it.m_id;
392         icon = it.m_icon;
393
394 LABEL(iteration)
395         float item_time = Item_ItemsTime_GetTime(id);
396         if (item_time < -1)
397         {
398             item_available = true;
399             item_time = -item_time;
400         }
401         else
402             item_available = (item_time <= time);
403
404         if (Item_ItemsTime_GetTime(id) >= 0)
405         {
406             if (time <= Item_ItemsTime_GetTime(id))
407                 ItemsTime_availableTime[id] = 0;
408             else if (ItemsTime_availableTime[id] == 0)
409                 ItemsTime_availableTime[id] = time;
410         }
411         else if (ItemsTime_availableTime[id] == 0)
412             ItemsTime_availableTime[id] = time;
413
414         float f = (time - ItemsTime_availableTime[id]) * 2;
415         f = (f > 1) ? 0 : bound(0, f, 1);
416
417         if (autocvar_hud_panel_itemstime_hidespawned == 1)
418             if (!(Item_ItemsTime_GetTime(id) > time || -Item_ItemsTime_GetTime(id) > time))
419                 continue;
420
421         if (autocvar_hud_panel_itemstime_hidespawned == 2)
422             if (!(Item_ItemsTime_GetTime(id) > time))
423                 continue;
424
425         DrawItemsTimeItem(pos + vec2(column * (itemstime_size.x + offset.x), row * (itemstime_size.y + offset.y)), itemstime_size, ar, icon, item_time, item_available, f);
426         ++row;
427         if (row >= rows)
428         {
429             row = 0;
430             column = column + 1;
431         }
432         if(id == REGISTRY_MAX(Items)) // can happen only in the last fake iteration
433                 break;
434     });
435     // add another fake iteration for superweapons time
436     if(id < REGISTRY_MAX(Items) && Item_ItemsTime_GetTime(REGISTRY_MAX(Items)) != -1)
437     {
438                 id = REGISTRY_MAX(Items);
439                 icon = "superweapons";
440                 goto iteration;
441     }
442 }
443
444 #endif