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