Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
sv_nades.qc
Go to the documentation of this file.
1#include "sv_nades.qh"
2
8
10
12
13vector nades_PlayerColor(entity this, bool isPants)
14{
15 if(teamplay)
16 return Team_ColorRGB(this.team);
17
18 // logic copied from Scoreboard_GetName
19 int col = (this.colormap >= 1024) ? this.colormap - 1024 : this.clientcolors;
20 return (isPants) ? colormapPaletteColor(col % 16, true) : colormapPaletteColor(floor(col / 16), false);
21}
22
24{
25 this.skin = 8 - (this.wait - time) / (this.nade_lifetime / 10);
26 this.nextthink = time;
27 if(!this.owner || wasfreed(this.owner))
28 delete(this);
29}
30
32{
33 CSQCProjectile(_nade, true, REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, _nade)).m_projectile[1], true);
34}
35
36void nade_spawn(entity _nade)
37{
38 entity timer = new(nade_timer);
39 setmodel(timer, MDL_NADE_TIMER);
40 setattachment(timer, _nade, "");
41 timer.colormap = _nade.colormap;
42 timer.glowmod = _nade.glowmod;
44 timer.nextthink = time;
45 timer.wait = _nade.wait;
46 timer.nade_lifetime = _nade.nade_lifetime;
47 timer.owner = _nade;
48 timer.skin = 10;
49
50 _nade.effects |= EF_LOWPRECISION;
51
52 CSQCProjectile(_nade, true, REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, _nade)).m_projectile[0], true);
53}
54
55
57{
58 if(time >= this.ltime)
59 {
60 delete(this);
61 return;
62 }
63
64 this.nextthink = time;
65
66 if(time >= this.nade_special_time)
67 {
68 this.nade_special_time = time+0.25;
69 this.nade_show_particles = 1;
70 }
71 else
72 this.nade_show_particles = 0;
73}
74
75entity nades_spawn_orb(entity own, entity realown, vector org, float orb_ltime, float orb_rad)
76{
77 // NOTE: this function merely places an orb
78 // you must add a custom touch function to the returned entity if desired
79 // also set .colormod if you wish to have it colorized
80 entity orb = new(nades_spawn_orb);
81 orb.owner = own;
82 orb.realowner = realown;
83 setorigin(orb, org);
84
85 orb.orb_lifetime = orb_ltime; // required for timers
86 orb.ltime = time + orb.orb_lifetime;
87 orb.bot_dodge = false;
88 orb.team = realown.team;
89 orb.solid = SOLID_TRIGGER;
90
91 setmodel(orb, MDL_NADE_ORB);
92 orb.skin = 1;
93 orb.orb_radius = orb_rad; // required for fading
94 vector size = '.5 .5 .5' * orb.orb_radius;
95 setsize(orb, -size, size);
96
97 Net_LinkEntity(orb, true, 0, orb_send);
98 orb.SendFlags |= 1;
99
101 orb.nextthink = time;
102
103 return orb;
104}
105
106
108{
109 entity expef = NULL;
110 vector expcol_min = '0 0 0', expcol_max = '0 0 0';
111
112 Nade ntype = REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, this));
113
114 if (!this.takedamage || ntype == NADE_TYPE_Null)
115 {
116 // first condition: nade was destroyed by something (lava, void, etc.), just do a normal explosion
117 // this prevents weird cases like spawn nade setting your spawnpoint on the void, translocate sending you into the void, etc.
118 ntype = NADE_TYPE_NORMAL;
119 }
120
121#define SET_NADE_EFFECT(nade_type, exp_effect, exp_color_min, exp_color_max) \
122 case nade_type: \
123 expef = exp_effect; \
124 expcol_min = exp_color_min; \
125 expcol_max = exp_color_max; \
126 break
127
128 switch (ntype)
129 {
130 SET_NADE_EFFECT(NADE_TYPE_NAPALM, EFFECT_EXPLOSION_MEDIUM, '0 0 0', '0 0 0');
131 SET_NADE_EFFECT(NADE_TYPE_ICE, EFFECT_ELECTRO_COMBO, '0 0 0', '0 0 0');
132 SET_NADE_EFFECT(NADE_TYPE_TRANSLOCATE, NULL, '0 0 0', '0 0 0');
133 SET_NADE_EFFECT(NADE_TYPE_MONSTER, NULL, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true));
134 SET_NADE_EFFECT(NADE_TYPE_SPAWN, EFFECT_SPAWN, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true));
135 SET_NADE_EFFECT(NADE_TYPE_HEAL, EFFECT_SPAWN, '1 0 0', '1 0 0');
136 SET_NADE_EFFECT(NADE_TYPE_ENTRAP, EFFECT_SPAWN, '1 1 0', '1 1 0');
137 SET_NADE_EFFECT(NADE_TYPE_VEIL, EFFECT_SPAWN, '0 0 0', '0 0 0');
138 SET_NADE_EFFECT(NADE_TYPE_AMMO, EFFECT_SPAWN, '0.33 0.33 1', '0.33 0.33 1');
139 SET_NADE_EFFECT(NADE_TYPE_DARKNESS, EFFECT_EXPLOSION_MEDIUM, '0 0 0', '0 0 0');
140 SET_NADE_EFFECT(NADE_TYPE_NORMAL, EFFECT_NADE_EXPLODE, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true));
141 }
142#undef SET_NADE_EFFECT
143
144 if (expef)
145 Send_Effect_Except(expef, findbetterlocation(this.origin, 8), '0 0 0', 1, expcol_min, expcol_max, NULL);
146
147 sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
148 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
149
150 this.event_damage = func_null; // prevent somehow calling damage in the next call
151
152 switch (ntype)
153 {
154 case NADE_TYPE_NORMAL: nade_normal_boom(this); break;
155 case NADE_TYPE_NAPALM: nade_napalm_boom(this); break;
156 case NADE_TYPE_ICE: nade_ice_boom(this); break;
157 case NADE_TYPE_TRANSLOCATE: nade_translocate_boom(this); break;
158 case NADE_TYPE_SPAWN: nade_spawn_boom(this); break;
159 case NADE_TYPE_HEAL: nade_heal_boom(this); break;
160 case NADE_TYPE_MONSTER: nade_monster_boom(this); break;
161 case NADE_TYPE_ENTRAP: nade_entrap_boom(this); break;
162 case NADE_TYPE_VEIL: nade_veil_boom(this); break;
163 case NADE_TYPE_AMMO: nade_ammo_boom(this); break;
164 case NADE_TYPE_DARKNESS: nade_darkness_boom(this); break;
165 }
166
167 IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
168 {
169 RemoveHook(it);
170 });
171
172 delete(this);
173}
174
175void spawn_held_nade(entity player, entity nowner, float ntime, string ntype, string pntype);
176void nade_pickup(entity this, entity thenade)
177{
178 spawn_held_nade(this, thenade.realowner, autocvar_g_nades_pickup_time, REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, thenade)).netname, thenade.pokenade_type);
179
180 // set refire so player can't even
182 STAT(NADE_TIMER, this) = 0;
183
184 if(this.nade)
185 this.nade.nade_time_primed = thenade.nade_time_primed;
186}
187
188bool CanThrowNade(entity this);
190{
191 if(toucher)
193
194 if(toucher == this.realowner)
195 return; // no this impacts
196
198 if(time >= this.spawnshieldtime)
199 if(!toucher.nade && GetResource(this, RES_HEALTH) == this.max_health) // no boosted shot pickups, thank you very much
200 if(CanThrowNade(toucher)) // prevent some obvious things, like dead players
201 if(IS_REAL_CLIENT(toucher)) // above checks for IS_PLAYER, don't need to do it here
202 {
203 nade_pickup(toucher, this);
204 sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
205 delete(this);
206 return;
207 }
208 /*float is_weapclip = 0;
209 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NODRAW)
210 if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NONSOLID))
211 if (!(trace_dphitcontents & DPCONTENTS_OPAQUE))
212 is_weapclip = 1;*/
213 if(ITEM_TOUCH_NEEDKILL()) // || is_weapclip)
214 {
215 IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
216 {
217 RemoveHook(it);
218 });
219 delete(this);
220 return;
221 }
222
224
225 //setsize(this, '-2 -2 -2', '2 2 2');
226 //UpdateCSQCProjectile(this);
227 if(GetResource(this, RES_HEALTH) == this.max_health)
228 {
230 return;
231 }
232
233 this.enemy = toucher;
234 nade_boom(this);
235}
236
238{
239 sound(this, CH_SHOTS_SINGLE, SND_NADE_BEEP, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
240 setthink(this, nade_boom);
241 this.nextthink = max(this.wait, time);
242}
243
244void nade_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
245{
246 if(ITEM_DAMAGE_NEEDKILL(deathtype))
247 {
248 this.takedamage = DAMAGE_NO;
249 W_PrepareExplosionByDamage(this, attacker, nade_boom);
250 return;
251 }
252
253 if(STAT(NADE_BONUS_TYPE, this) == NADE_TYPE_TRANSLOCATE.m_id || STAT(NADE_BONUS_TYPE, this) == NADE_TYPE_SPAWN.m_id)
254 return;
255
256 if (MUTATOR_CALLHOOK(Nade_Damage, this, DEATH_WEAPONOF(deathtype), force, damage)) {}
257 else if(DEATH_ISWEAPON(deathtype, WEP_BLASTER))
258 {
259 force *= 1.5;
260 damage = 0;
261 }
262 else if(DEATH_ISWEAPON(deathtype, WEP_VORTEX) || DEATH_ISWEAPON(deathtype, WEP_VAPORIZER) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_NEX))
263 {
264 force *= 6;
265 damage = this.max_health * 0.55;
266 }
267 else if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_MACHINEGUN))
268 damage = this.max_health * 0.1;
269 else if(DEATH_ISWEAPON(deathtype, WEP_SHOTGUN) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_SHOTGUN)) // WEAPONTODO
270 {
271 if(!(deathtype & HITTYPE_SECONDARY))
272 damage = this.max_health * 1.15;
273 }
274
275 // melee slaps
276 entity death_weapon = DEATH_WEAPONOF(deathtype);
277 if(((deathtype & HITTYPE_SECONDARY) ? (death_weapon.spawnflags & WEP_TYPE_MELEE_SEC) : (death_weapon.spawnflags & WEP_TYPE_MELEE_PRI)))
278 {
279 damage = this.max_health * 0.1;
280 force *= 10;
281 }
282
283 this.velocity += force;
285
286 if(damage <= 0 || ((IS_ONGROUND(this)) && IS_PLAYER(attacker)))
287 return;
288
289 float hp = GetResource(this, RES_HEALTH);
290 if(hp == this.max_health)
291 {
292 sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
293 this.nextthink = max(time + this.nade_lifetime, time);
294 setthink(this, nade_beep);
295 }
296
297 hp -= damage;
298 SetResource(this, RES_HEALTH, hp);
299
300 if(STAT(NADE_BONUS_TYPE, this) != NADE_TYPE_TRANSLOCATE.m_id && STAT(NADE_BONUS_TYPE, this) != NADE_TYPE_SPAWN.m_id)
301 if(STAT(NADE_BONUS_TYPE, this) != NADE_TYPE_HEAL.m_id || IS_PLAYER(attacker))
302 this.realowner = attacker;
303
304 if(hp <= 0)
305 {
306 if(nade_spawn_DestroyDamage(this, attacker))
307 return;
308 if(nade_translocate_DestroyDamage(this, attacker))
309 return;
310
311 W_PrepareExplosionByDamage(this, attacker, nade_boom);
312 }
313 else
314 nade_burn_spawn(this);
315}
316
317void toss_nade(entity e, bool set_owner, vector _velocity, float _time)
318{
319 if(e.nade == NULL)
320 return;
321
322 entity _nade = e.nade;
323 e.nade = NULL;
324
325 if(e.fake_nade)
326 delete(e.fake_nade);
327 e.fake_nade = NULL;
328
329 Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER, CPID_NADES);
330
331 makevectors(e.v_angle);
332
333 // NOTE: always throw from first weapon entity?
334 W_SetupShot(e, _nade.weaponentity_fld, false, false, SND_Null, CH_WEAPON_A, 0, DEATH_NADE.m_id);
335
339
340 setorigin(_nade, w_shotorg + offset);
341 //setmodel(_nade, MDL_PROJECTILE_NADE);
342 //setattachment(_nade, NULL, "");
344 if(STAT(NADES_SMALL, e))
345 setsize(_nade, '-8 -8 -8', '8 8 8');
346 else
347 setsize(_nade, '-16 -16 -16', '16 16 16');
349
350 tracebox(_nade.origin, _nade.mins, _nade.maxs, _nade.origin, MOVE_NOMONSTERS, _nade);
352 setorigin(_nade, e.origin);
353
354 if(e.v_angle.x >= 70 && e.v_angle.x <= 110 && PHYS_INPUT_BUTTON_CROUCH(e))
355 _nade.velocity = '0 0 100';
357 _nade.velocity = e.velocity + _velocity;
359 _nade.velocity = _velocity;
360 else
361 _nade.velocity = W_CalculateProjectileVelocity(e, e.velocity, _velocity, true);
362
363 if(set_owner)
364 _nade.realowner = e;
365
366 settouch(_nade, nade_touch);
367 _nade.spawnshieldtime = time + 0.1; // prevent instantly picking up again
368 SetResource(_nade, RES_HEALTH, autocvar_g_nades_nade_health);
369 _nade.max_health = GetResource(_nade, RES_HEALTH);
370 _nade.takedamage = DAMAGE_AIM;
371 _nade.event_damage = nade_damage;
372 setcefc(_nade, func_null);
373 _nade.exteriormodeltoclient = NULL;
374 _nade.traileffectnum = 0;
375 _nade.teleportable = true;
376 _nade.pushable = true;
377 _nade.gravity = 1;
378 _nade.missile_flags = MIF_SPLASH | MIF_ARC;
379 _nade.damagedbycontents = true;
381 _nade.angles = vectoangles(_nade.velocity);
382 _nade.flags = FL_PROJECTILE;
383 IL_PUSH(g_projectiles, _nade);
384 IL_PUSH(g_bot_dodge, _nade);
385 _nade.projectiledeathtype = DEATH_NADE.m_id;
386 _nade.toss_time = time;
387 _nade.solid = SOLID_CORPSE; //((STAT(NADE_BONUS_TYPE, _nade) == NADE_TYPE_TRANSLOCATE) ? SOLID_CORPSE : SOLID_BBOX);
388
389 if(STAT(NADE_BONUS_TYPE, _nade) == NADE_TYPE_TRANSLOCATE.m_id
390 || STAT(NADE_BONUS_TYPE, _nade) == NADE_TYPE_SPAWN.m_id
391 || STAT(NADE_BONUS_TYPE, _nade) == NADE_TYPE_MONSTER.m_id)
392 _nade.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
393 else
394 _nade.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY;
395
396 nade_spawn(_nade);
397
398 if(_time)
399 {
400 setthink(_nade, nade_boom);
401 _nade.nextthink = _time;
402 }
403
404 e.nade_refire = time + autocvar_g_nades_nade_refire;
405 STAT(NADE_TIMER, e) = 0;
406}
407
409{
410#define NADE_TYPE_CHECK(nade_ent, nade_cvar) \
411 case nade_ent.m_id: \
412 if (nade_cvar) \
413 return ntype; \
414 break
415
416 switch (ntype.m_id)
417 {
418 case 0: return NADE_TYPE_Null; // use NADE_TYPE_Null to signify a random nade
419 NADE_TYPE_CHECK(NADE_TYPE_NAPALM, autocvar_g_nades_napalm);
421 NADE_TYPE_CHECK(NADE_TYPE_TRANSLOCATE, autocvar_g_nades_translocate);
422 NADE_TYPE_CHECK(NADE_TYPE_SPAWN, autocvar_g_nades_spawn);
423 NADE_TYPE_CHECK(NADE_TYPE_HEAL, autocvar_g_nades_heal);
424 NADE_TYPE_CHECK(NADE_TYPE_MONSTER, autocvar_g_nades_pokenade && autocvar_g_monsters); // if monsters disabled, this nade can't do anything, use instead normal nade
425 NADE_TYPE_CHECK(NADE_TYPE_ENTRAP, autocvar_g_nades_entrap);
426 NADE_TYPE_CHECK(NADE_TYPE_VEIL, autocvar_g_nades_veil);
427 NADE_TYPE_CHECK(NADE_TYPE_AMMO, autocvar_g_nades_ammo);
428 NADE_TYPE_CHECK(NADE_TYPE_DARKNESS, autocvar_g_nades_darkness);
429 }
430 return NADE_TYPE_NORMAL; // default to NADE_TYPE_NORMAL for unknown nade types
431#undef NADE_TYPE_CHECK
432}
433
434void nades_GiveBonus(entity player, float score)
435{
438 if (IS_REAL_CLIENT(player))
439 if (IS_PLAYER(player) && STAT(NADE_BONUS, player) < autocvar_g_nades_bonus_max)
440 if (!STAT(FROZEN, player))
441 if (!IS_DEAD(player))
442 {
443 if ( STAT(NADE_BONUS_SCORE, player) < 1 )
444 STAT(NADE_BONUS_SCORE, player) += score/autocvar_g_nades_bonus_score_max;
445
446 if ( STAT(NADE_BONUS_SCORE, player) >= 1 )
447 {
448 Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_NADE_BONUS);
449 play2(player, SND(NADE_BONUS));
450 STAT(NADE_BONUS, player)++;
451 STAT(NADE_BONUS_SCORE, player) -= 1;
452 }
453 }
454}
455
458{
459 STAT(NADE_BONUS, player) = STAT(NADE_BONUS_SCORE, player) = 0;
460}
461
463{
464 entity player = M_ARGV(0, entity);
465
466 nades_RemoveBonus(player);
467}
468
469bool nade_customize(entity this, entity client)
470{
471 //if(IS_SPEC(client)) { return false; }
472 if(client == this.exteriormodeltoclient || (IS_SPEC(client) && client.enemy == this.exteriormodeltoclient))
473 {
474 // somewhat hide the model, but keep the glow
475 //this.effects = 0;
476 if(this.traileffectnum)
477 this.traileffectnum = 0;
478 this.alpha = -1;
479 }
480 else
481 {
482 //this.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
483 if(!this.traileffectnum)
484 {
485 entity nade = REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, this));
486 this.traileffectnum = _particleeffectnum(Nade_TrailEffect(nade.m_projectile[0], this.team).eent_eff_name);
487 }
488 this.alpha = 1;
489 }
490
491 return true;
492}
493
495{
497 FOREACH(Nades, it != NADE_TYPE_Null, {
498 if (nades_CheckTypes(it) == it) // this nade type is allowed
499 RandomSelection_AddEnt(it, 1, 1);
500 });
501 return RandomSelection_chosen_ent.m_id;
502}
503
505{
506 FOREACH(Nades, it != NADE_TYPE_Null && (it.netname == ntype || ftos(it.impulse) == ntype),
507 {
508 return it;
509 });
510 return NADE_TYPE_Null;
511}
512
513Nade Nades_GetType(string ntype)
514{
515 Nade def = Nades_FromString(ntype);
516 if(ntype == "random" || ntype == "0")
517 def = REGISTRY_GET(Nades, nade_choose_random());
518
519 return (def == NADE_TYPE_Null) ? NADE_TYPE_NORMAL : def;
520}
521
522void spawn_held_nade(entity player, entity nowner, float ntime, string ntype, string pntype)
523{
524 entity n = new(nade), fn = new(fake_nade);
525
526 Nade def = Nades_GetType(ntype);
527
528 n.pokenade_type = pntype;
529
530 STAT(NADE_BONUS_TYPE, n) = def.m_id;
531
532 .entity weaponentity = weaponentities[0]; // TODO: unhardcode
533
534 setmodel(n, MDL_PROJECTILE_NADE);
535 //setattachment(n, player, "bip01 l hand");
536 n.exteriormodeltoclient = player;
538 n.traileffectnum = _particleeffectnum(Nade_TrailEffect(def.m_projectile[0], player.team).eent_eff_name);
539 n.colormod = def.m_color;
540 n.realowner = nowner;
541 n.colormap = player.colormap;
542 n.glowmod = player.glowmod;
543 n.wait = time + max(0, ntime);
544 n.nade_time_primed = time;
546 n.nextthink = max(n.wait - 3, time);
547 n.projectiledeathtype = DEATH_NADE.m_id;
548 n.weaponentity_fld = weaponentity;
549 n.nade_lifetime = ntime;
550 n.alpha = def.m_alpha;
551
552 setmodel(fn, MDL_NADE_VIEW);
553 //setattachment(fn, player.(weaponentity), "");
554 fn.viewmodelforclient = player;
555 fn.realowner = fn.owner = player;
556 fn.colormod = def.m_color;
557 fn.colormap = player.colormap;
558 fn.glowmod = player.glowmod;
559 setthink(fn, SUB_Remove);
560 fn.nextthink = n.wait;
561 fn.weaponentity_fld = weaponentity;
562 fn.alpha = def.m_alpha;
563
564 player.nade = n;
565 player.fake_nade = fn;
566}
567
569{
570 if(autocvar_g_nades_bonus_only && !STAT(NADE_BONUS, this))
571 return; // only allow bonus nades
572
573 // TODO: handle old nade if it exists?
574 if(this.nade)
575 delete(this.nade);
576 this.nade = NULL;
577
578 if(this.fake_nade)
579 delete(this.fake_nade);
580 this.fake_nade = NULL;
581
582 Nade ntype;
583 string pntype = this.pokenade_type;
584
585 if(StatusEffects_active(STATUSEFFECT_Strength, this) && autocvar_g_nades_bonus_onstrength)
586 ntype = REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, this));
587 else if (STAT(NADE_BONUS, this) >= 1)
588 {
589 ntype = REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, this));
590 pntype = this.pokenade_type;
591 STAT(NADE_BONUS, this) -= 1;
592 }
593 else
594 {
596 {
598 pntype = CS_CVAR(this).cvar_cl_pokenade_type;
599 }
600 else
601 {
604 }
605 }
606
607 spawn_held_nade(this, this, autocvar_g_nades_nade_lifetime, ntype.netname, pntype);
608}
609
611{
612 return !(this.vehicle || !autocvar_g_nades || IS_DEAD(this) || !IS_PLAYER(this) || weaponLocked(this));
613}
614
616
618{
619 if(!CanThrowNade(this))
620 return;
621
622 entity held_nade = this.nade;
623 if (!held_nade)
624 {
625 this.nade_altbutton = true;
626 if(time > this.nade_refire)
627 {
628 nade_prime(this);
630 }
631 }
632 else
633 {
634 this.nade_altbutton = false;
635 if (time >= held_nade.nade_time_primed + 1) {
636 makevectors(this.v_angle);
637 float _force = time - held_nade.nade_time_primed;
640 vector dir = (v_forward * 0.75 + v_up * 0.2 + v_right * 0.05);
642 toss_nade(this, true, dir * _force, 0);
643 }
644 }
645}
646
647void nades_Clear(entity player)
648{
649 if(player.nade)
650 delete(player.nade);
651 if(player.fake_nade)
652 delete(player.fake_nade);
653
654 player.nade = player.fake_nade = NULL;
655 STAT(NADE_TIMER, player) = 0;
656}
657
658MUTATOR_HOOKFUNCTION(nades, VehicleEnter)
659{
660 entity player = M_ARGV(0, entity);
661
662 if(player.nade)
663 toss_nade(player, true, '0 0 100', max(player.nade.wait, time + 0.05));
664}
665
667 METHOD(NadeOffhand, offhand_think, void(NadeOffhand this, entity player, bool key_pressed))
668 {
669 entity held_nade = player.nade;
670
671 if (!CanThrowNade(player)) return;
672 if (!(time > player.nade_refire)) return;
673 if (key_pressed) {
674 if (!held_nade) {
675 nade_prime(player);
676 held_nade = player.nade;
677 }
678 } else if (time >= held_nade.nade_time_primed + 1) {
679 if (held_nade) {
680 makevectors(player.v_angle);
681 float _force = time - held_nade.nade_time_primed;
682 _force /= autocvar_g_nades_nade_lifetime;
683 _force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce));
684 vector dir = (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1);
685 dir = W_CalculateSpread(dir, autocvar_g_nades_spread, autocvar_g_projectiles_spread_style, false);
686 toss_nade(player, false, dir * _force, 0);
687 }
688 }
689 }
693{
695 {
697 }
698 return 0;
699}
700
701MUTATOR_HOOKFUNCTION(nades, ForbidThrowCurrentWeapon, CBC_ORDER_LAST)
702{
703 entity player = M_ARGV(0, entity);
704
705 if (player.offhand != OFFHAND_NADE || (STAT(WEAPONS, player) & WEPSET(HOOK)) || autocvar_g_nades_override_dropweapon) {
706 nades_CheckThrow(player);
707 return true;
708 }
709}
710
712{
713 entity player = M_ARGV(0, entity);
714
715 if (!IS_PLAYER(player)) { return; }
716
717 if (player.nade && (player.offhand != OFFHAND_NADE || (STAT(WEAPONS, player) & WEPSET(HOOK))))
718 OFFHAND_NADE.offhand_think(OFFHAND_NADE, player, player.nade_altbutton);
719
720 entity held_nade = player.nade;
721 if (held_nade)
722 {
723 STAT(NADE_TIMER, player) = bound(0, (time - held_nade.nade_time_primed) / held_nade.nade_lifetime, 1);
724 // LOG_TRACEF("%d %d", STAT(NADE_TIMER, player), time - held_nade.nade_time_primed);
725 makevectors(player.angles);
726 held_nade.velocity = player.velocity;
727 setorigin(held_nade, player.origin + player.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
728 held_nade.angles_y = player.angles.y;
729
730 if (time + 0.1 >= held_nade.wait)
731 {
732 toss_nade(player, false, '0 0 0', time + 0.05);
733 Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_NADE_THROW);
734 }
735 }
736
737 if(IS_PLAYER(player))
738 {
740 {
741 entity key;
742 float key_count = 0;
743 FOR_EACH_KH_KEY(key) if(key.owner == player) { ++key_count; }
744
745 float time_score;
746 if(GameRules_scoring_is_vip(player))
748 else
750
751 if(key_count)
752 time_score = autocvar_g_nades_bonus_score_time_flagcarrier * key_count; // multiply by the number of keys the player is holding
753
755 {
756 STAT(NADE_BONUS_TYPE, player) = nades_CheckTypes(Nades_FromString(CS_CVAR(player).cvar_cl_nade_type)).m_id;
757 player.pokenade_type = CS_CVAR(player).cvar_cl_pokenade_type;
758 }
759 else
760 {
761 STAT(NADE_BONUS_TYPE, player) = Nades_FromString(autocvar_g_nades_bonus_type).m_id;
762 player.pokenade_type = autocvar_g_nades_pokenade_monster_type;
763 }
764
765 if(STAT(NADE_BONUS_SCORE, player) >= 0 && autocvar_g_nades_bonus_score_max)
767 }
768 else
769 {
770 STAT(NADE_BONUS, player) = STAT(NADE_BONUS_SCORE, player) = 0;
771 }
772
773 nade_veil_Apply(player);
774 }
775}
776
777MUTATOR_HOOKFUNCTION(nades, PlayerSpawn)
778{
779 entity player = M_ARGV(0, entity);
780
781 if (StatusEffects_active(STATUSEFFECT_SpawnShield, player))
782 player.nade_refire = StatusEffects_gettime(STATUSEFFECT_SpawnShield, player);
783 else
784 player.nade_refire = time;
785
787 player.nade_refire += autocvar_g_nades_nade_refire;
788
790 STAT(NADE_BONUS_TYPE, player) = Nades_FromString(CS_CVAR(player).cvar_cl_nade_type).m_id;
791
792 STAT(NADE_TIMER, player) = 0;
793
794 if (!player.offhand) player.offhand = OFFHAND_NADE;
795
796 if(player.nade_spawnloc)
797 {
798 setorigin(player, player.nade_spawnloc.origin);
799 player.nade_spawnloc.cnt -= 1;
800
801 if(player.nade_spawnloc.cnt <= 0)
802 {
803 delete(player.nade_spawnloc);
804 player.nade_spawnloc = NULL;
805 }
806
808 }
809}
810
812{
813 entity frag_attacker = M_ARGV(1, entity);
815
816 if(frag_target.nade)
818 toss_nade(frag_target, true, '0 0 100', max(frag_target.nade.wait, time + 0.05));
819
820 if(IS_PLAYER(frag_attacker))
821 {
822 float killcount_bonus = ((CS(frag_attacker).killcount >= 1) ? bound(0, autocvar_g_nades_bonus_score_minor * CS(frag_attacker).killcount, autocvar_g_nades_bonus_score_medium)
824 if (SAME_TEAM(frag_attacker, frag_target) || frag_attacker == frag_target)
825 nades_RemoveBonus(frag_attacker);
828 else if(autocvar_g_nades_bonus_score_spree && CS(frag_attacker).killcount > 1)
829 {
830 #define SPREE_ITEM(counta,countb,center,normal,gentle) \
831 case counta: { nades_GiveBonus(frag_attacker, autocvar_g_nades_bonus_score_spree); break; }
832 switch(CS(frag_attacker).killcount)
833 {
835 default: nades_GiveBonus(frag_attacker, autocvar_g_nades_bonus_score_minor); break;
836 }
837 #undef SPREE_ITEM
838 }
839 else
840 nades_GiveBonus(frag_attacker, killcount_bonus);
841 }
842
844}
845
846MUTATOR_HOOKFUNCTION(nades, Damage_Calculate)
847{
848 entity frag_inflictor = M_ARGV(0, entity);
849 entity frag_attacker = M_ARGV(1, entity);
851 float frag_deathtype = M_ARGV(3, float);
852
853 if(autocvar_g_freezetag_revive_nade && STAT(FROZEN, frag_target) && frag_attacker == frag_target && frag_deathtype == DEATH_NADE.m_id)
854 if(time - frag_inflictor.toss_time <= 0.1)
855 {
858 Send_Effect(EFFECT_ICEORGLASS, frag_target.origin, '0 0 0', 3);
859 M_ARGV(4, float) = 0;
860 M_ARGV(6, vector) = '0 0 0';
861 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED_NADE, frag_target.netname);
862 Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_FREEZETAG_REVIVE_SELF);
863 }
864}
865
866MUTATOR_HOOKFUNCTION(nades, MonsterDies)
867{
869 entity frag_attacker = M_ARGV(1, entity);
870
871 if(IS_PLAYER(frag_attacker))
872 if(DIFF_TEAM(frag_attacker, frag_target))
873 if(!(frag_target.spawnflags & MONSTERFLAG_SPAWNED))
875}
876
877MUTATOR_HOOKFUNCTION(nades, DropSpecialItems)
878{
880
881 if(frag_target.nade)
882 toss_nade(frag_target, true, '0 0 0', time + 0.05);
883}
884
886{
887 nades_Clear(this);
888 nades_RemoveBonus(this);
889}
890
891MUTATOR_HOOKFUNCTION(nades, MakePlayerObserver) { entity player = M_ARGV(0, entity); nades_RemovePlayer(player); }
893MUTATOR_HOOKFUNCTION(nades, reset_map_global)
894{
896 {
898 });
899}
900
902{
903 entity spectatee = M_ARGV(0, entity);
904 entity client = M_ARGV(1, entity);
905
906 STAT(NADE_TIMER, client) = STAT(NADE_TIMER, spectatee);
907 STAT(NADE_BONUS_TYPE, client) = STAT(NADE_BONUS_TYPE, spectatee);
908 client.pokenade_type = spectatee.pokenade_type;
909 STAT(NADE_BONUS, client) = STAT(NADE_BONUS, spectatee);
910 STAT(NADE_BONUS_SCORE, client) = STAT(NADE_BONUS_SCORE, spectatee);
911}
912
913MUTATOR_HOOKFUNCTION(nades, BuildMutatorsPrettyString)
914{
915 M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Nades");
916}
917
918MUTATOR_HOOKFUNCTION(nades, BuildMutatorsString)
919{
920 M_ARGV(0, string) = strcat(M_ARGV(0, string), ":Nades");
921}
IntrusiveList g_bot_dodge
Definition api.qh:150
#define MUTATOR_ONADD
Definition base.qh:309
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
#define REGISTER_MUTATOR(...)
Definition base.qh:295
const int CBC_ORDER_LAST
Definition base.qh:11
#define MUTATOR_HOOKFUNCTION(...)
Definition base.qh:335
vector W_CalculateSpread(vector dir, float spread, int spread_style, bool must_normalize)
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float max_health
void SetResource(entity e, Resource res_type, float amount)
Sets the current amount of resource the given entity will have.
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
virtual void offhand_think()
Definition sv_nades.qc:667
Definition nades.qh:14
string netname
Definition nades.qh:20
float m_alpha
Definition nades.qh:19
vector m_color
Definition nades.qh:16
int m_id
Definition nades.qh:15
int m_projectile[2]
Definition nades.qh:22
string netname
Definition powerups.qc:20
float alpha
Definition items.qc:13
float wait
Definition items.qc:17
entity owner
Definition main.qh:87
int team
Definition main.qh:188
#define colormapPaletteColor(c, isPants)
Definition color.qh:5
#define setmodel(this, m)
Definition model.qh:26
#define M_ARGV(x, type)
Definition events.qh:17
void nade_ammo_boom(entity this)
Definition ammo.qc:67
bool autocvar_g_nades_ammo
Definition ammo.qh:6
#define PHYS_INPUT_BUTTON_CROUCH(s)
Definition player.qh:154
#define IS_DEAD(s)
Definition player.qh:245
vector v_angle
Definition player.qh:237
#define IS_PLAYER(s)
Definition player.qh:243
vector findbetterlocation(vector org, float mindist)
Definition util.qc:117
const int FL_PROJECTILE
Definition constants.qh:85
vector v_up
const float MOVE_NOMONSTERS
float DPCONTENTS_BOTCLIP
const float SOLID_TRIGGER
float DPCONTENTS_SOLID
const float SOLID_CORPSE
vector velocity
float DPCONTENTS_BODY
float DPCONTENTS_PLAYERCLIP
float skin
float time
vector v_right
float trace_startsolid
vector size
float nextthink
float colormap
vector v_forward
vector origin
void UpdateCSQCProjectile(entity e)
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
IntrusiveList g_damagedbycontents
Definition damage.qh:135
float spawnshieldtime
Definition damage.qh:61
void nade_darkness_boom(entity this)
Definition darkness.qc:71
bool autocvar_g_nades_darkness
Definition darkness.qh:6
#define DEATH_ISWEAPON(t, w)
Definition all.qh:46
#define DEATH_WEAPONOF(t)
Definition all.qh:45
const int HITTYPE_SECONDARY
Definition all.qh:29
void SUB_Remove(entity this)
Remove entity.
Definition defer.qh:13
float traileffectnum
float EF_LOWPRECISION
entity exteriormodeltoclient
#define nade(name, colormin1, colormax1, colormin2, colormax2)
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:124
void Send_Effect_Except(entity eff, vector eff_loc, vector eff_vel, int eff_cnt, vector eff_col_min, vector eff_col_max, entity ignore)
Definition all.qc:105
clientcolors
Definition ent_cs.qc:147
void nade_entrap_boom(entity this)
Definition entrap.qc:33
bool autocvar_g_nades_entrap
Definition entrap.qh:6
float timer
Definition hud.qh:125
void nade_ice_boom(entity this)
Definition ice.qc:80
bool autocvar_g_nades_ice
Definition ice.qh:6
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define IL_EACH(this, cond, body)
#define FOREACH(list, cond, body)
Definition iter.qh:19
#define PlayerPreThink
Definition _all.inc:254
#define PutClientInServer
Definition _all.inc:246
#define ClientDisconnect
Definition _all.inc:242
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
float bound(float min, float value, float max)
vector vectoangles(vector v)
string ftos(float f)
float floor(float f)
float max(float f,...)
void nade_monster_boom(entity this)
Definition monster.qc:7
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_BOUNCE
Definition movetypes.qh:139
#define IS_ONGROUND(s)
Definition movetypes.qh:16
void nade_heal_boom(entity this)
Definition heal.qc:34
bool autocvar_g_nades_heal
Definition heal.qh:6
bool autocvar_g_nades_pokenade
Definition monster.qh:7
string autocvar_g_nades_pokenade_monster_type
Definition monster.qh:8
void nade_spawn_boom(entity this)
Definition spawn.qc:4
void nade_spawn_SetSpawnHealth(entity player)
Definition spawn.qc:22
bool nade_spawn_DestroyDamage(entity this, entity attacker)
Definition spawn.qc:28
bool autocvar_g_nades_spawn
Definition spawn.qh:6
entity Nade_TrailEffect(int proj, int nade_team)
Definition nades.qc:17
float autocvar_g_nades_spread
Definition nades.qc:7
void nade_napalm_boom(entity this)
Definition napalm.qc:152
bool autocvar_g_nades_napalm
Definition napalm.qh:6
bool orb_send(entity this, entity to, int sf)
Definition net.qc:85
float ltime
Definition net.qc:10
var void func_null()
void nade_normal_boom(entity this)
Definition normal.qc:4
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
Definition all.qc:1573
void Kill_Notification(NOTIF broadcast, entity client, MSG net_type, CPID net_cpid)
Definition all.qc:1537
#define KILL_SPREE_LIST
Definition all.qh:491
#define NEW(cname,...)
Definition oo.qh:117
#define CLASS(...)
Definition oo.qh:145
#define ENDCLASS(cname)
Definition oo.qh:281
#define METHOD(cname, name, prototype)
Definition oo.qh:269
#define NULL
Definition post.qh:14
#define makevectors
Definition post.qh:21
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 REGISTRY_GET(id, i)
Definition registry.qh:43
#define setthink(e, f)
vector
Definition self.qh:92
entity this
Definition self.qh:72
#define setcefc(e, f)
vector org
Definition self.qh:92
entity entity toucher
Definition self.qh:72
#define settouch(e, f)
Definition self.qh:73
void SpectateCopy(entity this, entity spectatee)
Definition client.qc:1793
int killcount
Definition client.qh:315
int dir
Definition impulse.qc:89
#define ITEM_TOUCH_NEEDKILL()
Definition items.qh:128
#define ITEM_DAMAGE_NEEDKILL(dt)
Definition items.qh:129
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode)
Definition common.qc:87
const int MIF_SPLASH
Definition common.qh:46
#define PROJECTILE_TOUCH(e, t)
Definition common.qh:28
IntrusiveList g_projectiles
Definition common.qh:58
const int MIF_ARC
Definition common.qh:47
#define PROJECTILE_MAKETRIGGER(e)
Definition common.qh:34
const float VOL_BASE
Definition sound.qh:36
const int CH_SHOTS
Definition sound.qh:14
const int CH_WEAPON_A
Definition sound.qh:7
const float ATTEN_MAX
Definition sound.qh:34
const int CH_SHOTS_SINGLE
Definition sound.qh:15
const float ATTEN_NORM
Definition sound.qh:30
#define sound(e, c, s, v, a)
Definition sound.qh:52
const float ATTEN_LARGE
Definition sound.qh:31
Sound SND_GRENADE_BOUNCE_RANDOM()
Definition all.inc:17
void play2(entity e, string filename)
Definition all.qc:116
float spamsound(entity e, int chan, Sound samp, float vol, float _atten)
use this one if you might be causing spam (e.g.
Definition all.qc:124
#define SND(id)
Definition all.qh:35
#define CS_CVAR(this)
Definition state.qh:51
ClientState CS(Client this)
Definition state.qh:47
float StatusEffects_gettime(StatusEffect this, entity actor)
bool StatusEffects_active(StatusEffect this, entity actor)
const int DAMAGE_NO
Definition subs.qh:79
const int DAMAGE_AIM
Definition subs.qh:81
float takedamage
Definition subs.qh:78
if(frag_attacker.flagcarried)
Definition sv_ctf.qc:2325
entity frag_target
Definition sv_ctf.qc:2321
entity enemy
Definition sv_ctf.qh:153
void freezetag_Unfreeze(entity targ, bool reset_health)
float autocvar_g_freezetag_revive_nade_health
bool autocvar_g_freezetag_revive_nade
#define FOR_EACH_KH_KEY(v)
Definition sv_keyhunt.qh:27
const int MONSTERFLAG_SPAWNED
float autocvar_g_monsters
Definition sv_monsters.qh:5
#define SET_NADE_EFFECT(nade_type, exp_effect, exp_color_min, exp_color_max)
void nades_RemoveBonus(entity player)
Remove all bonus nades from a player.
Definition sv_nades.qc:457
void nades_orb_think(entity this)
Definition sv_nades.qc:56
entity nades_spawn_orb(entity own, entity realown, vector org, float orb_ltime, float orb_rad)
Definition sv_nades.qc:75
void nade_boom(entity this)
Definition sv_nades.qc:107
void spawn_held_nade(entity player, entity nowner, float ntime, string ntype, string pntype)
Definition sv_nades.qc:522
vector nades_PlayerColor(entity this, bool isPants)
Definition sv_nades.qc:13
bool CanThrowNade(entity this)
Definition sv_nades.qc:610
void nade_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition sv_nades.qc:244
void nades_Clear(entity player)
Definition sv_nades.qc:647
void nade_pickup(entity this, entity thenade)
Definition sv_nades.qc:176
void nades_CheckThrow(entity this)
Definition sv_nades.qc:617
bool nade_customize(entity this, entity client)
Definition sv_nades.qc:469
Nade Nades_FromString(string ntype)
Definition sv_nades.qc:504
void nades_GiveBonus(entity player, float score)
Definition sv_nades.qc:434
void nades_RemovePlayer(entity this)
Definition sv_nades.qc:885
void nade_touch(entity this, entity toucher)
Definition sv_nades.qc:189
Nade nades_CheckTypes(Nade ntype)
Definition sv_nades.qc:408
void nade_burn_spawn(entity _nade)
Definition sv_nades.qc:31
bool nade_altbutton
Definition sv_nades.qc:615
#define NADE_TYPE_CHECK(nade_ent, nade_cvar)
int nade_choose_random()
Definition sv_nades.qc:494
entity nade_spawnloc
Definition sv_nades.qc:11
void nade_beep(entity this)
Definition sv_nades.qc:237
NadeOffhand OFFHAND_NADE
Definition sv_nades.qc:691
void nade_timer_think(entity this)
Definition sv_nades.qc:23
float nade_time_primed
Definition sv_nades.qc:9
Nade Nades_GetType(string ntype)
Definition sv_nades.qc:513
void nade_prime(entity this)
Definition sv_nades.qc:568
void toss_nade(entity e, bool set_owner, vector _velocity, float _time)
Definition sv_nades.qc:317
void nade_spawn(entity _nade)
Definition sv_nades.qc:36
bool autocvar_g_nades
Definition sv_nades.qh:5
float nade_lifetime
Definition sv_nades.qh:45
float autocvar_g_nades_nade_minforce
Definition sv_nades.qh:15
int autocvar_g_nades_bonus_score_spree
Definition sv_nades.qh:40
int autocvar_g_nades_nade_newton_style
Definition sv_nades.qh:23
bool autocvar_g_nades_bonus_client_select
Definition sv_nades.qh:29
float autocvar_g_nades_nade_refire
Definition sv_nades.qh:18
bool autocvar_g_nades_override_dropweapon
Definition sv_nades.qh:6
string pokenade_type
Definition sv_nades.qh:48
float autocvar_g_nades_nade_lifetime
Definition sv_nades.qh:14
float autocvar_g_nades_pickup_time
Definition sv_nades.qh:13
bool autocvar_g_nades_bonus_onstrength
Definition sv_nades.qh:30
int autocvar_g_nades_bonus_score_time_flagcarrier
Definition sv_nades.qh:35
bool autocvar_g_nades_bonus_only
Definition sv_nades.qh:31
bool autocvar_g_nades_bonus
Definition sv_nades.qh:27
int autocvar_g_nades_bonus_score_time
Definition sv_nades.qh:34
float autocvar_g_nades_nade_health
Definition sv_nades.qh:17
bool autocvar_g_nades_onspawn
Definition sv_nades.qh:8
vector autocvar_g_nades_throw_offset
Definition sv_nades.qh:7
int autocvar_g_nades_bonus_max
Definition sv_nades.qh:32
entity fake_nade
Definition sv_nades.qh:44
float autocvar_g_nades_nade_maxforce
Definition sv_nades.qh:16
float nade_special_time
Definition sv_nades.qh:47
string autocvar_g_nades_bonus_type
Definition sv_nades.qh:28
string cvar_cl_nade_type
Definition sv_nades.qh:50
float nade_show_particles
Definition sv_nades.qh:53
int autocvar_g_nades_bonus_score_minor
Definition sv_nades.qh:36
bool autocvar_g_nades_pickup
Definition sv_nades.qh:12
int autocvar_g_nades_bonus_score_medium
Definition sv_nades.qh:39
bool autocvar_g_nades_client_select
Definition sv_nades.qh:25
float nade_refire
Definition sv_nades.qh:46
string autocvar_g_nades_nade_type
Definition sv_nades.qh:24
int autocvar_g_nades_bonus_score_max
Definition sv_nades.qh:33
#define GameRules_scoring_is_vip(player)
Definition sv_rules.qh:79
entity vehicle
Entity to disply the shild effect on damage.
#define SAME_TEAM(a, b)
Definition teams.qh:241
vector Team_ColorRGB(int teamid)
Definition teams.qh:76
bool teamplay
Definition teams.qh:59
#define DIFF_TEAM(a, b)
Definition teams.qh:242
entity realowner
vector W_CalculateProjectileVelocity(entity actor, vector pvelocity, vector mvelocity, float forceAbsolute)
Definition tracing.qc:176
int autocvar_g_projectiles_spread_style
Definition tracing.qh:14
vector w_shotorg
Definition tracing.qh:19
#define W_SetupShot(ent, wepent, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition tracing.qh:34
void nade_translocate_boom(entity this)
Definition translocate.qc:4
bool nade_translocate_DestroyDamage(entity this, entity attacker)
bool autocvar_g_nades_translocate
Definition translocate.qh:6
#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:50
void nade_veil_Apply(entity player)
Definition veil.qc:34
void nade_veil_boom(entity this)
Definition veil.qc:26
bool autocvar_g_nades_veil
Definition veil.qh:6
#define WEPSET(id)
Definition all.qh:45
const int WEP_TYPE_MELEE_PRI
Definition weapon.qh:220
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17
const int WEP_TYPE_MELEE_SEC
Definition weapon.qh:221
bool weaponLocked(entity player)