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