Xonotic
minelayer.qc
Go to the documentation of this file.
1 #include "minelayer.qh"
2 
3 #ifdef SVQC
4 
5 void W_MineLayer_Stick(entity this, entity to)
6 {
7  spamsound(this, CH_SHOTS, SND_MINE_STICK, VOL_BASE, ATTN_NORM);
8 
9  // in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile
10 
11  entity newmine = spawn();
12  IL_PUSH(g_mines, newmine);
13  newmine.weaponentity_fld = this.weaponentity_fld;
14  newmine.classname = this.classname;
15 
16  newmine.bot_dodge = this.bot_dodge;
17  newmine.bot_dodgerating = this.bot_dodgerating;
18 
19  newmine.owner = this.owner;
20  newmine.realowner = this.realowner;
21  setorigin(newmine, this.origin);
22  setmodel(newmine, MDL_MINELAYER_MINE);
23  setsize(newmine, '-4 -4 -4', '4 4 4');
24  newmine.angles = vectoangles(-trace_plane_normal); // face against the surface
25 
26  newmine.movedir = -trace_plane_normal;
27 
28  newmine.takedamage = this.takedamage;
29  newmine.damageforcescale = this.damageforcescale;
31  newmine.event_damage = this.event_damage;
32  newmine.spawnshieldtime = this.spawnshieldtime;
33  newmine.damagedbycontents = true;
34  IL_PUSH(g_damagedbycontents, newmine);
35 
36  set_movetype(newmine, MOVETYPE_NONE); // lock the mine in place
37  newmine.projectiledeathtype = this.projectiledeathtype;
38 
39  newmine.mine_time = this.mine_time;
40 
41  settouch(newmine, func_null);
42  setthink(newmine, W_MineLayer_Think);
43  newmine.nextthink = time;
44  newmine.cnt = this.cnt;
45  newmine.flags = this.flags;
46  IL_PUSH(g_projectiles, newmine);
47  IL_PUSH(g_bot_dodge, newmine);
48 
49  delete(this);
50 
51  if(to)
52  SetMovetypeFollow(newmine, to);
53 }
54 
55 void W_MineLayer_Explode(entity this, entity directhitentity)
56 {
57  if(directhitentity.takedamage == DAMAGE_AIM)
58  if(IS_PLAYER(directhitentity))
59  if(DIFF_TEAM(this.realowner, directhitentity))
60  if(!IS_DEAD(directhitentity))
61  if(IsFlying(directhitentity))
62  Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
63 
64  this.event_damage = func_null;
65  this.takedamage = DAMAGE_NO;
66 
67  RadiusDamage(this, this.realowner, WEP_CVAR(minelayer, damage), WEP_CVAR(minelayer, edgedamage), WEP_CVAR(minelayer, radius), NULL, NULL, WEP_CVAR(minelayer, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
68 
69  .entity weaponentity = this.weaponentity_fld;
70  Weapon thiswep = WEP_MINE_LAYER;
71  if(this.realowner.(weaponentity).m_weapon == thiswep)
72  {
73  entity own = this.realowner;
74  if(!thiswep.wr_checkammo1(thiswep, own, weaponentity))
75  {
76  own.cnt = thiswep.m_id;
77  ATTACK_FINISHED(own, weaponentity) = time;
78  own.(weaponentity).m_switchweapon = w_getbestweapon(own, weaponentity);
79  }
80  }
81  delete(this);
82 }
83 
84 void W_MineLayer_Explode_think(entity this)
85 {
86  W_MineLayer_Explode(this, NULL);
87 }
88 
89 void W_MineLayer_DoRemoteExplode(entity this)
90 {
91  this.event_damage = func_null;
92  this.takedamage = DAMAGE_NO;
93 
95  this.velocity = this.movedir; // particle fx and decals need .velocity
96 
97  RadiusDamage(this, this.realowner, WEP_CVAR(minelayer, remote_damage), WEP_CVAR(minelayer, remote_edgedamage), WEP_CVAR(minelayer, remote_radius),
98  NULL, NULL, WEP_CVAR(minelayer, remote_force), this.projectiledeathtype | HITTYPE_BOUNCE, this.weaponentity_fld, NULL);
99 
100  .entity weaponentity = this.weaponentity_fld;
101  Weapon thiswep = WEP_MINE_LAYER;
102  if(this.realowner.(weaponentity).m_weapon == thiswep)
103  {
104  entity own = this.realowner;
105  if(!thiswep.wr_checkammo1(thiswep, own, weaponentity))
106  {
107  own.cnt = thiswep.m_id;
108  ATTACK_FINISHED(own, weaponentity) = time;
109  own.(weaponentity).m_switchweapon = w_getbestweapon(own, weaponentity);
110  }
111  }
112  delete(this);
113 }
114 
115 void W_MineLayer_RemoteExplode(entity this)
116 {
117  if(!IS_DEAD(this.realowner))
118  if((this.spawnshieldtime >= 0)
119  ? (time >= this.spawnshieldtime) // timer
120  : (vdist(NearestPointOnBox(this.realowner, this.origin) - this.origin, >, WEP_CVAR(minelayer, remote_radius))) // safety device
121  )
122  {
123  W_MineLayer_DoRemoteExplode(this);
124  }
125 }
126 
127 void W_MineLayer_ProximityExplode(entity this)
128 {
129  // make sure no friend is in the mine's radius. If there is any, explosion is delayed until he's at a safe distance
130  if(WEP_CVAR(minelayer, protection) && this.mine_explodeanyway == 0)
131  {
132  entity head;
133  head = findradius(this.origin, WEP_CVAR(minelayer, radius));
134  while(head)
135  {
136  if(head == this.realowner || SAME_TEAM(head, this.realowner))
137  return;
138  head = head.chain;
139  }
140  }
141 
142  this.mine_time = 0;
143  W_MineLayer_Explode(this, NULL);
144 }
145 
146 int W_MineLayer_Count(entity e, .entity weaponentity)
147 {
148  int minecount = 0;
149  IL_EACH(g_mines, it.realowner == e && it.weaponentity_fld == weaponentity,
150  {
151  minecount += 1;
152  });
153 
154  return minecount;
155 }
156 
157 void W_MineLayer_Think(entity this)
158 {
159  entity head;
160 
161  this.nextthink = time;
162 
163  if(this.move_movetype == MOVETYPE_FOLLOW)
164  {
165  if(LostMovetypeFollow(this))
166  {
167  UnsetMovetypeFollow(this);
169  }
170  }
171 
172  // our lifetime has expired, it's time to die - mine_time just allows us to play a sound for this
173  // TODO: replace this mine_trigger.wav sound with a real countdown
174  if((time > this.cnt) && (!this.mine_time) && (this.cnt > 0))
175  {
176  if(WEP_CVAR(minelayer, lifetime_countdown) > 0)
177  spamsound(this, CH_SHOTS, SND_MINE_TRIGGER, VOL_BASE, ATTN_NORM);
178  this.mine_time = time + WEP_CVAR(minelayer, lifetime_countdown);
179  this.mine_explodeanyway = 1; // make the mine super aggressive -- Samual: Rather, make it not care if a team mate is near.
180  }
181 
182  // a player's mines shall explode if he disconnects or dies
183  // TODO: Do this on team change too -- Samual: But isn't a player killed when they switch teams?
184  if(!IS_PLAYER(this.realowner) || IS_DEAD(this.realowner) || STAT(FROZEN, this.realowner))
185  {
187  W_MineLayer_Explode(this, NULL);
188  return;
189  }
190 
191  // set the mine for detonation when a foe gets close enough
192  head = findradius(this.origin, WEP_CVAR(minelayer, proximityradius));
193  while(head)
194  {
195  if(IS_PLAYER(head) && !IS_DEAD(head) && !STAT(FROZEN, head))
196  if(head != this.realowner && DIFF_TEAM(head, this.realowner)) // don't trigger for team mates
197  if(!this.mine_time)
198  {
199  spamsound(this, CH_SHOTS, SND_MINE_TRIGGER, VOL_BASE, ATTN_NORM);
200  this.mine_time = time + WEP_CVAR(minelayer, time);
201  }
202  head = head.chain;
203  }
204 
205  // explode if it's time to
206  if(this.mine_time && time >= this.mine_time)
207  {
208  W_MineLayer_ProximityExplode(this);
209  return;
210  }
211 
212  // remote detonation
213  .entity weaponentity = this.weaponentity_fld;
214  if(this.realowner.(weaponentity).m_weapon == WEP_MINE_LAYER)
215  if(!IS_DEAD(this.realowner))
216  if(this.minelayer_detonate)
217  W_MineLayer_RemoteExplode(this);
218 }
219 
220 void W_MineLayer_Touch(entity this, entity toucher)
221 {
223  return; // we're already a stuck mine, why do we get called? TODO does this even happen?
224 
225  PROJECTILE_TOUCH(this, toucher);
226 
227  if((toucher && IS_PLAYER(toucher) && !IS_DEAD(toucher)) || toucher.owner == this.owner)
228  {
229  // hit a player or other mine
230  // don't stick
231  }
232  else
233  {
234  W_MineLayer_Stick(this, toucher);
235  }
236 }
237 
238 void W_MineLayer_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
239 {
240  if(GetResource(this, RES_HEALTH) <= 0)
241  return;
242 
243  float is_from_enemy = (inflictor.realowner != this.realowner);
244 
245  if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, (is_from_enemy ? 1 : -1)))
246  return; // g_projectiles_damage says to halt
247 
248  TakeResource(this, RES_HEALTH, damage);
249  this.angles = vectoangles(this.velocity);
250 
251  if(GetResource(this, RES_HEALTH) <= 0)
252  W_PrepareExplosionByDamage(this, attacker, W_MineLayer_Explode_think);
253 }
254 
255 void W_MineLayer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
256 {
257  // scan how many mines we placed, and return if we reached our limit
258  if(WEP_CVAR(minelayer, limit))
259  {
260  int minecount = W_MineLayer_Count(actor, weaponentity);
261  if(minecount >= WEP_CVAR(minelayer, limit))
262  {
263  // the refire delay keeps this message from being spammed
264  Send_Notification(NOTIF_ONE, actor, MSG_MULTI, WEAPON_MINELAYER_LIMIT, WEP_CVAR(minelayer, limit));
265  play2(actor, SND(UNAVAILABLE));
266  return;
267  }
268  }
269 
270  W_DecreaseAmmo(thiswep, actor, WEP_CVAR(minelayer, ammo), weaponentity);
271 
272  W_SetupShot_ProjectileSize(actor, weaponentity, '-4 -4 -4', '4 4 4', false, 5, SND_MINE_FIRE, CH_WEAPON_A, WEP_CVAR(minelayer, damage), thiswep.m_id);
273  W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
274 
276  mine.weaponentity_fld = weaponentity;
277  IL_PUSH(g_mines, mine);
278  mine.owner = mine.realowner = actor;
279  if(WEP_CVAR(minelayer, detonatedelay) >= 0)
280  mine.spawnshieldtime = time + WEP_CVAR(minelayer, detonatedelay);
281  else
282  mine.spawnshieldtime = -1;
283  mine.classname = "mine";
284  mine.bot_dodge = true;
285  mine.bot_dodgerating = WEP_CVAR(minelayer, damage) * 2; // * 2 because it can detonate inflight which makes it even more dangerous
286 
287  mine.takedamage = DAMAGE_YES;
288  mine.damageforcescale = WEP_CVAR(minelayer, damageforcescale);
289  SetResourceExplicit(mine, RES_HEALTH, WEP_CVAR(minelayer, health));
290  mine.event_damage = W_MineLayer_Damage;
291  mine.damagedbycontents = true;
293 
296  mine.projectiledeathtype = thiswep.m_id;
297  mine.weaponentity_fld = weaponentity;
298  setsize(mine, '-4 -4 -4', '4 4 4'); // give it some size so it can be shot
299 
300  setorigin(mine, w_shotorg - v_forward * 4); // move it back so it hits the wall at the right point
301  W_SetupProjVelocity_Basic(mine, WEP_CVAR(minelayer, speed), 0);
302  mine.angles = vectoangles(mine.velocity);
303 
304  settouch(mine, W_MineLayer_Touch);
305  setthink(mine, W_MineLayer_Think);
306  mine.nextthink = time;
307  mine.cnt = (WEP_CVAR(minelayer, lifetime) - WEP_CVAR(minelayer, lifetime_countdown));
308  mine.flags = FL_PROJECTILE;
309  IL_PUSH(g_projectiles, mine);
310  IL_PUSH(g_bot_dodge, mine);
311  mine.missile_flags = MIF_SPLASH | MIF_ARC | MIF_PROXY;
312 
313  if(mine.cnt > 0) { mine.cnt += time; }
314 
315  CSQCProjectile(mine, true, PROJECTILE_MINE, true);
316 
317  // common properties
318 
319  MUTATOR_CALLHOOK(EditProjectile, actor, mine);
320 }
321 
322 bool W_MineLayer_PlacedMines(entity this, .entity weaponentity, bool detonate)
323 {
324  bool minfound = false;
325 
326  IL_EACH(g_mines, it.realowner == this && it.weaponentity_fld == weaponentity,
327  {
328  if(detonate)
329  {
330  if(!it.minelayer_detonate)
331  {
332  it.minelayer_detonate = true;
333  minfound = true;
334  }
335  }
336  else
337  minfound = true;
338  });
339  return minfound;
340 }
341 
342 METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
343 {
344  // aim and decide to fire if appropriate
345  int minecount = W_MineLayer_Count(actor, weaponentity);
346  if(minecount >= WEP_CVAR(minelayer, limit))
347  PHYS_INPUT_BUTTON_ATCK(actor) = false;
348  else
349  PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR(minelayer, speed), 0, WEP_CVAR(minelayer, lifetime), false);
350  if(skill >= 2) // skill 0 and 1 bots won't detonate mines!
351  {
352  // decide whether to detonate mines
353  float edgedamage, coredamage, edgeradius, recipricoledgeradius;
354  float selfdamage, teamdamage, enemydamage;
355  edgedamage = WEP_CVAR(minelayer, edgedamage);
356  coredamage = WEP_CVAR(minelayer, damage);
357  edgeradius = WEP_CVAR(minelayer, radius);
358  recipricoledgeradius = 1 / edgeradius;
359  selfdamage = 0;
360  teamdamage = 0;
361  enemydamage = 0;
362 
363  IL_EACH(g_mines, it.realowner == actor,
364  {
365  entity mine = it;
366  IL_EACH(g_bot_targets, it.bot_attack,
367  {
368  float d = vlen(it.origin + (it.mins + it.maxs) * 0.5 - mine.origin);
369  d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
370  // count potential damage according to type of target
371  if(it == actor)
372  selfdamage = selfdamage + d;
373  else if(SAME_TEAM(it, actor))
374  teamdamage = teamdamage + d;
375  else if(bot_shouldattack(actor, it))
376  enemydamage = enemydamage + d;
377  });
378  });
379 
380  float desirabledamage;
381  desirabledamage = enemydamage;
382  if(StatusEffects_active(STATUSEFFECT_Shield, actor) && !StatusEffects_active(STATUSEFFECT_SpawnShield, actor))
383  desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent;
384  if(teamplay && actor.team)
385  desirabledamage = desirabledamage - teamdamage;
386 
387  makevectors(actor.v_angle);
388  IL_EACH(g_mines, it.realowner == actor,
389  {
390  if(skill > 9) // normal players only do this for the target they are tracking
391  {
392  entity mine = it;
393  IL_EACH(g_bot_targets, it.bot_attack,
394  {
395  if((v_forward * normalize(mine.origin - it.origin) < 0.1)
396  && desirabledamage > 0.1 * coredamage
397  ) PHYS_INPUT_BUTTON_ATCK2(actor) = true;
398  });
399  }
400  else
401  {
402  //As the distance gets larger, a correct detonation gets near imposible
403  //Bots are assumed to use the mine spawnfunc_light to see if the mine gets near a player
404  if((v_forward * normalize(it.origin - actor.enemy.origin) < 0.1)
405  && IS_PLAYER(actor.enemy)
406  && (desirabledamage >= 0.1 * coredamage)
407  )
408  {
409  float distance = bound(300, vlen(actor.origin - actor.enemy.origin), 30000);
410  if(random() / distance * 300 > frametime * bound(0, (10 - skill) * 0.2, 1))
411  PHYS_INPUT_BUTTON_ATCK2(actor) = true;
412  }
413  }
414  });
415 
416  // if we would be doing at X percent of the core damage, detonate it
417  // but don't fire a new shot at the same time!
418  if(desirabledamage >= 0.75 * coredamage) //this should do group damage in rare fortunate events
419  PHYS_INPUT_BUTTON_ATCK2(actor) = true;
420  if((skill > 6.5) && (selfdamage > GetResource(actor, RES_HEALTH)))
421  PHYS_INPUT_BUTTON_ATCK2(actor) = false;
422  //if(PHYS_INPUT_BUTTON_ATCK2(actor) == true)
423  // dprint(ftos(desirabledamage),"\n");
424  if(PHYS_INPUT_BUTTON_ATCK2(actor)) PHYS_INPUT_BUTTON_ATCK(actor) = false;
425  }
426 }
427 METHOD(MineLayer, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
428 {
429  actor.(weaponentity).minelayer_mines = W_MineLayer_Count(actor, weaponentity);
430 
431  if(autocvar_g_balance_minelayer_reload_ammo && actor.(weaponentity).clip_load < WEP_CVAR(minelayer, ammo)) // forced reload
432  {
433  // not if we're holding the minelayer without enough ammo, but can detonate existing mines
434  if(!(W_MineLayer_PlacedMines(actor, weaponentity, false) && GetResource(actor, thiswep.ammo_type) < WEP_CVAR(minelayer, ammo))) {
435  thiswep.wr_reload(thiswep, actor, weaponentity);
436  }
437  }
438  else if(fire & 1)
439  {
440  if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(minelayer, refire)))
441  {
442  W_MineLayer_Attack(thiswep, actor, weaponentity);
443  weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(minelayer, animtime), w_ready);
444  }
445  }
446 
447  if(fire & 2)
448  {
449  if(W_MineLayer_PlacedMines(actor, weaponentity, true))
450  sound(actor, CH_WEAPON_B, SND_MINE_DET, VOL_BASE, ATTN_NORM);
451  }
452 }
453 METHOD(MineLayer, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
454 {
455  // actually do // don't switch while placing a mine
456  //if(ATTACK_FINISHED(actor, weaponentity) <= time || PS(actor).m_weapon != WEP_MINE_LAYER)
457  //{
458  float ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR(minelayer, ammo);
459  ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(minelayer, ammo);
460  return ammo_amount;
461  //}
462  //return true;
463 }
464 METHOD(MineLayer, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
465 {
466  if(W_MineLayer_PlacedMines(actor, weaponentity, false))
467  return true;
468  else
469  return false;
470 }
471 METHOD(MineLayer, wr_resetplayer, void(entity thiswep, entity actor))
472 {
473  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
474  {
475  .entity weaponentity = weaponentities[slot];
476  actor.(weaponentity).minelayer_mines = 0;
477  }
478 }
479 METHOD(MineLayer, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
480 {
481  W_Reload(actor, weaponentity, WEP_CVAR(minelayer, ammo), SND_RELOAD);
482 }
483 METHOD(MineLayer, wr_suicidemessage, Notification(entity thiswep))
484 {
485  return WEAPON_MINELAYER_SUICIDE;
486 }
487 METHOD(MineLayer, wr_killmessage, Notification(entity thiswep))
488 {
489  return WEAPON_MINELAYER_MURDER;
490 }
491 
492 #endif
493 #ifdef CSQC
494 
495 METHOD(MineLayer, wr_impacteffect, void(entity thiswep, entity actor))
496 {
497  vector org2;
498  org2 = w_org + w_backoff * 12;
499  pointparticles(EFFECT_ROCKET_EXPLODE, org2, '0 0 0', 1);
500  if(!w_issilent)
501  sound(actor, CH_SHOTS, SND_MINE_EXP, VOL_BASE, ATTN_NORM);
502 }
503 
504 #endif
#define PHYS_INPUT_BUTTON_ATCK2(s)
Definition: player.qh:148
#define W_SetupProjVelocity_Basic(ent, pspeed, pspread)
Definition: tracing.qh:48
#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
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
float spawnshieldtime
Definition: damage.qh:64
#define PROJECTILE_MAKETRIGGER(e)
Definition: common.qh:29
#define SND(id)
Definition: all.qh:35
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
int minelayer_mines
Definition: wepent.qh:11
const int MIF_SPLASH
Definition: common.qh:34
#define w_getbestweapon(ent, wepent)
Definition: selection.qh:23
float MOVETYPE_TOSS
Definition: progsdefs.qc:252
#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
const int PROJECTILE_MINE
Definition: projectiles.qh:10
float DAMAGE_AIM
Definition: progsdefs.qc:284
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
float radius
Definition: impulse.qh:11
float skill
Definition: api.qh:35
#define WEP_CVAR(wepname, name)
Definition: all.qh:299
vector w_shotdir
Definition: tracing.qh:19
entity weaponentity_fld
Definition: weaponsystem.qh:27
entity to
Definition: self.qh:96
origin
Definition: ent_cs.qc:114
string classname
Definition: csprogsdefs.qc:107
#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
entity owner
Definition: main.qh:73
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
#define setmodel(this, m)
Definition: model.qh:26
const float ATTN_NORM
Definition: csprogsdefs.qc:226
RES_HEALTH
Definition: ent_cs.qc:126
float ammo
Definition: sv_turrets.qh:44
vector movedir
Definition: progsdefs.qc:203
float lifetime
Definition: powerups.qc:23
float autocvar_g_balance_selfdamagepercent
Definition: damage.qh:24
float cnt
Definition: powerups.qc:24
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
const int CH_WEAPON_A
Definition: sound.qh:7
const int MAX_WEAPONSLOTS
Definition: weapon.qh:13
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
entity WarpZone_RefSys_SpawnSameRefSys(entity me)
Definition: common.qc:791
#define pointparticles
Definition: csprogsdefs.qh:13
#define NULL
Definition: post.qh:17
float bot_dodgerating
Definition: api.qh:39
const float VOL_BASE
Definition: sound.qh:36
#define PHYS_INPUT_BUTTON_ATCK(s)
Definition: player.qh:146
float takedamage
Definition: progsdefs.qc:147
#define SAME_TEAM(a, b)
Definition: teams.qh:239
float teamplay
Definition: progsdefs.qc:31
#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
vector(float skel, float bonenum) _skel_get_boneabs_hidden
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
float flags
Definition: csprogsdefs.qc:129
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition: vector.qh:8
float MOVETYPE_FOLLOW
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
float bot_dodge
Definition: api.qh:40
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
setorigin(ent, v)
#define setthink(e, f)
vector trace_plane_normal
Definition: csprogsdefs.qc:38
#define ATTACK_FINISHED(ent, w)
Definition: weaponsystem.qh:42
vector angles
Definition: csprogsdefs.qc:104
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
const int MIF_PROXY
Definition: common.qh:36
int m_id
Definition: weapon.qh:42
#define makevectors
Definition: post.qh:21
float DAMAGE_NO
Definition: progsdefs.qc:282
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 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