Xonotic
mortar.qc
Go to the documentation of this file.
1 #include "mortar.qh"
2 
3 #ifdef SVQC
4 
5 void W_Mortar_Grenade_Explode(entity this, entity directhitentity)
6 {
7  if(directhitentity.takedamage == DAMAGE_AIM)
8  if(IS_PLAYER(directhitentity))
9  if(DIFF_TEAM(this.realowner, directhitentity))
10  if(!IS_DEAD(directhitentity))
11  if(IsFlying(directhitentity))
12  Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
13 
14  this.event_damage = func_null;
15  this.takedamage = DAMAGE_NO;
16 
17  if(this.move_movetype == MOVETYPE_NONE)
18  this.velocity = this.oldvelocity;
19 
20  RadiusDamage(this, this.realowner, WEP_CVAR_PRI(mortar, damage), WEP_CVAR_PRI(mortar, edgedamage), WEP_CVAR_PRI(mortar, radius), NULL, NULL, WEP_CVAR_PRI(mortar, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
21 
22  delete(this);
23 }
24 
25 void W_Mortar_Grenade_Explode_use(entity this, entity actor, entity trigger)
26 {
27  W_Mortar_Grenade_Explode(this, trigger);
28 }
29 
30 void W_Mortar_Grenade_Explode2(entity this, entity directhitentity)
31 {
32  if(directhitentity.takedamage == DAMAGE_AIM)
33  if(IS_PLAYER(directhitentity))
34  if(DIFF_TEAM(this.realowner, directhitentity))
35  if(!IS_DEAD(directhitentity))
36  if(IsFlying(directhitentity))
37  Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
38 
39  this.event_damage = func_null;
40  this.takedamage = DAMAGE_NO;
41 
42  if(this.move_movetype == MOVETYPE_NONE)
43  this.velocity = this.oldvelocity;
44 
45  RadiusDamage(this, this.realowner, WEP_CVAR_SEC(mortar, damage), WEP_CVAR_SEC(mortar, edgedamage), WEP_CVAR_SEC(mortar, radius), NULL, NULL, WEP_CVAR_SEC(mortar, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
46 
47  delete(this);
48 }
49 
50 void W_Mortar_Grenade_Explode2_use(entity this, entity actor, entity trigger)
51 {
52  W_Mortar_Grenade_Explode2(this, trigger);
53 }
54 
55 void W_Mortar_Grenade_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
56 {
57  if(GetResource(this, RES_HEALTH) <= 0)
58  return;
59 
60  if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions
61  return; // g_projectiles_damage says to halt
62 
63  TakeResource(this, RES_HEALTH, damage);
64 
65  if(GetResource(this, RES_HEALTH) <= 0)
66  W_PrepareExplosionByDamage(this, attacker, adaptor_think2use);
67 }
68 
69 void W_Mortar_Grenade_Think1(entity this)
70 {
71  this.nextthink = time;
72  if(time > this.cnt)
73  {
75  W_Mortar_Grenade_Explode(this, NULL);
76  return;
77  }
78  if(this.gl_detonate_later && this.gl_bouncecnt >= WEP_CVAR_PRI(mortar, remote_minbouncecnt))
79  W_Mortar_Grenade_Explode(this, NULL);
80 }
81 
82 void W_Mortar_Grenade_Touch1(entity this, entity toucher)
83 {
84  PROJECTILE_TOUCH(this, toucher);
85  if(toucher.takedamage == DAMAGE_AIM || WEP_CVAR_PRI(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile
86  {
87  this.use(this, NULL, toucher);
88  }
89  else if(WEP_CVAR_PRI(mortar, type) == 1) // bounce
90  {
92  Send_Effect(EFFECT_HAGAR_BOUNCE, this.origin, this.velocity, 1);
94  this.gl_bouncecnt += 1;
95  }
96  else if(WEP_CVAR_PRI(mortar, type) == 2 && (!toucher || (toucher.takedamage != DAMAGE_AIM && toucher.move_movetype == MOVETYPE_NONE))) // stick
97  {
98  spamsound(this, CH_SHOTS, SND_GRENADE_STICK, VOL_BASE, ATTN_NORM);
99 
100  // let it stick whereever it is
101  this.oldvelocity = this.velocity;
102  this.velocity = '0 0 0';
103  set_movetype(this, MOVETYPE_NONE); // also disables gravity
104  this.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO
105  UpdateCSQCProjectile(this);
106 
107  // do not respond to any more touches
108  this.solid = SOLID_NOT;
109 
110  this.nextthink = min(this.nextthink, time + WEP_CVAR_PRI(mortar, lifetime_stick));
111  }
112 }
113 
114 void W_Mortar_Grenade_Touch2(entity this, entity toucher)
115 {
116  PROJECTILE_TOUCH(this, toucher);
117  if(toucher.takedamage == DAMAGE_AIM || WEP_CVAR_SEC(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile
118  {
119  this.use(this, NULL, toucher);
120  }
121  else if(WEP_CVAR_SEC(mortar, type) == 1) // bounce
122  {
124  Send_Effect(EFFECT_HAGAR_BOUNCE, this.origin, this.velocity, 1);
126  this.gl_bouncecnt += 1;
127 
128  if(WEP_CVAR_SEC(mortar, lifetime_bounce) && this.gl_bouncecnt == 1)
129  this.nextthink = time + WEP_CVAR_SEC(mortar, lifetime_bounce);
130 
131  }
132  else if(WEP_CVAR_SEC(mortar, type) == 2 && (!toucher || (toucher.takedamage != DAMAGE_AIM && toucher.move_movetype == MOVETYPE_NONE))) // stick
133  {
134  spamsound(this, CH_SHOTS, SND_GRENADE_STICK, VOL_BASE, ATTN_NORM);
135 
136  // let it stick whereever it is
137  this.oldvelocity = this.velocity;
138  this.velocity = '0 0 0';
139  set_movetype(this, MOVETYPE_NONE); // also disables gravity
140  this.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO
141  UpdateCSQCProjectile(this);
142 
143  // do not respond to any more touches
144  this.solid = SOLID_NOT;
145 
146  this.nextthink = min(this.nextthink, time + WEP_CVAR_SEC(mortar, lifetime_stick));
147  }
148 }
149 
150 void W_Mortar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
151 {
152  W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(mortar, ammo), weaponentity);
153 
154  W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage), thiswep.m_id);
155  w_shotdir = v_forward; // no TrueAim for grenades please
156 
157  W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
158 
159  entity gren = new(grenade);
160  gren.owner = gren.realowner = actor;
161  gren.bot_dodge = true;
162  gren.bot_dodgerating = WEP_CVAR_PRI(mortar, damage);
164  gren.bouncefactor = WEP_CVAR(mortar, bouncefactor);
165  gren.bouncestop = WEP_CVAR(mortar, bouncestop);
167  gren.projectiledeathtype = thiswep.m_id;
168  gren.weaponentity_fld = weaponentity;
169  setorigin(gren, w_shotorg);
170  setsize(gren, '-3 -3 -3', '3 3 3');
171 
172  gren.cnt = time + WEP_CVAR_PRI(mortar, lifetime);
173  gren.nextthink = time;
174  setthink(gren, W_Mortar_Grenade_Think1);
175  gren.use = W_Mortar_Grenade_Explode_use;
176  settouch(gren, W_Mortar_Grenade_Touch1);
177 
178  gren.takedamage = DAMAGE_YES;
180  gren.damageforcescale = WEP_CVAR_PRI(mortar, damageforcescale);
181  gren.event_damage = W_Mortar_Grenade_Damage;
182  gren.damagedbycontents = true;
184  gren.missile_flags = MIF_SPLASH | MIF_ARC;
185  W_SetupProjVelocity_UP_PRI(gren, mortar);
186 
187  gren.angles = vectoangles(gren.velocity);
188  gren.flags = FL_PROJECTILE;
189  IL_PUSH(g_projectiles, gren);
190  IL_PUSH(g_bot_dodge, gren);
191 
192  if(WEP_CVAR_PRI(mortar, type) == 0 || WEP_CVAR_PRI(mortar, type) == 2)
193  CSQCProjectile(gren, true, PROJECTILE_GRENADE, true);
194  else
195  CSQCProjectile(gren, true, PROJECTILE_GRENADE_BOUNCING, true);
196 
197  MUTATOR_CALLHOOK(EditProjectile, actor, gren);
198 }
199 
200 void W_Mortar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
201 {
202  entity gren;
203 
204  W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(mortar, ammo), weaponentity);
205 
206  W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage), thiswep.m_id | HITTYPE_SECONDARY);
207  w_shotdir = v_forward; // no TrueAim for grenades please
208 
209  W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
210 
211  gren = new(grenade);
212  gren.owner = gren.realowner = actor;
213  gren.bot_dodge = true;
214  gren.bot_dodgerating = WEP_CVAR_SEC(mortar, damage);
216  gren.bouncefactor = WEP_CVAR(mortar, bouncefactor);
217  gren.bouncestop = WEP_CVAR(mortar, bouncestop);
219  gren.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
220  gren.weaponentity_fld = weaponentity;
221  setorigin(gren, w_shotorg);
222  setsize(gren, '-3 -3 -3', '3 3 3');
223 
224  gren.nextthink = time + WEP_CVAR_SEC(mortar, lifetime);
226  gren.use = W_Mortar_Grenade_Explode2_use;
227  settouch(gren, W_Mortar_Grenade_Touch2);
228 
229  gren.takedamage = DAMAGE_YES;
231  gren.damageforcescale = WEP_CVAR_SEC(mortar, damageforcescale);
232  gren.event_damage = W_Mortar_Grenade_Damage;
233  gren.damagedbycontents = true;
235  gren.missile_flags = MIF_SPLASH | MIF_ARC;
236  W_SetupProjVelocity_UP_SEC(gren, mortar);
237 
238  gren.angles = vectoangles(gren.velocity);
239  gren.flags = FL_PROJECTILE;
240  IL_PUSH(g_projectiles, gren);
241  IL_PUSH(g_bot_dodge, gren);
242 
243  if(WEP_CVAR_SEC(mortar, type) == 0 || WEP_CVAR_SEC(mortar, type) == 2)
244  CSQCProjectile(gren, true, PROJECTILE_GRENADE, true);
245  else
246  CSQCProjectile(gren, true, PROJECTILE_GRENADE_BOUNCING, true);
247 
248  MUTATOR_CALLHOOK(EditProjectile, actor, gren);
249 }
250 
251 .float bot_secondary_grenademooth;
252 
253 METHOD(Mortar, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
254 {
255  PHYS_INPUT_BUTTON_ATCK(actor) = false;
256  PHYS_INPUT_BUTTON_ATCK2(actor) = false;
257  if(actor.bot_secondary_grenademooth == 0) // WEAPONTODO: merge this into using WEP_CVAR_BOTH
258  {
259  if(bot_aim(actor, weaponentity, WEP_CVAR_PRI(mortar, speed), WEP_CVAR_PRI(mortar, speed_up), WEP_CVAR_PRI(mortar, lifetime), true))
260  {
261  PHYS_INPUT_BUTTON_ATCK(actor) = true;
262  if(random() < 0.01) actor.bot_secondary_grenademooth = 1;
263  }
264  }
265  else
266  {
267  if(bot_aim(actor, weaponentity, WEP_CVAR_SEC(mortar, speed), WEP_CVAR_SEC(mortar, speed_up), WEP_CVAR_SEC(mortar, lifetime), true))
268  {
269  PHYS_INPUT_BUTTON_ATCK2(actor) = true;
270  if(random() < 0.02) actor.bot_secondary_grenademooth = 0;
271  }
272  }
273 }
274 /*case WR_CALCINFO:
275 {
276  wepinfo_pri_refire = max3(sys_frametime, WEP_CVAR_PRI(mortar, refire), WEP_CVAR_PRI(mortar, animtime));
277  wepinfo_pri_dps = (WEP_CVAR_PRI(mortar, damage) * (1 / wepinfo_pri_refire));
278  wepinfo_pri_speed = (1 / max(1, (10000 / max(1, WEP_CVAR_PRI(mortar, speed)))));
279 
280  // for the range calculation, closer to 1 is better
281  wepinfo_pri_range_max = 2000 * wepinfo_pri_speed;
282  wepinfo_pri_range = wepinfo_pri_speed * WEP_CVAR_PRI(mortar,
283 
284  wepinfo_sec_refire = max3(sys_frametime, WEP_CVAR_SEC(mortar, refire), WEP_CVAR_SEC(mortar, animtime));
285  wepinfo_sec_dps = (WEP_CVAR_SEC(mortar, damage) * (1 / wepinfo_sec_refire));
286 
287  wepinfo_sec_dps = (WEP_CVAR_SEC(mortar, damage) * (1 / max3(sys_frametime, WEP_CVAR_SEC(mortar, refire), WEP_CVAR_SEC(mortar, animtime))));
288  wepinfo_ter_dps = 0;
289  */
290 METHOD(Mortar, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
291 {
292  if(autocvar_g_balance_mortar_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) { // forced reload
293  thiswep.wr_reload(thiswep, actor, weaponentity);
294  } else if(fire & 1)
295  {
296  if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(mortar, refire)))
297  {
298  W_Mortar_Attack(thiswep, actor, weaponentity);
299  weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(mortar, animtime), w_ready);
300  }
301  }
302  else if(fire & 2)
303  {
304  if(WEP_CVAR_SEC(mortar, remote_detonateprimary))
305  {
306  bool nadefound = false;
307  IL_EACH(g_projectiles, it.realowner == actor && it.classname == "grenade",
308  {
309  if(!it.gl_detonate_later)
310  {
311  it.gl_detonate_later = true;
312  nadefound = true;
313  }
314  });
315  if(nadefound)
316  sound(actor, CH_WEAPON_B, SND_ROCKET_DET, VOL_BASE, ATTN_NORM);
317  }
318  else if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(mortar, refire)))
319  {
320  W_Mortar_Attack2(thiswep, actor, weaponentity);
321  weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(mortar, animtime), w_ready);
322  }
323  }
324 }
325 METHOD(Mortar, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
326 {
327  float ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(mortar, ammo);
328  ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(mortar, ammo);
329  return ammo_amount;
330 }
331 METHOD(Mortar, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
332 {
333  float ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(mortar, ammo);
334  ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(mortar, ammo);
335  return ammo_amount;
336 }
337 METHOD(Mortar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
338 {
339  W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo)), SND_RELOAD); // WEAPONTODO
340 }
341 METHOD(Mortar, wr_suicidemessage, Notification(entity thiswep))
342 {
344  return WEAPON_MORTAR_SUICIDE_BOUNCE;
345  else
346  return WEAPON_MORTAR_SUICIDE_EXPLODE;
347 }
348 METHOD(Mortar, wr_killmessage, Notification(entity thiswep))
349 {
351  return WEAPON_MORTAR_MURDER_BOUNCE;
352  else
353  return WEAPON_MORTAR_MURDER_EXPLODE;
354 }
355 
356 #endif
357 #ifdef CSQC
358 
359 METHOD(Mortar, wr_impacteffect, void(entity thiswep, entity actor))
360 {
361  vector org2;
362  org2 = w_org + w_backoff * 12;
363  pointparticles(EFFECT_GRENADE_EXPLODE, org2, '0 0 0', 1);
364  if(!w_issilent)
365  sound(actor, CH_SHOTS, SND_GRENADE_IMPACT, VOL_BASE, ATTN_NORM);
366 }
367 
368 #endif
const float SOLID_NOT
Definition: csprogsdefs.qc:244
const int PROJECTILE_GRENADE
Definition: projectiles.qh:8
#define WEP_CVAR_PRI(wepname, name)
Definition: all.qh:300
#define PHYS_INPUT_BUTTON_ATCK2(s)
Definition: player.qh:148
#define IL_EACH(this, cond, body)
bool bot_aim(entity this,.entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, float applygravity)
float MOVETYPE_NONE
Definition: progsdefs.qc:246
#define WEP_CVAR_SEC(wepname, name)
Definition: all.qh:301
float weapon_load[REGISTRY_MAX(Weapons)]
Definition: weaponsystem.qh:29
const int HITTYPE_BOUNCE
Definition: all.qh:28
float speed
Definition: subs.qh:41
vector w_shotorg
Definition: tracing.qh:18
#define PROJECTILE_MAKETRIGGER(e)
Definition: common.qh:29
Sound SND_GRENADE_BOUNCE_RANDOM()
Definition: all.inc:41
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
Definition: cl_resources.qc:15
const int MIF_ARC
Definition: common.qh:35
#define W_SetupProjVelocity_UP_SEC(ent, wepname)
Definition: tracing.qh:55
const int MIF_SPLASH
Definition: common.qh:34
#define W_SetupShot_ProjectileSize(ent, wepent, mi, ma, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition: tracing.qh:29
float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception)
Definition: common.qc:49
float damageforcescale
Definition: damage.qh:137
IntrusiveList g_damagedbycontents
Definition: damage.qh:155
entity() spawn
float DAMAGE_AIM
Definition: progsdefs.qc:284
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
float radius
Definition: impulse.qh:11
#define WEP_CVAR(wepname, name)
Definition: all.qh:299
vector w_shotdir
Definition: tracing.qh:19
entity weaponentity_fld
Definition: weaponsystem.qh:27
float bouncestop
origin
Definition: ent_cs.qc:114
vector oldvelocity
Definition: main.qh:38
float MOVETYPE_BOUNCE
Definition: progsdefs.qc:256
#define METHOD(cname, name, prototype)
Definition: oo.qh:257
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
#define DIFF_TEAM(a, b)
Definition: teams.qh:240
float move_movetype
Definition: movetypes.qh:76
IntrusiveList g_bot_dodge
Definition: api.qh:150
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
Definition: cl_resources.qc:31
#define PROJECTILE_TOUCH(e, t)
Definition: common.qh:27
const float ATTN_NORM
Definition: csprogsdefs.qc:226
RES_HEALTH
Definition: ent_cs.qc:126
float ammo
Definition: sv_turrets.qh:44
float bouncefactor
float lifetime
Definition: powerups.qc:23
float cnt
Definition: powerups.qc:24
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void UpdateCSQCProjectile(entity e)
const int CH_WEAPON_A
Definition: sound.qh:7
bool weapon_prepareattack(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode)
Definition: common.qc:91
#define pointparticles
Definition: csprogsdefs.qh:13
Definition: mortar.qh:3
#define NULL
Definition: post.qh:17
const float VOL_BASE
Definition: sound.qh:36
#define PHYS_INPUT_BUTTON_ATCK(s)
Definition: player.qh:146
float takedamage
Definition: progsdefs.qc:147
const int HITTYPE_SECONDARY
Definition: all.qh:25
#define IS_DEAD(s)
Definition: utils.qh:26
float nextthink
Definition: csprogsdefs.qc:121
const int CH_SHOTS
Definition: sound.qh:14
bool IsFlying(entity this)
Definition: player.qc:804
float w_deathtype
Definition: damage.qh:97
vector(float skel, float bonenum) _skel_get_boneabs_hidden
float gravity
Definition: items.qh:16
IntrusiveList g_projectiles
Definition: common.qh:46
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
entity Notification
always last
Definition: all.qh:82
float health
Definition: progsdefs.qc:137
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
Definition: damage.qc:1057
entity realowner
Definition: common.qh:25
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
setorigin(ent, v)
#define setthink(e, f)
const int PROJECTILE_GRENADE_BOUNCING
Definition: projectiles.qh:9
void adaptor_think2use_hittype_splash(entity this)
Definition: common.qc:110
#define use
Definition: csprogsdefs.qh:50
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use,.entity weaponentity)
#define sound(e, c, s, v, a)
Definition: sound.qh:52
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
float time
Definition: csprogsdefs.qc:16
vector velocity
Definition: csprogsdefs.qc:103
const int CH_WEAPON_B
Definition: sound.qh:8
int m_id
Definition: weapon.qh:42
float DAMAGE_NO
Definition: progsdefs.qc:282
#define W_SetupProjVelocity_UP_PRI(ent, wepname)
Definition: tracing.qh:53
void set_movetype(entity this, int mt)
#define IS_PLAYER(v)
Definition: utils.qh:9
var void func_null()
vector v_forward
Definition: csprogsdefs.qc:31
float solid
Definition: csprogsdefs.qc:99
float DAMAGE_YES
Definition: progsdefs.qc:283
void W_Reload(entity actor,.entity weaponentity, float sent_ammo_min, Sound sent_sound)
int projectiledeathtype
Definition: common.qh:20