Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
items.qc
Go to the documentation of this file.
1#include "items.qh"
2
4#include <common/constants.qh>
13#include <common/net_linked.qh>
16#include <common/util.qh>
18#include <common/wepent.qh>
21#include <server/bot/api.qh>
23#include <server/damage.qh>
25#include <server/teamplay.qh>
29#include <server/world.qh>
30
31bool ItemSend(entity this, entity to, int sf)
32{
33 if(this.gravity)
34 sf |= ISF_DROP;
35 else
36 sf &= ~ISF_DROP;
37
38 // if this item is being spawned (in CSQC's perspective)
39 // reuse ISF_SIZE and ISF_SIZE2 to also tell CSQC its bbox size
40 if(sf & ISF_SIZE)
41 {
42 if(this.maxs == ITEM_S_MAXS) // Small
43 {
44 sf |= ISF_SIZE;
45 sf &= ~ISF_SIZE2;
46 }
47 else if(this.maxs == ITEM_L_MAXS) // Large
48 {
49 sf &= ~ISF_SIZE;
50 sf |= ISF_SIZE2;
51 }
52 else // Default
53 sf |= ISF_SIZE | ISF_SIZE2;
54 }
55
56 WriteHeader(MSG_ENTITY, ENT_CLIENT_ITEM);
58
59 //WriteByte(MSG_ENTITY, this.cnt);
60 if(sf & ISF_LOCATION)
61 {
62 WriteVector(MSG_ENTITY, this.origin);
63 }
64
65 if(sf & ISF_ANGLES)
66 {
67 WriteAngleVector(MSG_ENTITY, this.angles);
68 }
69
70 if(sf & ISF_STATUS)
72
73 if(sf & (ISF_SIZE | ISF_SIZE2)) // always true when it's spawned (in CSQC's perspective)
74 {
75 WriteShort(MSG_ENTITY, bound(0, this.fade_end, 32767));
76
77 if(this.mdl == "")
78 LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, "expect a crash just about now");
79
81 WriteByte(MSG_ENTITY, bound(0, this.skin, 255));
82 }
83
84 if(sf & ISF_COLORMAP)
85 {
87 WriteByte(MSG_ENTITY, this.glowmod.x * 255.0);
88 WriteByte(MSG_ENTITY, this.glowmod.y * 255.0);
89 WriteByte(MSG_ENTITY, this.glowmod.z * 255.0);
90 }
91
92 if(sf & ISF_DROP)
93 {
94 WriteVector(MSG_ENTITY, this.velocity);
95 }
96
97 return true;
98}
99
101{
102 this.oldorigin = this.origin;
103 this.SendFlags |= ISF_LOCATION;
104}
105
107{
108 if(getSendEntity(this) == ItemSend)
109 ItemUpdate(this);
110}
111
113{
114 if (this.itemdef.spawnflags & ITEM_FLAG_MUTATORBLOCKED)
115 return false;
116
117 if(!this.itemdef.instanceOfPowerup)
118 {
120 return true;
122 return false;
123 if(g_weaponarena)
124 if(STAT(WEAPONS, this) || this.itemdef.instanceOfAmmo) // no item or ammo pickups in weaponarena
125 return false;
126 }
127 return true;
128}
129
130void Item_Show(entity e, int mode)
131{
133 e.ItemStatus &= ~ITS_STAYWEP;
134 entity def = e.itemdef;
135 if (mode > 0)
136 {
137 // make the item look normal, and be touchable
138 e.model = e.mdl;
139 e.solid = SOLID_TRIGGER;
140 e.spawnshieldtime = 1;
141 e.ItemStatus |= ITS_AVAILABLE;
142 }
143 else if (mode < 0)
144 {
145 // hide the item completely
146 e.model = string_null;
147 e.solid = SOLID_NOT;
148 e.spawnshieldtime = 1;
149 e.ItemStatus &= ~ITS_AVAILABLE;
150 }
151 else
152 {
153 bool nostay = def.instanceOfWeaponPickup ? !!(def.m_weapon.m_wepset & WEPSET_SUPERWEAPONS) : false // no weapon-stay on superweapons
154 || e.team // weapon stay isn't supported for teamed weapons
155 ;
156 if(def.instanceOfWeaponPickup && !nostay && g_weapon_stay)
157 {
158 // make the item translucent and not touchable
159 e.model = e.mdl;
160 e.solid = SOLID_TRIGGER; // can STILL be picked up!
161 e.effects |= EF_STARDUST;
162 e.spawnshieldtime = 0; // field indicates whether picking it up may give you anything other than the weapon
163 e.ItemStatus |= (ITS_AVAILABLE | ITS_STAYWEP);
164 }
165 else
166 {
167 e.solid = SOLID_NOT;
168 e.spawnshieldtime = 1;
169 e.ItemStatus &= ~ITS_AVAILABLE;
170 }
171 }
172
173 if (def.m_glow)
174 e.ItemStatus |= ITS_GLOW;
175
177 e.effects |= EF_NODEPTHTEST;
178
180 e.ItemStatus |= ITS_ALLOWFB;
181 else
182 e.ItemStatus &= ~ITS_ALLOWFB;
183
185 e.ItemStatus |= ITS_ALLOWSI;
186
187 // relink entity (because solid may have changed)
188 setorigin(e, e.origin);
189 e.SendFlags |= ISF_STATUS;
190}
191
193{
194 if (ITEM_IS_LOOT(this))
195 {
196 if (time < this.wait - IT_DESPAWNFX_TIME)
197 this.nextthink = min(time + IT_UPDATE_INTERVAL, this.wait - IT_DESPAWNFX_TIME); // ensuring full time for effects
198 else
199 {
200 // despawning soon, start effects
201 this.ItemStatus |= ITS_EXPIRING;
202 this.SendFlags |= ISF_STATUS;
203 if (time < this.wait - IT_UPDATE_INTERVAL)
205 else
206 {
207 setthink(this, RemoveItem);
208 this.nextthink = this.wait;
209 }
210 }
211
212 if (this.itemdef.instanceOfPowerup)
214
215 // caution: kludge FIXME (with sv_legacy_bbox_expand)
216 // this works around prediction errors caused by bbox discrepancy between SVQC and CSQC
217 if (this.velocity == '0 0 0' && IS_ONGROUND(this))
218 this.gravity = 0; // don't send ISF_DROP anymore
219
220 // send slow updates even if the item didn't move
221 // recovers prediction desyncs where server thinks item stopped, client thinks it didn't
222 ItemUpdate(this);
223 }
224 else
225 {
226 // bones_was_here: TODO: predict movers, enable client prediction of items with a groundentity,
227 // and then send those less often too (and not all on the same frame)
228 this.nextthink = time;
229
230 if(this.origin != this.oldorigin)
231 ItemUpdate(this);
232 }
233}
234
237float Item_ItemsTime_UpdateTime(entity e, float t);
238void Item_ItemsTime_SetTime(entity e, float t);
240
242{
243 Item_Show(this, 1);
244 sound(this, CH_TRIGGER, this.itemdef.m_respawnsound, VOL_BASE, ATTEN_NORM); // play respawn sound
245
246 if (Item_ItemsTime_Allow(this.itemdef) || (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS))
247 {
248 float t = Item_ItemsTime_UpdateTime(this, 0);
249 Item_ItemsTime_SetTime(this, t);
251 }
252
253 setthink(this, Item_Think);
254 this.nextthink = time;
255}
256
258{
260 {
263 Item_Respawn(this);
264 }
265 else
266 {
267 this.nextthink = time + 1;
268 this.item_respawncounter += 1;
269 if(this.item_respawncounter == 1)
270 {
271 do {
272 {
273 entity wi = REGISTRY_GET(Weapons, this.weapon);
274 if (wi != WEP_Null) {
275 entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, this, '0 0 64', NULL, 0, this, waypointsprite_attached, true, RADARICON_Weapon);
276 wp.wp_extra = wi.m_id;
277 break;
278 }
279 }
280 {
281 entity ii = this.itemdef;
282 if (ii != NULL) {
283 entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, this, '0 0 64', NULL, 0, this, waypointsprite_attached, true, RADARICON_Item);
284 wp.wp_extra = ii.m_id;
285 break;
286 }
287 }
288 } while (0);
289 bool mutator_returnvalue = MUTATOR_CALLHOOK(Item_RespawnCountdown, this);
291 {
292 GameItem def = this.itemdef;
293 if (Item_ItemsTime_SpectatorOnly(def) && !mutator_returnvalue)
296 }
297 }
298
300 {
302 if(this.waypointsprite_attached.waypointsprite_visible_for_player(this.waypointsprite_attached, it, it))
303 {
304 msg_entity = it;
305 soundto(MSG_ONE, this, CH_TRIGGER, SND(ITEMRESPAWNCOUNTDOWN), VOL_BASE, ATTEN_NORM, 0); // play respawn sound
306 }
307 });
308
310 //WaypointSprite_UpdateHealth(this.waypointsprite_attached, this.item_respawncounter);
311 }
312 }
313}
314
316{
317 this.nextthink = time;
318 if(this.origin != this.oldorigin)
319 ItemUpdate(this);
320
321 if(time >= this.wait)
322 Item_Respawn(this);
323}
324
326{
327 // if the respawn time is longer than 10 seconds, show a waypoint, otherwise, just respawn normally
328 bool set_itemstime = Item_ItemsTime_Allow(e.itemdef) || (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS);
329 if ((set_itemstime || MUTATOR_CALLHOOK(Item_ScheduleRespawn, e, t)) && (t - ITEM_RESPAWN_TICKS) > 0)
330 {
332 e.nextthink = time + max(0, t - ITEM_RESPAWN_TICKS);
333 e.scheduledrespawntime = e.nextthink + ITEM_RESPAWN_TICKS;
334 e.item_respawncounter = 0;
335 }
336 else
337 {
339 e.nextthink = time;
340 e.scheduledrespawntime = time + t;
341 e.wait = time + t;
342 }
343
344 if (set_itemstime)
345 {
346 t = Item_ItemsTime_UpdateTime(e, e.scheduledrespawntime);
349 }
350}
351
352AUTOCVAR(g_pickup_respawntime_scaling_reciprocal, float, 0.0, "multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `reciprocal` (with `offset` and `linear` set to \\\"0\\\") can be used to achieve a constant number of items spawned *per player*");
353AUTOCVAR(g_pickup_respawntime_scaling_offset, float, 0.0, "multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `offset` offsets the curve left or right (NOTE: results are not intuitive and it is recommend to plot the respawn time and the number of items per player to see what's happening)");
354AUTOCVAR(g_pickup_respawntime_scaling_linear, float, 1.0, "multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `linear` can be used to simply scale the respawn time linearly");
355
357float adjust_respawntime(float normal_respawntime) {
358 float r = autocvar_g_pickup_respawntime_scaling_reciprocal;
359 float o = autocvar_g_pickup_respawntime_scaling_offset;
360 float l = autocvar_g_pickup_respawntime_scaling_linear;
361
362 if (r == 0 && l == 1) {
363 return normal_respawntime;
364 }
365
368 int players = 0;
369 for (int i = 1; i <= NUM_TEAMS; ++i)
370 {
371 if (TeamBalance_IsTeamAllowed(balance, i))
372 {
374 }
375 }
376 TeamBalance_Destroy(balance);
377
378 if (players >= 2) {
379 return normal_respawntime * (r / (players + o) + l);
380 } else {
381 return normal_respawntime;
382 }
383}
384
386{
387 if(e.respawntime > 0)
388 {
389 Item_Show(e, 0);
390
391 float adjusted_respawntime = adjust_respawntime(e.respawntime);
392 //LOG_INFOF("item %s will respawn in %f", e.classname, adjusted_respawntime);
393
394 // range: adjusted_respawntime - respawntimejitter .. adjusted_respawntime + respawntimejitter
395 float respawn_in = adjusted_respawntime + crandom() * e.respawntimejitter;
396 Item_ScheduleRespawnIn(e, respawn_in);
397 }
398 else // if respawntime is -1, this item does not respawn
399 Item_Show(e, -1);
400}
401
402AUTOCVAR(g_pickup_respawntime_initial_random, int, 1,
403 "for items that don't start spawned; \\\"0\\\" = spawn after their normal respawntime, \\\"1\\\" = spawn after `random * respawntime` with the *same* random, \\\"2\\\" = same as 1 but each item has separate random");
404
406{
407 Item_Show(e, 0);
408
409 float spawn_in;
410 if (autocvar_g_pickup_respawntime_initial_random == 0)
411 {
412 // range: respawntime .. respawntime + respawntimejitter
413 spawn_in = e.respawntime + random() * e.respawntimejitter;
414 }
415 else
416 {
417 float rnd;
418 if (autocvar_g_pickup_respawntime_initial_random == 1)
419 {
420 static float shared_random = 0;
421 // NOTE this code works only if items are scheduled at the same time (normal case)
422 // NOTE2 random() can't return exactly 1 so this check always work as intended
423 if (!shared_random || floor(time) > shared_random)
424 shared_random = floor(time) + random();
425 rnd = shared_random - floor(time);
426 }
427 else
428 rnd = random();
429
430 // range:
431 // if respawntime >= ITEM_RESPAWN_TICKS: ITEM_RESPAWN_TICKS .. respawntime + respawntimejitter
432 // else: 0 .. ITEM_RESPAWN_TICKS
433 // this is to prevent powerups spawning unexpectedly without waypoints
434 spawn_in = ITEM_RESPAWN_TICKS + rnd * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
435 }
436
437 Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : spawn_in));
438}
439
440void GiveRandomWeapons(entity receiver, int num_weapons, string weapon_names,
441 entity ammo_entity)
442{
443 if (num_weapons == 0)
444 {
445 return;
446 }
447 int num_potential_weapons = tokenize_console(weapon_names);
448 for (int give_attempt = 0; give_attempt < num_weapons; ++give_attempt)
449 {
451 for (int weapon_index = 0; weapon_index < num_potential_weapons;
452 ++weapon_index)
453 {
454 string weapon = argv(weapon_index);
455 FOREACH(Weapons, it != WEP_Null,
456 {
457 // Finding a weapon which player doesn't have.
458 if (!(STAT(WEAPONS, receiver) & it.m_wepset) && (it.netname == weapon))
459 {
460 RandomSelection_AddEnt(it, 1, 1);
461 break;
462 }
463 });
464 }
466 {
467 return;
468 }
469 STAT(WEAPONS, receiver) |= RandomSelection_chosen_ent.m_wepset;
470 if (RandomSelection_chosen_ent.ammo_type == RES_NONE)
471 {
472 continue;
473 }
474 if (GetResource(receiver,
475 RandomSelection_chosen_ent.ammo_type) != 0)
476 {
477 continue;
478 }
479 GiveResource(receiver, RandomSelection_chosen_ent.ammo_type,
480 GetResource(ammo_entity,
481 RandomSelection_chosen_ent.ammo_type));
482 }
483}
484
485bool Item_GiveAmmoTo(entity item, entity player, Resource res_type, float ammomax)
486{
487 float amount = GetResource(item, res_type);
488 if (amount == 0)
489 {
490 return false;
491 }
492 float player_amount = GetResource(player, res_type);
493 if (item.spawnshieldtime)
494 {
495 if ((player_amount >= ammomax) && (item.pickup_anyway <= 0))
496 return false;
497 }
498 else if (g_weapon_stay == 2)
499 {
500 ammomax = min(amount, ammomax);
501 if(player_amount >= ammomax)
502 return false;
503 }
504 else
505 return false;
506 if (amount < 0)
507 TakeResourceWithLimit(player, res_type, -amount, ammomax);
508 else
509 GiveResourceWithLimit(player, res_type, amount, ammomax);
510 return true;
511}
512
513void Item_NotifyWeapon(entity player, int wep)
514{
515 FOREACH_CLIENT(IS_REAL_CLIENT(it) && (it == player || (IS_SPEC(it) && it.enemy == player)), {
516 msg_entity = it;
517 WriteHeader(MSG_ONE, TE_CSQC_WEAPONPICKUP);
518 WriteByte(MSG_ONE, wep);
519 });
520}
521
522bool Item_GiveTo(entity item, entity player)
523{
524 // if nothing happens to player, just return without taking the item
525 int _switchweapon = 0;
526 // in case the player has cl_autoswitch enabled do the following:
527 // if the player is using their best weapon before items are given, they
528 // probably want to switch to an even better weapon after items are given
529
530 bool use_cts_autoswitch = (g_cts && item.itemdef.instanceOfWeaponPickup && (CS_CVAR(player).cvar_cl_autoswitch_cts != -1));
531 if (CS_CVAR(player).cvar_cl_autoswitch && !use_cts_autoswitch)
532 {
533 for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
534 {
535 .entity weaponentity = weaponentities[slot];
536 if (player.(weaponentity).m_weapon != WEP_Null || slot == 0)
537 {
538 if (player.(weaponentity).m_switchweapon == w_getbestweapon(player, weaponentity))
539 _switchweapon |= BIT(slot);
540
541 if (!(STAT(WEAPONS, player) & WepSet_FromWeapon(player.(weaponentity).m_switchweapon)))
542 _switchweapon |= BIT(slot);
543 }
544 }
545 }
546 bool pickedup = false;
547 pickedup |= Item_GiveAmmoTo(item, player, RES_HEALTH, item.max_health);
548 pickedup |= Item_GiveAmmoTo(item, player, RES_ARMOR, item.max_armorvalue);
549 pickedup |= Item_GiveAmmoTo(item, player, RES_SHELLS, autocvar_g_pickup_shells_max);
550 pickedup |= Item_GiveAmmoTo(item, player, RES_BULLETS, autocvar_g_pickup_nails_max);
551 pickedup |= Item_GiveAmmoTo(item, player, RES_ROCKETS, autocvar_g_pickup_rockets_max);
552 pickedup |= Item_GiveAmmoTo(item, player, RES_CELLS, autocvar_g_pickup_cells_max);
553 pickedup |= Item_GiveAmmoTo(item, player, RES_FUEL, autocvar_g_pickup_fuel_max);
554 if (item.itemdef.instanceOfWeaponPickup)
555 {
556 WepSet w, wp;
557 w = STAT(WEAPONS, item);
558 wp = w & ~STAT(WEAPONS, player);
559
560 if (wp || (item.spawnshieldtime && item.pickup_anyway > 0))
561 {
562 pickedup = true;
563 FOREACH(Weapons, it != WEP_Null, {
564 if(w & (it.m_wepset))
565 Item_NotifyWeapon(player, it.m_id);
566
567 if(wp & (it.m_wepset))
568 {
569 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
570 {
571 .entity weaponentity = weaponentities[slot];
572 if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
573 W_DropEvent(wr_pickup, player, it.m_id, item, weaponentity);
574 }
575 W_GiveWeapon(player, it.m_id);
576 }
577 });
578 }
579 }
580
581 if (item.itemdef.instanceOfPowerup)
582 {
583 if ((item.itemdef == ITEM_FuelRegen) && !(player.items & IT_FUEL_REGEN))
584 Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_ITEM_FUELREGEN_GOT);
585 else if ((item.itemdef == ITEM_Jetpack) && !(player.items & IT_JETPACK))
586 Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_ITEM_JETPACK_GOT);
587 }
588
589 int its = item.items & ~(player.items) & IT_PICKUPMASK;
590 if (its)
591 {
592 pickedup = true;
593 player.items |= its;
594 // TODO: we probably want to show a message in the console, but not this one!
595 //Send_Notification(NOTIF_ONE, player, MSG_INFO, INFO_ITEM_WEAPON_GOT, item.netname);
596 }
597
598 if (item.strength_finished)
599 {
600 pickedup = true;
601 float t = StatusEffects_gettime(STATUSEFFECT_Strength, player);
603 t += item.strength_finished;
604 else
605 t = max(t, time + item.strength_finished);
606 StatusEffects_apply(STATUSEFFECT_Strength, player, t, 0);
607 }
608 if (item.invincible_finished)
609 {
610 pickedup = true;
611 float t = StatusEffects_gettime(STATUSEFFECT_Shield, player);
613 t += item.invincible_finished;
614 else
615 t = max(t, time + item.invincible_finished);
616 StatusEffects_apply(STATUSEFFECT_Shield, player, t, 0);
617 }
618 if (item.speed_finished)
619 {
620 pickedup = true;
621 float t = StatusEffects_gettime(STATUSEFFECT_Speed, player);
623 t += item.speed_finished;
624 else
625 t = max(t, time + item.speed_finished);
626 StatusEffects_apply(STATUSEFFECT_Speed, player, t, 0);
627 }
628 if (item.invisibility_finished)
629 {
630 pickedup = true;
631 float t = StatusEffects_gettime(STATUSEFFECT_Invisibility, player);
633 t += item.invisibility_finished;
634 else
635 t = max(t, time + item.invisibility_finished);
636 StatusEffects_apply(STATUSEFFECT_Invisibility, player, t, 0);
637 }
638 if (item.superweapons_finished)
639 {
640 pickedup = true;
641 float t = StatusEffects_gettime(STATUSEFFECT_Superweapon, player);
642 StatusEffects_apply(STATUSEFFECT_Superweapon, player, t + item.superweapons_finished, 0);
643 }
644
645 // always eat teamed entities
646 if(item.team)
647 pickedup = true;
648
649 if (!pickedup)
650 return false;
651
652 if(use_cts_autoswitch)
653 {
654 // CTS handling: never switch (0), always switch (1)
655 if(CS_CVAR(player).cvar_cl_autoswitch_cts == 1)
656 {
657 // crude hack to enforce switching weapons
658 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
659 {
660 .entity weaponentity = weaponentities[slot];
661 Weapon w = REGISTRY_GET(Weapons, item.weapon);
662 if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
663 if(client_hasweapon(player, w, weaponentity, true, false)) // ammo check
664 W_SwitchWeapon_Force(player, w, weaponentity);
665 }
666 }
667 }
668 else if(_switchweapon)
669 {
670 // non-CTS handling: weaponpriority-based autoswitch
671 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
672 {
673 .entity weaponentity = weaponentities[slot];
674 if(_switchweapon & BIT(slot))
675 {
676 Weapon best_wep = w_getbestweapon(player, weaponentity);
677 if(player.(weaponentity).m_switchweapon != best_wep)
678 W_SwitchWeapon_Force(player, best_wep, weaponentity);
679 }
680 }
681 }
682
683 return true;
684}
685
687{
688 // remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky)
689 if (ITEM_IS_LOOT(this))
690 {
692 {
693 this.SendFlags |= ISF_REMOVEFX;
694 RemoveItem(this);
695 return;
696 }
697 }
698
699 if(!(toucher.flags & FL_PICKUPITEMS)
700 || IS_DEAD(toucher)
701 || (this.solid != SOLID_TRIGGER)
702 || (this.owner == toucher)
703 || (time < this.item_spawnshieldtime)
704 ) { return; }
705
706 switch (MUTATOR_CALLHOOK(ItemTouch, this, toucher))
707 {
708 case MUT_ITEMTOUCH_RETURN: { return; }
709 case MUT_ITEMTOUCH_PICKUP: { toucher = M_ARGV(1, entity); goto pickup; }
710 }
711
712 toucher = M_ARGV(1, entity);
713
714 if (ITEM_IS_EXPIRING(this))
715 {
718 this.speed_finished = max(0, this.speed_finished - time);
721 }
722 bool gave = ITEM_HANDLE(Pickup, this.itemdef, this, toucher);
723 if (!gave)
724 {
725 if (ITEM_IS_EXPIRING(this))
726 {
727 // undo what we did above
728 this.strength_finished += time;
730 this.speed_finished += time;
733 }
734 return;
735 }
736
737LABEL(pickup)
738
739 if(this.target != "" && this.target != "###item###") // q3compat
741
742 GameItem def = this.itemdef;
743 int ch = ((def.instanceOfPowerup && def.m_itemid != IT_RESOURCE) ? CH_TRIGGER_SINGLE : CH_TRIGGER);
745
746 MUTATOR_CALLHOOK(ItemTouched, this, toucher);
747 if (wasfreed(this))
748 {
749 return;
750 }
751
752 if (ITEM_IS_LOOT(this))
753 {
754 this.SendFlags |= ISF_REMOVEFX;
755 RemoveItem(this);
756 return;
757 }
758 if (!this.spawnshieldtime)
759 {
760 return;
761 }
762 entity e;
763 if (this.team)
764 {
766 IL_EACH(g_items, it.team == this.team,
767 {
768 if (it.itemdef) // is a registered item
769 {
770 Item_Show(it, -1);
771 it.scheduledrespawntime = 0;
772 RandomSelection_AddEnt(it, it.cnt, 0);
773 }
774 });
776 Item_Show(e, 1); // reset its state so it is visible (extra sendflags doesn't matter, this happens anyway)
777 }
778 else
779 e = this;
781}
782
784{
785 if (this.targetname != "" && !(this.spawnflags & 16)) // q3compat
786 {
787 Item_Show(this, -1);
790 this.nextthink = 0;
791 return;
792 }
793
794 Item_Show(this, !this.state);
795
796 if (ITEM_IS_LOOT(this))
797 {
798 return;
799 }
800 setthink(this, Item_Think);
801 this.nextthink = time;
802 this.active = ACTIVE_ACTIVE;
804 {
806 }
807 if (this.itemdef.instanceOfPowerup || (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS)) // do not spawn powerups initially!
808 {
810 }
811}
812
814{
815 if(!(this.effects & EF_NOGUNBOB)) // marker for item team search
816 return;
817
818 LOG_TRACE("Initializing item team ", ftos(this.team));
820 IL_EACH(g_items, it.team == this.team,
821 {
822 if(it.itemdef) // is a registered item
823 RandomSelection_AddEnt(it, it.cnt, 0);
824 });
825
827 if (!e)
828 return;
829
830 IL_EACH(g_items, it.team == this.team,
831 {
832 if(it.itemdef) // is a registered item
833 {
834 if(it != e)
835 {
836 Item_Show(it, -1); // make it non-spawned
837 if (it.waypointsprite_attached)
838 WaypointSprite_Kill(it.waypointsprite_attached);
839 it.nextthink = 0; // disable any scheduled powerup spawn
840 }
841 else
842 Item_Reset(it);
843
844 // leave 'this' marked so Item_FindTeam() works when called again via this.reset
845 if(it != this)
846 it.effects &= ~EF_NOGUNBOB;
847 }
848 });
849}
850
852{
853 setorigin(to, this.origin);
854 to.spawnflags = this.spawnflags;
855 to.noalign = ITEM_SHOULD_KEEP_POSITION(this);
856 to.cnt = this.cnt;
857 to.team = this.team;
858 to.spawnfunc_checked = true;
859 // TODO: copy respawn times? this may not be desirable in some cases
860 //to.respawntime = this.respawntime;
861 //to.respawntimejitter = this.respawntimejitter;
862}
863
864// Savage: used for item garbage-collection
866{
867 if(wasfreed(this) || !this) { return; }
870
871 if (this.SendFlags & ISF_REMOVEFX)
872 {
873 // delay removal until ISF_REMOVEFX has been sent
874 setthink(this, RemoveItem);
875 this.nextthink = time + 2 * autocvar_sys_ticrate; // micro optimisation: next frame will be too soon
876 this.solid = SOLID_NOT; // untouchable
877 }
878 else
879 delete(this);
880}
881
882// pickup evaluation functions
883// these functions decide how desirable an item is to the bots
884
885float generic_pickupevalfunc(entity player, entity item) {return item.bot_pickupbasevalue;}
886
888{
889 // See if I have it already
890 if(STAT(WEAPONS, player) & STAT(WEAPONS, item))
891 {
892 // If I can pick it up
893 if(!item.spawnshieldtime)
894 return 0;
895 return ammo_pickupevalfunc(player, item);
896 }
897
898 // reduce weapon value if bot already got a good arsenal
899 float c = 1;
900 int weapons_value = 0;
901 FOREACH(Weapons, it != WEP_Null && (STAT(WEAPONS, player) & it.m_wepset), {
902 weapons_value += it.bot_pickupbasevalue;
903 });
904 c -= bound(0, weapons_value / 20000, 1) * 0.5;
905
906 return item.bot_pickupbasevalue * c;
907}
908
910{
911 entity item_resource = NULL; // pointer to the resource that may be associated with the given item
912 entity wpn = NULL;
913 float c = 0;
914 float rating = 0;
915
916 // detect needed ammo
917 if(item.itemdef.instanceOfWeaponPickup)
918 {
919 entity res = item.itemdef.m_weapon.ammo_type;
920 entity ammo = (res != RES_NONE) ? GetAmmoItem(res) : NULL;
921 if(!ammo)
922 return 0;
923 if(res != RES_NONE && GetResource(item, res))
924 item_resource = res;
925
926 wpn = item;
927 rating = ammo.m_botvalue;
928 }
929 else
930 {
931 FOREACH(Weapons, it != WEP_Null, {
932 if(!(STAT(WEAPONS, player) & (it.m_wepset)))
933 continue;
934 if(it.ammo_type == RES_NONE)
935 continue;
936
937 if(GetResource(item, it.ammo_type))
938 {
939 item_resource = it.ammo_type;
940 break;
941 }
942 });
943 rating = item.bot_pickupbasevalue;
944 }
945
946 float noammorating = 0.5;
947
948 if(item_resource && (GetResource(player, item_resource) < GetResourceLimit(player, item_resource)))
949 c = GetResource(item, item_resource) / max(noammorating, GetResource(player, item_resource));
950
951 rating *= min(c, 2);
952 if(wpn)
953 rating += wpn.bot_pickupbasevalue * 0.1;
954 return rating;
955}
956
958{
959 float c = 0;
960 float rating = item.bot_pickupbasevalue;
961
962 float itemarmor = GetResource(item, RES_ARMOR);
963 float itemhealth = GetResource(item, RES_HEALTH);
964
965 if(item.item_group)
966 {
967 itemarmor *= min(4, item.item_group_count);
968 itemhealth *= min(4, item.item_group_count);
969 }
970
971 if (itemarmor && (GetResource(player, RES_ARMOR) < item.max_armorvalue))
972 c = itemarmor / max(1, GetResource(player, RES_ARMOR) * 2/3 + GetResource(player, RES_HEALTH) * 1/3);
973
974 if (itemhealth && (GetResource(player, RES_HEALTH) < item.max_health))
975 c = itemhealth / max(1, GetResource(player, RES_HEALTH));
976
977 rating *= min(2, c);
978 return rating;
979}
980
981void Item_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
982{
983 if(ITEM_DAMAGE_NEEDKILL(deathtype))
984 RemoveItem(this);
985}
986
987void item_use(entity this, entity actor, entity trigger)
988{
989 if (this.spawnflags & 16)
990 gettouch(this)(this, actor);
991 else // q3compat
992 Item_Respawn(this);
993}
994
995void item_setactive(entity this, int act)
996{
997 int old_status = this.active;
998 if(act == ACTIVE_TOGGLE)
1000 else
1001 this.active = act;
1002
1003 if(this.active != old_status)
1004 Item_Show(this, ((this.active == ACTIVE_ACTIVE) ? 1 : -1));
1005}
1006
1007void StartItem(entity this, entity def)
1008{
1009 if (def.m_spawnfunc_hookreplace)
1010 def = def.m_spawnfunc_hookreplace(def, this);
1011 this.itemdef = def;
1012 if (def.m_canonical_spawnfunc != "") // FIXME why do weapons set itemdef to an entity that doesn't have this?
1013 this.classname = def.m_canonical_spawnfunc;
1014
1015 startitem_failed = true; // early return means failure
1016
1017 // some mutators check for resources set by m_iteminit in FilterItem
1018 if(def.m_iteminit)
1019 def.m_iteminit(def, this);
1020
1021 // also checked by some mutators in FilterItem
1022 this.items = def.m_itemid;
1023 this.weapon = def.instanceOfWeaponPickup ? def.m_weapon.m_id : 0;
1024 if(this.weapon)
1025 STAT(WEAPONS, this) = WepSet_FromWeapon(REGISTRY_GET(Weapons, this.weapon));
1026 this.flags = FL_ITEM | def.m_itemflags;
1027
1028 // FilterItem may change any field of a specific instance of an item, but
1029 // it must not change any itemdef field (would cause mutators to break other mutators),
1030 // and must not convert items into different ones (StartItem could be refactored to support that).
1031 if(MUTATOR_CALLHOOK(FilterItem, this))
1032 {
1033 delete(this);
1034 return;
1035 }
1036
1037 if (!this.item_model_ent)
1038 this.item_model_ent = def.m_model;
1039
1040 if (!this.item_pickupsound_ent)
1041 this.item_pickupsound_ent = def.m_sound;
1042 if (!this.item_pickupsound && this.item_pickupsound_ent)
1044 if (this.item_pickupsound == "")
1045 LOG_WARNF("No pickup sound set for a %s", this.classname);
1046
1047 if(!this.pickup_anyway && def.m_pickupanyway)
1048 this.pickup_anyway = def.m_pickupanyway;
1049
1050 // bones_was_here TODO: implement sv_cullentities_dist and replace g_items_maxdist with it
1051 if(!this.fade_end)
1053
1054 // bones_was_here TODO: can we do this after we're sure the entity won't be deleted?
1055 IL_PUSH(g_items, this);
1056
1057 this.mdl = this.model ? this.model : strzone(this.item_model_ent.model_str());
1058 setmodel(this, MDL_Null); // precision set below
1059 // set item size before we spawn a waypoint or droptofloor or MoveOutOfSolid
1060 setsize (this, this.pos1 = def.m_mins, this.pos2 = def.m_maxs);
1061
1062 if (ITEM_IS_LOOT(this))
1063 {
1064 this.reset = RemoveItem;
1065
1067 this.gravity = 1;
1068
1069 setthink(this, Item_Think);
1072
1073 this.owner = NULL; // anyone can pick this up, including the player who threw it
1074 this.item_spawnshieldtime = time + 0.5; // but not straight away
1075
1076 this.takedamage = DAMAGE_YES;
1077 this.event_damage = Item_Damage;
1078 // enable this to have thrown items burn in lava
1079 //this.damagedbycontents = true;
1080 //IL_PUSH(g_damagedbycontents, this);
1081
1082 if (ITEM_IS_EXPIRING(this))
1083 {
1084 // if item is worthless after a timer, have it expire then
1086 }
1087
1088 // most loot items have a bigger horizontal size than a player
1089 nudgeoutofsolid_OrFallback(this);
1090
1091 // don't drop if in a NODROP zone (such as lava)
1092 traceline(this.origin, this.origin, MOVE_NORMAL, this);
1094 {
1095 delete(this);
1096 return;
1097 }
1098 }
1099 else
1100 {
1101 // must be done after def.m_iteminit() as that may set ITEM_FLAG_MUTATORBLOCKED
1102 if(!have_pickup_item(this))
1103 {
1104 delete(this);
1105 return;
1106 }
1107
1108 // must be done before Item_Reset() and after MUTATORBLOCKED check (blocked items may be uninitialised)
1109 if(!this.respawntime)
1110 {
1111 if (def.m_respawntime)
1112 this.respawntime = def.m_respawntime;
1113 else
1114 LOG_WARNF("Default respawntime for a %s is unavailable from its itemdef", this.classname);
1115 }
1116
1117 this.reset = Item_Reset;
1118
1119 if(this.angles != '0 0 0')
1120 this.SendFlags |= ISF_ANGLES;
1121
1122 if(q3compat)
1123 {
1124 if (!this.team)
1125 {
1126 string t = GetField_fullspawndata(this, "team", false);
1127 // bones_was_here: this hack is cheaper than changing to a .string strcmp()
1128 if(t) this.team = crc16(false, t);
1129 }
1130
1131 // In Q3 the origin is in the middle of the bbox ("radius" 15), in Xon it's at the bottom
1132 // so we need to offset vertically (only for items placed by the mapper).
1133 this.origin.z += -15 - this.mins.z;
1134 setorigin(this, this.origin);
1135 }
1136
1137 // it's a level item
1138 if(this.spawnflags & 1)
1139 this.noalign = 1;
1140 if (this.noalign > 0)
1142 else
1144 // do item filtering according to gametype and other things
1145 if (this.noalign <= 0)
1146 {
1147 if (!this.noalign)
1150 }
1151
1152 if (this.targetname != "")
1153 this.use = item_use;
1154
1155 this.setactive = item_setactive;
1156 this.active = ACTIVE_ACTIVE;
1157
1158 if(autocvar_spawn_debug >= 2)
1159 {
1160 // why not flags & fl_item?
1161 FOREACH_ENTITY_RADIUS(this.origin, 3, it.is_item, {
1162 LOG_TRACE("XXX Found duplicated item: ", def.m_name, vtos(this.origin));
1163 LOG_TRACE(" vs ", it.netname, vtos(it.origin));
1164 error("Mapper sucks.");
1165 });
1166 this.is_item = true;
1167 }
1168
1170
1171 if ( def.instanceOfPowerup
1172 || def.instanceOfWeaponPickup
1173 || (def.instanceOfHealth && def != ITEM_HealthSmall)
1174 || (def.instanceOfArmor && def != ITEM_ArmorSmall)
1175 || (def.m_itemid & (IT_KEY1 | IT_KEY2))
1176 )
1177 {
1178 if(!this.target || this.target == "")
1179 this.target = "###item###"; // for finding the nearest item using findnearest
1180 }
1181
1182 Item_ItemsTime_SetTime(this, 0);
1183
1184 this.glowmod = def.m_color;
1185 }
1186
1187 this.bot_pickup = true;
1188 this.bot_pickupevalfunc = def.m_pickupevalfunc;
1189 this.bot_pickupbasevalue = def.m_botvalue;
1190 this.netname = def.m_name;
1191 settouch(this, Item_Touch);
1192 //this.effects |= EF_LOWPRECISION;
1193
1194 // support skinned models for powerups
1195 if(!this.skin)
1196 this.skin = def.m_skin;
1197
1198 if (!(this.spawnflags & 1024)) {
1199 if(def.instanceOfPowerup)
1200 this.ItemStatus |= ITS_ANIMATE1;
1201
1202 if(GetResource(this, RES_ARMOR) || GetResource(this, RES_HEALTH))
1203 this.ItemStatus |= ITS_ANIMATE2;
1204 }
1205
1206 if(def.instanceOfWeaponPickup)
1207 {
1208 if (!ITEM_IS_LOOT(this)) // if dropped, colormap is already set up nicely
1209 this.colormap = 1024; // color shirt=0 pants=0 grey
1210 if (!(this.spawnflags & 1024))
1211 this.ItemStatus |= ITS_ANIMATE1;
1212 this.SendFlags |= ISF_COLORMAP;
1213 }
1214
1215 this.state = 0;
1216 if(this.team)
1217 {
1218 if(!this.cnt)
1219 this.cnt = 1; // item probability weight
1220
1221 this.effects |= EF_NOGUNBOB; // marker for item team search
1223 this.reset = Item_FindTeam;
1224 }
1225 else
1226 Item_Reset(this);
1227
1228 Net_LinkEntity(this, !(def.instanceOfPowerup || def.instanceOfHealth || def.instanceOfArmor), 0, ItemSend);
1229
1230 // call this hook after everything else has been done
1231 if (MUTATOR_CALLHOOK(Item_Spawn, this))
1232 {
1233 delete(this);
1234 return;
1235 }
1236
1237 // we should be sure this item will spawn before loading its assets
1238 // CSQC handles model precaching: it may not use this model (eg simple items) and may not have connected yet
1239 //precache_model(this.mdl);
1241
1242 setItemGroup(this);
1243
1244 startitem_failed = false;
1245}
1246
1247#define IS_SMALL(def) ((def.instanceOfHealth && def == ITEM_HealthSmall) || (def.instanceOfArmor && def == ITEM_ArmorSmall))
1249
1251{
1252 if(!IS_SMALL(this.itemdef) || ITEM_IS_LOOT(this))
1253 return;
1254
1255 FOREACH_ENTITY_RADIUS(this.origin, 120, (it != this) && IS_SMALL(it.itemdef),
1256 {
1257 if(!this.item_group)
1258 {
1259 if(!it.item_group)
1260 {
1261 it.item_group = group_count;
1262 group_count++;
1263 }
1264 this.item_group = it.item_group;
1265 }
1266 else // spawning item is already part of a item_group X
1267 {
1268 if(!it.item_group)
1269 it.item_group = this.item_group;
1270 else if(it.item_group != this.item_group) // found an item near the spawning item that is part of a different item_group Y
1271 {
1272 int grY = it.item_group;
1273 // move all items of item_group Y to item_group X
1274 IL_EACH(g_items, IS_SMALL(it.itemdef),
1275 {
1276 if(it.item_group == grY)
1277 it.item_group = this.item_group;
1278 });
1279 }
1280 }
1281 });
1282}
1283
1285{
1286 for (int k = 1; k <= group_count; ++k)
1287 {
1288 int count = 0;
1289 IL_EACH(g_items, IS_SMALL(it.itemdef) && it.item_group == k, { count++; });
1290 if (count)
1291 IL_EACH(g_items, IS_SMALL(it.itemdef) && it.item_group == k, { it.item_group_count = count; });
1292 }
1293}
1294
1295float GiveWeapon(entity e, float wpn, float op, float val)
1296{
1297 WepSet v0, v1;
1299 v0 = (STAT(WEAPONS, e) & s);
1300 switch(op)
1301 {
1302 case OP_SET:
1303 if(val > 0)
1304 STAT(WEAPONS, e) |= s;
1305 else
1306 STAT(WEAPONS, e) &= ~s;
1307 break;
1308 case OP_MIN:
1309 case OP_PLUS:
1310 if(val > 0)
1311 STAT(WEAPONS, e) |= s;
1312 break;
1313 case OP_MAX:
1314 if(val <= 0)
1315 STAT(WEAPONS, e) &= ~s;
1316 break;
1317 case OP_MINUS:
1318 if(val > 0)
1319 STAT(WEAPONS, e) &= ~s;
1320 break;
1321 }
1322 v1 = (STAT(WEAPONS, e) & s);
1323 return (v0 != v1);
1324}
1325
1326bool GiveBuff(entity e, Buff thebuff, int op, int val)
1327{
1328 bool had_buff = StatusEffects_active(thebuff, e);
1329 float new_buff_time = ((had_buff) ? StatusEffects_gettime(thebuff, e) : time);
1330 switch (op)
1331 {
1332 case OP_SET:
1333 new_buff_time = time + val;
1334 break;
1335 case OP_MIN:
1336 new_buff_time = max(new_buff_time, time + val);
1337 break;
1338 case OP_MAX:
1339 new_buff_time = min(new_buff_time, time + val);
1340 break;
1341 case OP_PLUS:
1342 new_buff_time += val;
1343 break;
1344 case OP_MINUS:
1345 new_buff_time -= val;
1346 break;
1347 }
1348 if(new_buff_time <= time)
1349 {
1350 if(had_buff) // only trigger removal mechanics if there is an effect to remove!
1352 }
1353 else
1354 {
1355 buff_RemoveAll(e, STATUSEFFECT_REMOVE_CLEAR); // clear old buffs on the player first!
1356 StatusEffects_apply(thebuff, e, new_buff_time, 0);
1357 }
1358 bool have_buff = StatusEffects_active(thebuff, e);
1359 return (had_buff != have_buff);
1360}
1361
1362void GiveSound(entity e, float v0, float v1, float t, Sound snd_incr, Sound snd_decr)
1363{
1364 if(v1 == v0)
1365 return;
1366 if(v1 <= v0 - t)
1367 {
1368 if(snd_decr != NULL)
1369 sound(e, CH_TRIGGER, snd_decr, VOL_BASE, ATTEN_NORM);
1370 }
1371 else if(v0 >= v0 + t)
1372 {
1373 if(snd_incr != NULL)
1374 sound(e, ((snd_incr == SND_POWERUP) ? CH_TRIGGER_SINGLE : CH_TRIGGER), snd_incr, VOL_BASE, ATTEN_NORM);
1375 }
1376}
1377
1378void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .float regenfield, float regentime)
1379{
1380 if(v0 < v1)
1381 e.(rotfield) = max(e.(rotfield), time + rottime);
1382 else if(v0 > v1)
1383 e.(regenfield) = max(e.(regenfield), time + regentime);
1384}
1385bool GiveResourceValue(entity e, Resource res_type, int op, int val)
1386{
1387 int v0 = GetResource(e, res_type);
1388 float new_val = 0;
1389 switch (op)
1390 {
1391 // min 100 cells = at least 100 cells
1392 case OP_SET: new_val = val; break;
1393 case OP_MIN: new_val = max(v0, val); break;
1394 case OP_MAX: new_val = min(v0, val); break;
1395 case OP_PLUS: new_val = v0 + val; break;
1396 case OP_MINUS: new_val = v0 - val; break;
1397 default: return false;
1398 }
1399
1400 return SetResourceExplicit(e, res_type, new_val);
1401}
1402bool GiveStatusEffect(entity e, StatusEffect this, int op, float val)
1403{
1404 bool had_eff = StatusEffects_active(this, e);
1405 float new_eff_time = ((had_eff) ? StatusEffects_gettime(this, e) : time);
1406 switch (op)
1407 {
1408 case OP_SET:
1409 new_eff_time = time + val;
1410 break;
1411 case OP_MIN:
1412 new_eff_time = max(new_eff_time, time + val);
1413 break;
1414 case OP_MAX:
1415 new_eff_time = min(new_eff_time, time + val);
1416 break;
1417 case OP_PLUS:
1418 new_eff_time += val;
1419 break;
1420 case OP_MINUS:
1421 new_eff_time -= val;
1422 break;
1423 }
1424 if(new_eff_time <= time)
1425 {
1426 if(had_eff) // only trigger removal mechanics if there is an effect to remove!
1428 }
1429 else
1430 StatusEffects_apply(this, e, new_eff_time, 0);
1431 bool have_eff = StatusEffects_active(this, e);
1432 return (had_eff != have_eff);
1433}
1434
1435float GiveItems(entity e, float beginarg, float endarg)
1436{
1437 float got, i, val, op;
1438 string cmd;
1439
1440 val = 999;
1441 op = OP_SET;
1442
1443 got = 0;
1444
1445 int _switchweapon = 0;
1446
1447 bool use_cts_autoswitch = (g_cts && (CS_CVAR(e).cvar_cl_autoswitch_cts != -1));
1448 if(CS_CVAR(e).cvar_cl_autoswitch && !use_cts_autoswitch)
1449 {
1450 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
1451 {
1452 .entity weaponentity = weaponentities[slot];
1453 if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
1454 if(e.(weaponentity).m_switchweapon == w_getbestweapon(e, weaponentity))
1455 _switchweapon |= BIT(slot);
1456 }
1457 }
1458
1459 PREGIVE(e, items);
1460 PREGIVE_WEAPONS(e);
1461 PREGIVE_STATUSEFFECT(e, STATUSEFFECT_Strength);
1462 PREGIVE_STATUSEFFECT(e, STATUSEFFECT_Shield);
1463 PREGIVE_STATUSEFFECT(e, STATUSEFFECT_Speed);
1464 PREGIVE_STATUSEFFECT(e, STATUSEFFECT_Invisibility);
1465 //PREGIVE_STATUSEFFECT(e, STATUSEFFECT_Superweapon);
1466 PREGIVE_RESOURCE(e, RES_BULLETS);
1467 PREGIVE_RESOURCE(e, RES_CELLS);
1468 PREGIVE_RESOURCE(e, RES_SHELLS);
1469 PREGIVE_RESOURCE(e, RES_ROCKETS);
1470 PREGIVE_RESOURCE(e, RES_FUEL);
1472 PREGIVE_RESOURCE(e, RES_HEALTH);
1473
1474 Weapon last_wep = WEP_Null;
1475 for(i = beginarg; i < endarg; ++i)
1476 {
1477 cmd = argv(i);
1478
1479 if(cmd == "0" || stof(cmd))
1480 {
1481 val = stof(cmd);
1482 continue;
1483 }
1484 switch(cmd)
1485 {
1486 case "no":
1487 op = OP_MAX;
1488 val = 0;
1489 continue;
1490 case "max":
1491 op = OP_MAX;
1492 continue;
1493 case "min":
1494 op = OP_MIN;
1495 continue;
1496 case "plus":
1497 op = OP_PLUS;
1498 continue;
1499 case "minus":
1500 op = OP_MINUS;
1501 continue;
1502 case "ALL":
1503 got += GiveBit(e, items, ITEM_FuelRegen.m_itemid, op, val);
1504 FOREACH(StatusEffects, it.instanceOfPowerupStatusEffect, got += GiveStatusEffect(e, it, op, val));
1506 case "all":
1507 got += GiveBit(e, items, ITEM_Jetpack.m_itemid, op, val);
1508 got += GiveResourceValue(e, RES_HEALTH, op, val);
1509 got += GiveResourceValue(e, RES_ARMOR, op, val);
1510 case "allweapons":
1511 FOREACH(Weapons, it != WEP_Null && !(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN)),
1512 got += GiveWeapon(e, it.m_id, op, val));
1513 //case "allbuffs": // all buffs makes a player god, do not want!
1514 //FOREACH(StatusEffects, it.instanceOfBuff, got += GiveBuff(e, it, op, val));
1515 case "allammo":
1516 got += GiveResourceValue(e, RES_CELLS, op, val);
1517 got += GiveResourceValue(e, RES_SHELLS, op, val);
1518 got += GiveResourceValue(e, RES_BULLETS, op, val);
1519 got += GiveResourceValue(e, RES_ROCKETS, op, val);
1520 got += GiveResourceValue(e, RES_FUEL, op, val);
1521 break;
1522 case "unlimited_ammo":
1523 // this is from a time when unlimited superweapons were handled together with ammo in some parts of the code
1525 break;
1526 case "unlimited_weapon_ammo":
1527 got += GiveBit(e, items, IT_UNLIMITED_AMMO, op, val);
1528 break;
1529 case "unlimited_superweapons":
1530 got += GiveBit(e, items, IT_UNLIMITED_SUPERWEAPONS, op, val);
1531 break;
1532 case "jetpack":
1533 got += GiveBit(e, items, ITEM_Jetpack.m_itemid, op, val);
1534 break;
1535 case "fuel_regen":
1536 got += GiveBit(e, items, ITEM_FuelRegen.m_itemid, op, val);
1537 break;
1538 case "strength":
1539 got += GiveStatusEffect(e, STATUSEFFECT_Strength, op, val);
1540 break;
1541 case "invincible":
1542 case "shield":
1543 got += GiveStatusEffect(e, STATUSEFFECT_Shield, op, val);
1544 break;
1545 case "speed":
1546 got += GiveStatusEffect(e, STATUSEFFECT_Speed, op, val);
1547 break;
1548 case "invisibility":
1549 got += GiveStatusEffect(e, STATUSEFFECT_Invisibility, op, val);
1550 break;
1551 case "superweapons":
1552 got += GiveStatusEffect(e, STATUSEFFECT_Superweapon, op, val);
1553 break;
1554 case "cells":
1555 got += GiveResourceValue(e, RES_CELLS, op, val);
1556 break;
1557 case "shells":
1558 got += GiveResourceValue(e, RES_SHELLS, op, val);
1559 break;
1560 case "nails":
1561 case "bullets":
1562 got += GiveResourceValue(e, RES_BULLETS, op, val);
1563 break;
1564 case "rockets":
1565 got += GiveResourceValue(e, RES_ROCKETS, op, val);
1566 break;
1567 case "health":
1568 got += GiveResourceValue(e, RES_HEALTH, op, val);
1569 break;
1570 case "armor":
1571 got += GiveResourceValue(e, RES_ARMOR, op, val);
1572 break;
1573 case "fuel":
1574 got += GiveResourceValue(e, RES_FUEL, op, val);
1575 break;
1576 default:
1577 FOREACH(StatusEffects, it.instanceOfBuff && buff_Available(it) && Buff_CompatName(cmd) == it.netname,
1578 {
1579 got += GiveBuff(e, it, op, val);
1580 break;
1581 });
1582 FOREACH(Weapons, it != WEP_Null && (cmd == it.netname || cmd == it.m_deprecated_netname), {
1583 got += GiveWeapon(e, it.m_id, op, val);
1584 if(use_cts_autoswitch && CS_CVAR(e).cvar_cl_autoswitch_cts == 1)
1585 if(val > 0 && (op == OP_SET || op == OP_PLUS || op == OP_MIN)) // switch to any given weapons, even if we already had it
1586 last_wep = it; // (... non-CTS autoswitching can switch to a weapon we already have, so CTS autoswitch should be the same)
1587 break;
1588 });
1589 break;
1590 }
1591 val = 999;
1592 op = OP_SET;
1593 }
1594
1595 POSTGIVE_BIT(e, items, ITEM_FuelRegen.m_itemid, SND_ITEMPICKUP, SND_Null);
1596 POSTGIVE_BIT(e, items, IT_UNLIMITED_SUPERWEAPONS, SND_POWERUP, SND_POWEROFF);
1597 POSTGIVE_BIT(e, items, IT_UNLIMITED_AMMO, SND_POWERUP, SND_POWEROFF);
1598 POSTGIVE_BIT(e, items, ITEM_Jetpack.m_itemid, SND_ITEMPICKUP, SND_Null);
1599 FOREACH(Weapons, it != WEP_Null, {
1600 POSTGIVE_WEAPON(e, it, SND_WEAPONPICKUP, SND_Null);
1601 if(!(save_weapons & (it.m_wepset)))
1602 if(STAT(WEAPONS, e) & (it.m_wepset))
1603 it.wr_init(it);
1604 });
1605 POSTGIVE_STATUSEFFECT(e, STATUSEFFECT_Strength, SND_POWERUP, SND_POWEROFF);
1606 POSTGIVE_STATUSEFFECT(e, STATUSEFFECT_Shield, SND_POWERUP, SND_POWEROFF);
1607 POSTGIVE_STATUSEFFECT(e, STATUSEFFECT_Speed, SND_POWERUP, SND_POWEROFF);
1608 POSTGIVE_STATUSEFFECT(e, STATUSEFFECT_Invisibility, SND_POWERUP, SND_POWEROFF);
1609 POSTGIVE_RESOURCE(e, RES_BULLETS, 0, SND_ITEMPICKUP, SND_Null);
1610 POSTGIVE_RESOURCE(e, RES_CELLS, 0, SND_ITEMPICKUP, SND_Null);
1611 POSTGIVE_RESOURCE(e, RES_SHELLS, 0, SND_ITEMPICKUP, SND_Null);
1612 POSTGIVE_RESOURCE(e, RES_ROCKETS, 0, SND_ITEMPICKUP, SND_Null);
1616
1617 if(!StatusEffects_active(STATUSEFFECT_Superweapon, e))
1618 {
1619 // also give default superweapon time if player had no superweapons and just got one
1620 if(!g_weaponarena && !(save_weapons & WEPSET_SUPERWEAPONS) && (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
1621 StatusEffects_apply(STATUSEFFECT_Superweapon, e, time + autocvar_g_balance_superweapons_time, 0);
1622 }
1623
1624 if(e.statuseffects)
1626
1627 if(use_cts_autoswitch)
1628 {
1629 // CTS handling: never switch (0), always switch (1)
1630 if(last_wep != WEP_Null)
1631 if(CS_CVAR(e).cvar_cl_autoswitch_cts == 1)
1632 {
1633 // crude hack to enforce switching weapons
1634 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
1635 {
1636 .entity weaponentity = weaponentities[slot];
1637 if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
1638 if(client_hasweapon(e, last_wep, weaponentity, true, false)) // ammo check
1639 W_SwitchWeapon_Force(e, last_wep, weaponentity);
1640 }
1641 }
1642 }
1643 else
1644 {
1645 // non-CTS handling: weaponpriority-based autoswitch
1646 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
1647 {
1648 .entity weaponentity = weaponentities[slot];
1649 if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
1650 if(!(STAT(WEAPONS, e) & WepSet_FromWeapon(e.(weaponentity).m_switchweapon)))
1651 _switchweapon |= BIT(slot);
1652
1653 if(_switchweapon & BIT(slot))
1654 {
1655 Weapon best_wep = w_getbestweapon(e, weaponentity);
1656 if(e.(weaponentity).m_switchweapon != best_wep)
1657 W_SwitchWeapon_Force(e, best_wep, weaponentity);
1658 }
1659 }
1660 }
1661
1662 return got;
1663}
void waypoint_spawnforitem(entity e)
float bot_pickup
Definition api.qh:43
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition bits.qh:8
ERASEABLE bool GiveBit(entity e,.int fld, int bit, int op, int val)
Definition bits.qh:85
@ OP_MIN
Definition bits.qh:78
@ OP_PLUS
Definition bits.qh:80
@ OP_MAX
Definition bits.qh:79
@ OP_SET
Definition bits.qh:77
@ OP_MINUS
Definition bits.qh:81
float bot_pickupbasevalue
Definition bot.qh:68
string Buff_CompatName(string buffname)
Definition buffs.qc:10
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
void TakeResourceWithLimit(entity receiver, Resource res_type, float amount, float limit)
Takes an entity some resource but not less than a limit.
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
Definition buffs.qh:17
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition weapon.qh:44
string netname
Definition powerups.qc:20
float cnt
Definition powerups.qc:24
float count
Definition powerups.qc:22
float wait
Definition items.qc:17
float gravity
Definition items.qh:17
entity players
Definition main.qh:57
entity owner
Definition main.qh:87
int team
Definition main.qh:188
int autocvar_g_pickup_rockets_max
Definition ammo.qh:116
int spawnflags
Definition ammo.qh:15
int autocvar_g_pickup_fuel_max
Definition ammo.qh:188
int autocvar_g_pickup_shells_max
Definition ammo.qh:44
int autocvar_g_pickup_cells_max
Definition ammo.qh:152
int autocvar_g_pickup_nails_max
Definition ammo.qh:80
float fade_end
Definition item.qh:87
const int ITS_STAYWEP
Definition item.qh:62
float strength_finished
Definition item.qh:93
const int ISF_COLORMAP
Definition item.qh:53
const int ITS_ALLOWSI
Definition item.qh:67
const int ITS_EXPIRING
Definition item.qh:69
const int ITS_ALLOWFB
Definition item.qh:66
const int ITS_GLOW
Definition item.qh:68
const int IT_JETPACK
Definition item.qh:26
const float IT_UPDATE_INTERVAL
Definition item.qh:76
const int IT_PICKUPMASK
Definition item.qh:46
string mdl
Definition item.qh:89
const int IT_FUEL_REGEN
Definition item.qh:28
const int IT_UNLIMITED_AMMO
Definition item.qh:23
const int ITS_AVAILABLE
Definition item.qh:65
const int ISF_SIZE2
Definition item.qh:51
const vector ITEM_S_MAXS
Definition item.qh:81
const int IT_UNLIMITED_SUPERWEAPONS
Definition item.qh:24
int ItemStatus
Definition item.qh:61
const int IT_RESOURCE
Definition item.qh:30
const vector ITEM_L_MAXS
Definition item.qh:84
float invincible_finished
Definition item.qh:94
const int ITS_ANIMATE1
Definition item.qh:63
const int ISF_STATUS
Definition item.qh:52
@ ITEM_FLAG_MUTATORBLOCKED
Definition item.qh:121
const int ISF_REMOVEFX
Definition item.qh:49
const int ISF_ANGLES
Definition item.qh:55
#define ITEM_HANDLE(signal,...)
Definition item.qh:125
const float IT_DESPAWNFX_TIME
Definition item.qh:72
const int ITS_ANIMATE2
Definition item.qh:64
const int ISF_SIZE
Definition item.qh:56
const int ISF_LOCATION
Definition item.qh:50
const int ISF_DROP
Definition item.qh:54
#define setmodel(this, m)
Definition model.qh:26
#define M_ARGV(x, type)
Definition events.qh:17
int items
Definition player.qh:226
#define IS_DEAD(s)
Definition player.qh:244
vector weaponsInMap
all the weapons actually spawned in the map, does not include filtered items
Definition stats.qh:53
float game_starttime
Definition stats.qh:82
#define LABEL(id)
Definition compiler.qh:34
const int FL_PICKUPITEMS
Definition constants.qh:88
const int INITPRIO_FINDTARGET
Definition constants.qh:96
const int FL_ITEM
Definition constants.qh:77
string classname
float flags
const float EF_STARDUST
float DPCONTENTS_NODROP
const float SOLID_TRIGGER
const float MOVE_NORMAL
vector mins
float trace_dpstartcontents
vector velocity
const float EF_ADDITIVE
const float EF_FULLBRIGHT
const float SOLID_NOT
float effects
float skin
float time
vector maxs
float nextthink
float colormap
const float EF_NODEPTHTEST
vector origin
vector oldorigin
#define use
vector glowmod
#define g_cts
Definition cts.qh:36
#define AUTOCVAR(...)
Definition cvar.qh:161
float spawnshieldtime
Definition damage.qh:61
void W_SwitchWeapon_Force(Player this, Weapon w,.entity weaponentity)
Definition selection.qc:246
int state
const int ACTIVE_TOGGLE
Definition defs.qh:40
const int ACTIVE_NOT
Definition defs.qh:36
int active
Definition defs.qh:34
const int ACTIVE_ACTIVE
Definition defs.qh:37
float EF_NOGUNBOB
#define tokenize_console
RES_ARMOR
Definition ent_cs.qc:130
ent angles
Definition ent_cs.qc:121
model
Definition ent_cs.qc:139
solid
Definition ent_cs.qc:165
Weapons
Definition guide.qh:113
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define IL_EACH(this, cond, body)
float invisibility_finished
#define ITEM_IS_LOOT(item)
Returns whether the item is loot.
Definition spawning.qh:39
#define ITEM_IS_EXPIRING(item)
Returns whether the item is expiring (i.e.
Definition spawning.qh:58
bool startitem_failed
Definition spawning.qh:7
#define ITEM_SHOULD_KEEP_POSITION(item)
Returns whether item should keep its position or be dropped to the ground.
Definition spawning.qh:52
#define FOREACH_ENTITY_RADIUS(org, dist, cond, body)
Definition iter.qh:160
#define FOREACH(list, cond, body)
Definition iter.qh:19
void SUB_UseTargets(entity this, entity actor, entity trigger)
Definition triggers.qc:344
int SendFlags
Definition net.qh:118
const int MSG_ENTITY
Definition net.qh:115
#define WriteHeader(to, id)
Definition net.qh:221
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:123
#define STAT(...)
Definition stats.qh:82
#define LOG_WARNF(...)
Definition log.qh:62
#define LOG_TRACE(...)
Definition log.qh:76
float MSG_ONE
Definition menudefs.qc:56
float stof(string val,...)
float bound(float min, float value, float max)
void WriteString(string data, float dest, float desto)
float random(void)
void WriteShort(float data, float dest, float desto)
void cmd(string command,...)
string precache_sound(string sample)
float min(float f,...)
string ftos(float f)
void WriteByte(float data, float dest, float desto)
float floor(float f)
string strzone(string s)
string argv(float n)
float max(float f,...)
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_NONE
Definition movetypes.qh:129
const int MOVETYPE_TOSS
Definition movetypes.qh:135
#define IS_ONGROUND(s)
Definition movetypes.qh:16
float speed_finished
Definition speed.qh:17
@ STATUSEFFECT_REMOVE_CLEAR
Effect is being forcibly removed without calling any additional mechanics.
Definition all.qh:30
@ STATUSEFFECT_REMOVE_NORMAL
Effect is being removed by a function, calls regular removal mechanics.
Definition all.qh:28
string string_null
Definition nil.qh:9
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
Definition all.qc:1573
#define NULL
Definition post.qh:14
float weapon
Definition progsdefs.qc:139
entity msg_entity
Definition progsdefs.qc:63
q3compat
Definition quake3.qc:59
ERASEABLE void RandomSelection_Init()
Definition random.qc:4
#define RandomSelection_AddEnt(e, weight, priority)
Definition random.qh:14
entity RandomSelection_chosen_ent
Definition random.qh:5
#define crandom()
Returns a random number between -1.0 and 1.0.
Definition random.qh:32
#define REGISTRY_GET(id, i)
Definition registry.qh:43
bool client_hasweapon(entity this, Weapon wpn,.entity weaponentity, float andammo, bool complain)
Definition selection.qc:48
#define w_getbestweapon(ent, wepent)
Definition selection.qh:23
#define getSendEntity(e)
#define gettouch(e)
Definition self.qh:74
#define setthink(e, f)
vector
Definition self.qh:92
entity entity toucher
Definition self.qh:72
#define settouch(e, f)
Definition self.qh:73
float pauserotfuel_finished
Definition client.qh:340
int autocvar_spawn_debug
Definition client.qh:51
float pauseregen_finished
Definition client.qh:337
float pauserothealth_finished
Definition client.qh:338
float pauserotarmor_finished
Definition client.qh:339
float generic_pickupevalfunc(entity player, entity item)
Definition items.qc:885
bool Item_ItemsTime_SpectatorOnly(GameItem it)
Definition itemstime.qc:58
float ammo_pickupevalfunc(entity player, entity item)
Definition items.qc:909
float Item_ItemsTime_UpdateTime(entity e, float t)
Definition itemstime.qc:129
void Item_NotifyWeapon(entity player, int wep)
Definition items.qc:513
void GiveRot(entity e, float v0, float v1,.float rotfield, float rottime,.float regenfield, float regentime)
Definition items.qc:1378
float adjust_respawntime(float normal_respawntime)
Adjust respawn time according to the number of players.
Definition items.qc:357
void Item_ScheduleRespawn(entity e)
Definition items.qc:385
void Item_ItemsTime_SetTimesForAllPlayers()
Definition itemstime.qc:122
void Item_CopyFields(entity this, entity to)
Definition items.qc:851
bool GiveStatusEffect(entity e, StatusEffect this, int op, float val)
Definition items.qc:1402
bool GiveBuff(entity e, Buff thebuff, int op, int val)
Definition items.qc:1326
bool ItemSend(entity this, entity to, int sf)
Definition items.qc:31
void Item_RespawnThink(entity this)
Definition items.qc:315
bool Item_GiveAmmoTo(entity item, entity player, Resource res_type, float ammomax)
Definition items.qc:485
void Item_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition items.qc:981
void setItemGroupCount()
Definition items.qc:1284
void ItemUpdate(entity this)
Definition items.qc:100
void StartItem(entity this, entity def)
Definition items.qc:1007
void Item_ScheduleInitialRespawn(entity e)
Definition items.qc:405
void Item_ScheduleRespawnIn(entity e, float t)
Definition items.qc:325
void UpdateItemAfterTeleport(entity this)
Definition items.qc:106
void RemoveItem(entity this)
Definition items.qc:865
float weapon_pickupevalfunc(entity player, entity item)
Definition items.qc:887
float GiveWeapon(entity e, float wpn, float op, float val)
Definition items.qc:1295
void Item_Think(entity this)
Definition items.qc:192
void Item_RespawnCountdown(entity this)
Definition items.qc:257
void Item_Show(entity e, int mode)
Definition items.qc:130
void setItemGroup(entity this)
Definition items.qc:1250
void item_use(entity this, entity actor, entity trigger)
Definition items.qc:987
void Item_ItemsTime_SetTime(entity e, float t)
Definition itemstime.qc:107
void Item_FindTeam(entity this)
Definition items.qc:813
float GiveItems(entity e, float beginarg, float endarg)
Definition items.qc:1435
bool have_pickup_item(entity this)
Definition items.qc:112
bool Item_ItemsTime_Allow(GameItem it)
Definition itemstime.qc:66
void Item_Reset(entity this)
Definition items.qc:783
bool GiveResourceValue(entity e, Resource res_type, int op, int val)
Definition items.qc:1385
#define IS_SMALL(def)
Definition items.qc:1247
float healtharmor_pickupevalfunc(entity player, entity item)
Definition items.qc:957
void item_setactive(entity this, int act)
Definition items.qc:995
void GiveSound(entity e, float v0, float v1, float t, Sound snd_incr, Sound snd_decr)
Definition items.qc:1362
void GiveRandomWeapons(entity receiver, int num_weapons, string weapon_names, entity ammo_entity)
Give several random weapons and ammo to the entity.
Definition items.qc:440
bool Item_GiveTo(entity item, entity player)
Definition items.qc:522
void Item_Respawn(entity this)
Definition items.qc:241
void Item_Touch(entity this, entity toucher)
Definition items.qc:686
int group_count
Definition items.qc:1248
float autocvar_g_balance_superweapons_time
Definition items.qh:7
entity item_pickupsound_ent
Definition items.qh:23
int autocvar_g_pickup_items
Definition items.qh:11
float item_respawncounter
Definition items.qh:35
IntrusiveList g_items
Definition items.qh:119
#define ITEM_TOUCH_NEEDKILL()
Definition items.qh:122
#define ITEM_DAMAGE_NEEDKILL(dt)
Definition items.qh:123
#define POSTGIVE_WEAPON(e, b, snd_incr, snd_decr)
Definition items.qh:109
float autocvar_sv_simple_items
Definition items.qh:15
#define PREGIVE_WEAPONS(e)
Definition items.qh:105
entity itemdef
Definition items.qh:92
entity item_model_ent
Definition items.qh:24
#define POSTGIVE_RESOURCE(e, f, t, snd_incr, snd_decr)
Definition items.qh:112
#define PREGIVE(e, f)
Definition items.qh:106
bool autocvar_g_fullbrightitems
Definition items.qh:8
#define PREGIVE_STATUSEFFECT(e, f)
Definition items.qh:107
float superweapons_finished
Definition items.qh:39
const float ITEM_RESPAWN_TICKS
Definition items.qh:19
bool noalign
Definition items.qh:37
#define PREGIVE_RESOURCE(e, f)
Definition items.qh:108
float pickup_anyway
Definition items.qh:27
float autocvar_g_items_maxdist
Definition items.qh:9
bool autocvar_g_nodepthtestitems
Definition items.qh:12
#define POSTGIVE_STATUSEFFECT(e, f, snd_incr, snd_decr)
Definition items.qh:111
float item_spawnshieldtime
Definition items.qh:42
#define POSTGIVE_RES_ROT(e, f, t, rotfield, rottime, regenfield, regentime, snd_incr, snd_decr)
Definition items.qh:113
string item_pickupsound
Definition items.qh:22
#define POSTGIVE_BIT(e, f, b, snd_incr, snd_decr)
Definition items.qh:110
bool is_item
Definition items.qh:91
float respawntime
Definition items.qh:31
float autocvar_g_items_dropped_lifetime
Definition items.qh:10
string GetField_fullspawndata(entity e, string fieldname, bool vfspath)
Retrieves the value of a map entity field from fullspawndata.
Definition main.qc:451
float autocvar_sys_ticrate
Definition main.qh:17
@ MUT_ITEMTOUCH_PICKUP
Definition events.qh:736
@ MUT_ITEMTOUCH_RETURN
Definition events.qh:735
void W_GiveWeapon(entity e, int wep)
Definition common.qc:33
const int CH_TRIGGER
Definition sound.qh:12
const int CH_TRIGGER_SINGLE
Definition sound.qh:13
#define Sound_fixpath(this)
Definition sound.qh:141
const float VOL_BASE
Definition sound.qh:36
#define _sound(e, c, s, v, a)
Definition sound.qh:43
const float ATTEN_NORM
Definition sound.qh:30
#define sound(e, c, s, v, a)
Definition sound.qh:52
void soundto(int _dest, entity e, int chan, string samp, float vol, float _atten, float _pitch)
Definition all.qc:74
#define SND(id)
Definition all.qh:35
#define CS_CVAR(this)
Definition state.qh:51
void StatusEffects_remove(StatusEffect this, entity actor, int removal_type)
float StatusEffects_gettime(StatusEffect this, entity actor)
bool StatusEffects_active(StatusEffect this, entity actor)
void StatusEffects_apply(StatusEffect this, entity actor, float eff_time, int eff_flags)
void StatusEffects_update(entity e)
const int DAMAGE_YES
Definition subs.qh:80
vector pos1
Definition subs.qh:50
float takedamage
Definition subs.qh:78
float buff_Available(entity buff)
Definition sv_buffs.qc:254
void buff_RemoveAll(entity actor, int removal_type)
Definition sv_buffs.qc:282
void powerups_DropItem_Think(entity this)
bool autocvar_g_powerups_stack
void GiveResource(entity receiver, Resource res_type, float amount)
Gives an entity some resource.
float GetResourceLimit(entity e, Resource res_type)
Returns the maximum amount of the given resource.
void GiveResourceWithLimit(entity receiver, Resource res_type, float amount, float limit)
Gives an entity some resource but not more than a limit.
float autocvar_g_balance_pause_fuel_regen
float autocvar_g_balance_pause_armor_rot
float autocvar_g_balance_pause_health_rot
float autocvar_g_balance_pause_health_regen
float autocvar_g_balance_pause_fuel_rot
float ammo
Definition sv_turrets.qh:43
#define IT_KEY1
Definition sys-pre.qh:20
#define IT_KEY2
Definition sys-pre.qh:21
void TeamBalance_Destroy(entity balance)
Destroy the team balance entity.
Definition teamplay.qc:599
int TeamBalance_GetNumberOfPlayers(entity balance, int index)
Returns the number of players (both humans and bots) in a team.
Definition teamplay.qc:927
void TeamBalance_GetTeamCounts(entity balance, entity ignore)
Counts the number of players and various other information about each team.
Definition teamplay.qc:846
entity TeamBalance_CheckAllowedTeams(entity for_whom)
Checks whether the player can join teams according to global configuration and mutator settings.
Definition teamplay.qc:459
bool TeamBalance_IsTeamAllowed(entity balance, int index)
Returns whether the team change to the specified team is allowed.
Definition teamplay.qc:826
const int NUM_TEAMS
Number of teams in the game.
Definition teams.qh:3
string targetname
Definition triggers.qh:56
string target
Definition triggers.qh:55
#define IS_SPEC(v)
Definition utils.qh:10
#define IS_REAL_CLIENT(v)
Definition utils.qh:17
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:52
void WaypointSprite_Kill(entity wp)
void WaypointSprite_Ping(entity e)
entity WaypointSprite_Spawn(entity spr, float _lifetime, float maxdistance, entity ref, vector ofs, entity showto, float t, entity own,.entity ownfield, float hideable, entity icon)
void WaypointSprite_UpdateBuildFinished(entity e, float f)
void WaypointSprite_UpdateRule(entity e, float t, float r)
entity waypointsprite_attached
const int SPRITERULE_SPECTATOR
entity GetAmmoItem(Resource ammotype)
Definition all.qc:189
WepSet WEPSET_SUPERWEAPONS
Definition all.qh:329
#define WepSet_FromWeapon(it)
Definition all.qh:46
const int MAX_WEAPONSLOTS
Definition weapon.qh:16
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17
const int WEP_FLAG_MUTATORBLOCKED
Definition weapon.qh:219
vector WepSet
Definition weapon.qh:14
const int WEP_FLAG_HIDDEN
Definition weapon.qh:216
void W_DropEvent(.void(Weapon, entity actor,.entity) event, entity player, int weapon_type, entity weapon_item,.entity weaponentity)
void DropToFloor_QC_DelayedInit(entity this)
Definition world.qc:2423
void InitializeEntity(entity e, void(entity this) func, int order)
Definition world.qc:2225
float g_weaponarena
Definition world.qh:75
float g_weapon_stay
Definition world.qh:109