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
287void HUD_ItemsTime(bool should_draw)
288{
289 if (!should_draw)
290 return;
292 {
293 if (!(
295 || (autocvar_hud_panel_itemstime == 2 && (spectatee_status != 0 || warmup_stage || STAT(ITEMSTIME) == 2))
296 )) { return; }
297 }
298
299 int count = 0;
301 {
302 FOREACH(Items, Item_ItemsTime_Allow(it), {
303 count += (Item_ItemsTime_GetTime(it.m_id) > time || -Item_ItemsTime_GetTime(it.m_id) > time);
304 });
306 }
308 {
309 FOREACH(Items, Item_ItemsTime_Allow(it), {
310 count += (Item_ItemsTime_GetTime(it.m_id) > time);
311 });
313 }
314 else
315 {
316 FOREACH(Items, Item_ItemsTime_Allow(it), {
317 count += (Item_ItemsTime_GetTime(it.m_id) != -1);
318 });
319 count += (Item_ItemsTime_GetTime(REGISTRY_MAX(Items)) != -1);
320 }
321 if (count == 0)
322 return;
323
325
326 vector pos, mySize;
327 pos = panel_pos;
328 mySize = panel_size;
329
331 {
332 pos += '1 1 0' * panel_bg_padding;
333 mySize -= '2 2 0' * panel_bg_padding;
334 }
335
336 float rows, columns;
337 float ar = max(2, autocvar_hud_panel_itemstime_ratio) + 1;
338 rows = HUD_GetRowCount(count, mySize, ar);
339 columns = ceil(count/rows);
340
341 vector itemstime_size = vec2(mySize.x / columns, mySize.y / rows);
342
343 vector offset = '0 0 0';
344 float newSize;
346 {
349 HUD_Panel_DrawBg(); // also draw the bg of the entire panel
350
351 // reduce panel to avoid spacing items
352 if (itemstime_size.x / itemstime_size.y < ar)
353 {
354 newSize = rows * itemstime_size.x / ar;
355 pos.y += (mySize.y - newSize) / 2;
356 mySize.y = newSize;
357 itemstime_size.y = mySize.y / rows;
358 }
359 else
360 {
361 newSize = columns * itemstime_size.y * ar;
362 pos.x += (mySize.x - newSize) / 2;
363 mySize.x = newSize;
364 itemstime_size.x = mySize.x / columns;
365 }
366 panel_pos = pos - '1 1 0' * panel_bg_padding;
367 panel_size = mySize + '2 2 0' * panel_bg_padding;
368 }
369 else
370 {
371 if (itemstime_size.x/itemstime_size.y > ar)
372 {
373 newSize = ar * itemstime_size.y;
374 offset.x = itemstime_size.x - newSize;
375 pos.x += offset.x/2;
376 itemstime_size.x = newSize;
377 }
378 else
379 {
380 newSize = 1/ar * itemstime_size.x;
381 offset.y = itemstime_size.y - newSize;
382 pos.y += offset.y/2;
383 itemstime_size.y = newSize;
384 }
385 }
386
389
390 float row = 0, column = 0;
391 bool item_available;
392 int id = 0;
393 string icon = "";
394 FOREACH(Items, Item_ItemsTime_Allow(it) && Item_ItemsTime_GetTime(it.m_id) != -1, {
395 id = it.m_id;
396 icon = it.m_icon;
397
398LABEL(iteration)
399 float item_time = Item_ItemsTime_GetTime(id);
400 if (item_time < -1)
401 {
402 item_available = true;
403 item_time = -item_time;
404 }
405 else
406 item_available = (item_time <= time);
407
408 if (Item_ItemsTime_GetTime(id) >= 0)
409 {
410 if (time <= Item_ItemsTime_GetTime(id))
412 else if (ItemsTime_availableTime[id] == 0)
414 }
415 else if (ItemsTime_availableTime[id] == 0)
417
418 float f = (time - ItemsTime_availableTime[id]) * 2;
419 f = (f > 1) ? 0 : bound(0, f, 1);
420
423 continue;
424
426 if (!(Item_ItemsTime_GetTime(id) > time))
427 continue;
428
429 DrawItemsTimeItem(pos + vec2(column * (itemstime_size.x + offset.x), row * (itemstime_size.y + offset.y)), itemstime_size, ar, icon, item_time, item_available, f);
430 ++row;
431 if (row >= rows)
432 {
433 row = 0;
434 ++column;
435 }
436 if(id == REGISTRY_MAX(Items)) // can happen only in the last fake iteration
437 break;
438 });
439 // add another fake iteration for superweapons time
440 if(id < REGISTRY_MAX(Items) && Item_ItemsTime_GetTime(REGISTRY_MAX(Items)) != -1)
441 {
442 id = REGISTRY_MAX(Items);
443 icon = "superweapons";
444 goto iteration;
445 }
446}
447
448#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:109
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:242
ERASEABLE float blink(float base, float range, float freq)
Definition util.qc:2274
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
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
void HUD_ItemsTime(bool should_draw)
Definition itemstime.qc:287
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:349
#define NET_HANDLE(id, param)
Definition net.qh:15
#define WriteHeader(to, id)
Definition net.qh:265
int ReadByte()
#define REGISTER_NET_TEMP(id)
Definition net.qh:31
#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:119
#define STATIC_INIT(func)
during worldspawn
Definition static.qh:32
if(frag_attacker.flagcarried)
Definition sv_ctf.qc:2318
#define IS_REAL_CLIENT(v)
Definition utils.qh:17
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:52
const vector eX
Definition vector.qh:44
#define vec2(...)
Definition vector.qh:90
WepSet WEPSET_SUPERWEAPONS
Definition all.qh:345