Xonotic
mage.qc
Go to the documentation of this file.
1 #include "mage.qh"
2 
3 #ifdef SVQC
4 
5 SOUND(MageSpike_FIRE, W_Sound("electro_fire"));
6 void M_Mage_Attack_Spike(entity this, vector dir);
7 void M_Mage_Attack_Push(entity this);
8 METHOD(MageSpike, wr_think, void(MageSpike thiswep, entity actor, .entity weaponentity, int fire))
9 {
10  TC(MageSpike, thiswep);
11  if (fire & 1)
12  if (!IS_PLAYER(actor) || weapon_prepareattack(thiswep, actor, weaponentity, false, 0.2)) {
13  if (!actor.target_range) actor.target_range = autocvar_g_monsters_target_range;
14  actor.enemy = Monster_FindTarget(actor);
15  monster_makevectors(actor, actor.enemy);
16  W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_MageSpike_FIRE, CH_WEAPON_B, 0, DEATH_MONSTER_MAGE.m_id);
17  if (!IS_PLAYER(actor)) w_shotdir = normalize((actor.enemy.origin + '0 0 10') - actor.origin);
18  M_Mage_Attack_Spike(actor, w_shotdir);
19  weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, 0, w_ready);
20  }
21  if (fire & 2)
22  if (!IS_PLAYER(actor) || weapon_prepareattack(thiswep, actor, weaponentity, true, 0.5)) {
23  M_Mage_Attack_Push(actor);
24  weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, 0, w_ready);
25  }
26 }
27 
28 void M_Mage_Attack_Teleport(entity this, entity targ);
29 
30 CLASS(OffhandMageTeleport, OffhandWeapon)
31  .bool OffhandMageTeleport_key_pressed;
32  METHOD(OffhandMageTeleport, offhand_think, void(OffhandMageTeleport this, entity player, bool key_pressed))
33  {
34  TC(OffhandMageTeleport, this);
35  if (key_pressed && !player.OffhandMageTeleport_key_pressed)
36  M_Mage_Attack_Teleport(player, player.enemy);
37  player.OffhandMageTeleport_key_pressed = key_pressed;
38  }
39 ENDCLASS(OffhandMageTeleport)
40 OffhandMageTeleport OFFHAND_MAGE_TELEPORT;
41 STATIC_INIT(OFFHAND_MAGE_TELEPORT) { OFFHAND_MAGE_TELEPORT = NEW(OffhandMageTeleport); }
42 
43 float autocvar_g_monster_mage_health;
44 float autocvar_g_monster_mage_damageforcescale = 0.5;
45 float autocvar_g_monster_mage_attack_spike_damage;
46 float autocvar_g_monster_mage_attack_spike_radius;
47 float autocvar_g_monster_mage_attack_spike_delay;
48 float autocvar_g_monster_mage_attack_spike_accel;
49 float autocvar_g_monster_mage_attack_spike_decel;
50 float autocvar_g_monster_mage_attack_spike_turnrate;
51 float autocvar_g_monster_mage_attack_spike_speed_max;
52 float autocvar_g_monster_mage_attack_spike_smart;
53 float autocvar_g_monster_mage_attack_spike_smart_trace_min;
54 float autocvar_g_monster_mage_attack_spike_smart_trace_max;
55 float autocvar_g_monster_mage_attack_spike_smart_mindist;
56 float autocvar_g_monster_mage_attack_push_damage;
57 float autocvar_g_monster_mage_attack_push_radius;
58 float autocvar_g_monster_mage_attack_push_delay;
59 float autocvar_g_monster_mage_attack_push_force;
60 float autocvar_g_monster_mage_heal_self;
61 float autocvar_g_monster_mage_heal_allies;
62 float autocvar_g_monster_mage_heal_minhealth;
63 float autocvar_g_monster_mage_heal_range;
64 float autocvar_g_monster_mage_heal_delay;
65 float autocvar_g_monster_mage_shield_time;
66 float autocvar_g_monster_mage_shield_delay;
67 float autocvar_g_monster_mage_shield_blockpercent;
68 float autocvar_g_monster_mage_speed_stop;
69 float autocvar_g_monster_mage_speed_run;
70 float autocvar_g_monster_mage_speed_walk;
71 
72 /*
73 const float mage_anim_idle = 0;
74 const float mage_anim_walk = 1;
75 const float mage_anim_attack = 2;
76 const float mage_anim_pain = 3;
77 const float mage_anim_death = 4;
78 const float mage_anim_run = 5;
79 */
80 
81 void M_Mage_Defend_Heal(entity this);
82 void M_Mage_Defend_Shield(entity this);
83 
84 .entity mage_spike;
85 .float mage_shield_delay;
86 
87 bool M_Mage_Defend_Heal_Check(entity this, entity targ)
88 {
89  if(targ == NULL)
90  return false;
91  if(GetResource(targ, RES_HEALTH) <= 0)
92  return false;
93  if(DIFF_TEAM(targ, this) && targ != this.monster_follow)
94  return false;
95  if(STAT(FROZEN, targ))
96  return false;
97  if(!IS_PLAYER(targ))
98  return (IS_MONSTER(targ) && GetResource(targ, RES_HEALTH) < targ.max_health);
99  if(StatusEffects_active(STATUSEFFECT_Shield, targ))
100  return false;
101 
102  switch(this.skin)
103  {
105  case 1:
106  {
107  return ((GetResource(targ, RES_CELLS) && GetResource(targ, RES_CELLS) < g_pickup_cells_max)
108  || (GetResource(targ, RES_PLASMA) && GetResource(targ, RES_PLASMA) < g_pickup_plasma_max)
109  || (GetResource(targ, RES_ROCKETS) && GetResource(targ, RES_ROCKETS) < g_pickup_rockets_max)
110  || (GetResource(targ, RES_BULLETS) && GetResource(targ, RES_BULLETS) < g_pickup_nails_max)
111  || (GetResource(targ, RES_SHELLS) && GetResource(targ, RES_SHELLS) < g_pickup_shells_max)
112  );
113  }
114  case 2: return (GetResource(targ, RES_ARMOR) < autocvar_g_balance_armor_regenstable);
115  case 3: return (GetResource(targ, RES_HEALTH) > 0);
116  }
117 
118  return false;
119 }
120 
121 void M_Mage_Attack_Spike_Explode(entity this, entity directhitentity)
122 {
123  this.event_damage = func_null;
124 
125  sound(this, CH_SHOTS, SND_GRENADE_IMPACT, VOL_BASE, ATTEN_NORM);
126 
127  this.realowner.mage_spike = NULL;
128 
129  Send_Effect(EFFECT_EXPLOSION_SMALL, this.origin, '0 0 0', 1);
130  RadiusDamage (this, this.realowner, (autocvar_g_monster_mage_attack_spike_damage), (autocvar_g_monster_mage_attack_spike_damage) * 0.5, (autocvar_g_monster_mage_attack_spike_radius),
131  NULL, NULL, 0, DEATH_MONSTER_MAGE.m_id, DMG_NOWEP, directhitentity);
132 
133  delete(this);
134 }
135 
136 void M_Mage_Attack_Spike_Touch(entity this, entity toucher)
137 {
138  PROJECTILE_TOUCH(this, toucher);
139 
140  M_Mage_Attack_Spike_Explode(this, toucher);
141 }
142 
143 .float wait;
144 
145 // copied from W_Seeker_Think
146 void M_Mage_Attack_Spike_Think(entity this)
147 {
148  if (time > this.ltime || (this.enemy && GetResource(this.enemy, RES_HEALTH) <= 0) || GetResource(this.owner, RES_HEALTH) <= 0) {
150  M_Mage_Attack_Spike_Explode(this, NULL);
151  }
152 
153  float spd = vlen(this.velocity);
154  spd = bound(
155  spd - (autocvar_g_monster_mage_attack_spike_decel) * frametime,
156  (autocvar_g_monster_mage_attack_spike_speed_max),
157  spd + (autocvar_g_monster_mage_attack_spike_accel) * frametime
158  );
159 
160  if (this.enemy != NULL)
161  if (this.enemy.takedamage != DAMAGE_AIM || IS_DEAD(this.enemy))
162  this.enemy = NULL;
163 
164  if (this.enemy != NULL)
165  {
166  entity e = this.enemy;
167  vector eorg = 0.5 * (e.absmin + e.absmax);
168  float turnrate = (autocvar_g_monster_mage_attack_spike_turnrate); // how fast to turn
169  vector desireddir = normalize(eorg - this.origin);
170  vector olddir = normalize(this.velocity); // get my current direction
171 
172  // Do evasive maneuvers for world objects? ( this should be a cpu hog. :P )
173  if ((autocvar_g_monster_mage_attack_spike_smart) && vdist(eorg - this.origin, >, autocvar_g_monster_mage_attack_spike_smart_mindist))
174  {
175  // Is it a better idea (shorter distance) to trace to the target itself?
176  if ( vlen2(this.origin + olddir * this.wait) < vlen2(eorg - this.origin))
177  traceline(this.origin, this.origin + olddir * this.wait, false, this);
178  else
179  traceline(this.origin, eorg, false, this);
180 
181  // Setup adaptive tracelength
182  this.wait = bound((autocvar_g_monster_mage_attack_spike_smart_trace_min), vlen(this.origin - trace_endpos), this.wait = (autocvar_g_monster_mage_attack_spike_smart_trace_max));
183 
184  // Calc how important it is that we turn and add this to the desierd (enemy) dir.
185  desireddir = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5);
186  }
187 
188  vector newdir = normalize(olddir + desireddir * turnrate); // take the average of the 2 directions; not the best method but simple & easy
189  this.velocity = newdir * spd; // make me fly in the new direction at my flight speed
190  }
191 
193 
194  //this.angles = vectoangles(this.velocity); // turn model in the new flight direction
195  this.nextthink = time;// + 0.05; // csqc projectiles
196  UpdateCSQCProjectile(this);
197 }
198 
199 void M_Mage_Attack_Spike(entity this, vector dir)
200 {
201  makevectors(this.angles);
202 
203  entity missile = new(M_Mage_Attack_Spike);
204  missile.owner = missile.realowner = this;
205  setthink(missile, M_Mage_Attack_Spike_Think);
206  missile.ltime = time + 7;
207  missile.nextthink = time;
208  missile.solid = SOLID_BBOX;
210  missile.flags = FL_PROJECTILE;
211  IL_PUSH(g_projectiles, missile);
212  IL_PUSH(g_bot_dodge, missile);
213  setorigin(missile, this.origin + v_forward * 14 + '0 0 30' + v_right * -14);
214  setsize(missile, '0 0 0', '0 0 0');
215  missile.velocity = dir * 400;
216  missile.avelocity = '300 300 300';
217  missile.enemy = this.enemy;
218  settouch(missile, M_Mage_Attack_Spike_Touch);
219 
220  this.mage_spike = missile;
221 
222  CSQCProjectile(missile, true, PROJECTILE_MAGE_SPIKE, true);
223 }
224 
225 void M_Mage_Defend_Heal(entity this)
226 {
227  float washealed = false;
228 
229  FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_monster_mage_heal_range, M_Mage_Defend_Heal_Check(this, it),
230  {
231  washealed = true;
232  entity fx = EFFECT_Null;
233  if(IS_PLAYER(it))
234  {
235  switch(this.skin)
236  {
237  case 0:
238  {
239  Heal(it, this, autocvar_g_monster_mage_heal_allies, autocvar_g_balance_health_regenstable);
240  fx = EFFECT_HEALING;
241  break;
242  }
243  case 1:
244  {
245  if(GetResource(this, RES_CELLS)) GiveResourceWithLimit(it, RES_CELLS, 1, g_pickup_cells_max);
246  if(GetResource(this, RES_PLASMA)) GiveResourceWithLimit(it, RES_PLASMA, 1, g_pickup_plasma_max);
247  if(GetResource(this, RES_ROCKETS)) GiveResourceWithLimit(it, RES_ROCKETS, 1, g_pickup_rockets_max);
248  if(GetResource(this, RES_SHELLS)) GiveResourceWithLimit(it, RES_SHELLS, 2, g_pickup_shells_max);
249  if(GetResource(this, RES_BULLETS)) GiveResourceWithLimit(it, RES_BULLETS, 5, g_pickup_nails_max);
250  // TODO: fuel?
251  fx = EFFECT_AMMO_REGEN;
252  break;
253  }
254  case 2:
256  {
257  GiveResourceWithLimit(it, RES_ARMOR, autocvar_g_monster_mage_heal_allies, autocvar_g_balance_armor_regenstable);
258  fx = EFFECT_ARMOR_REPAIR;
259  }
260  break;
261  case 3:
262  float hp = ((it == this) ? autocvar_g_monster_mage_heal_self : autocvar_g_monster_mage_heal_allies);
263  TakeResource(it, RES_HEALTH, hp); // TODO: use regular damage functions? needs a way to bypass friendly fire checks
264  fx = EFFECT_RAGE;
265  break;
266  }
267 
268  Send_Effect(fx, it.origin, '0 0 0', 1);
269  }
270  else
271  {
272  Send_Effect(EFFECT_HEALING, it.origin, '0 0 0', 1);
273  Heal(it, this, autocvar_g_monster_mage_heal_allies, RES_LIMIT_NONE);
274  if(!(it.spawnflags & MONSTERFLAG_INVINCIBLE) && it.sprite)
275  WaypointSprite_UpdateHealth(it.sprite, GetResource(it, RES_HEALTH));
276  }
277  });
278 
279  if(washealed)
280  {
281  setanim(this, this.anim_shoot, true, true, true);
282  this.attack_finished_single[0] = time + (autocvar_g_monster_mage_heal_delay);
283  this.anim_finished = time + 1.5;
284  }
285 }
286 
287 void M_Mage_Attack_Push(entity this)
288 {
289  sound(this, CH_SHOTS, SND_TAGEXP1, 1, ATTEN_NORM);
290  RadiusDamage (this, this, (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_radius),
291  NULL, NULL, (autocvar_g_monster_mage_attack_push_force), DEATH_MONSTER_MAGE.m_id, DMG_NOWEP, this.enemy);
292  Send_Effect(EFFECT_TE_EXPLOSION, this.origin, '0 0 0', 1);
293 
294  setanim(this, this.anim_shoot, true, true, true);
295  this.attack_finished_single[0] = time + (autocvar_g_monster_mage_attack_push_delay);
296 }
297 
298 void M_Mage_Attack_Teleport(entity this, entity targ)
299 {
300  if(!targ) return;
301  if(vdist(targ.origin - this.origin, >, 1500)) return;
302 
303  makevectors(targ.angles);
304  tracebox(targ.origin + ((v_forward * -1) * 200), this.mins, this.maxs, this.origin, MOVE_NOMONSTERS, this);
305 
306  if(trace_fraction < 1)
307  return;
308 
309  vector newpos = targ.origin + ((v_forward * -1) * 200);
310 
311  Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1);
312  Send_Effect(EFFECT_SPAWN_NEUTRAL, newpos, '0 0 0', 1);
313 
314  setorigin(this, newpos);
315 
316  vector a = vectoangles(targ.origin - this.origin);
317  a.x = -a.x;
318  this.angles_x = a.x;
319  this.angles_y = a.y;
320  this.fixangle = true;
321  this.velocity *= 0.5;
322 
323  this.attack_finished_single[0] = time + 0.2;
324 }
325 
326 void M_Mage_Defend_Shield(entity this)
327 {
328  StatusEffects_apply(STATUSEFFECT_Shield, this, time + autocvar_g_monster_mage_shield_time, 0);
329  this.mage_shield_delay = time + (autocvar_g_monster_mage_shield_delay);
330  SetResourceExplicit(this, RES_ARMOR, autocvar_g_monster_mage_shield_blockpercent);
331  setanim(this, this.anim_shoot, true, true, true);
332  this.attack_finished_single[0] = time + 1;
333  this.anim_finished = time + 1;
334 }
335 
336 bool M_Mage_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
337 {
338  switch(attack_type)
339  {
341  {
342  if(random() <= 0.7)
343  {
344  Weapon wep = WEP_MAGE_SPIKE;
345 
346  wep.wr_think(wep, actor, weaponentity, 2);
347  return true;
348  }
349 
350  return false;
351  }
353  {
354  if(!actor.mage_spike)
355  {
356  if(random() <= 0.4)
357  {
358  OffhandWeapon off = OFFHAND_MAGE_TELEPORT;
359  off.offhand_think(off, actor, true);
360  return true;
361  }
362  else
363  {
364  setanim(actor, actor.anim_shoot, true, true, true);
365  actor.attack_finished_single[0] = time + (autocvar_g_monster_mage_attack_spike_delay);
366  actor.anim_finished = time + 1;
367  Weapon wep = WEP_MAGE_SPIKE;
368  wep.wr_think(wep, actor, weaponentity, 1);
369  return true;
370  }
371  }
372 
373  if(actor.mage_spike)
374  return true;
375  else
376  return false;
377  }
378  }
379 
380  return false;
381 }
382 
383 spawnfunc(monster_mage) { Monster_Spawn(this, true, MON_MAGE); }
384 
385 #endif // SVQC
386 
387 #ifdef SVQC
388 METHOD(Mage, mr_think, bool(Mage thismon, entity actor))
389 {
390  TC(Mage, thismon);
391  bool need_help = false;
392 
393  FOREACH_CLIENT(IS_PLAYER(it) && it != actor,
394  {
395  if(vdist(it.origin - actor.origin, <=, autocvar_g_monster_mage_heal_range))
396  if(M_Mage_Defend_Heal_Check(actor, it))
397  {
398  need_help = true;
399  break;
400  }
401  });
402 
403  if(!need_help)
404  {
405  IL_EACH(g_monsters, it != actor,
406  {
407  if(vdist(it.origin - actor.origin, <=, autocvar_g_monster_mage_heal_range))
408  if(M_Mage_Defend_Heal_Check(actor, it))
409  {
410  need_help = true;
411  break;
412  }
413  });
414  }
415 
416  if(GetResource(actor, RES_HEALTH) < (autocvar_g_monster_mage_heal_minhealth) || need_help)
417  if(time >= actor.attack_finished_single[0])
418  if(random() < 0.5)
419  M_Mage_Defend_Heal(actor);
420 
421  if(actor.enemy && time >= actor.mage_shield_delay && random() < 0.5)
422  if(GetResource(actor, RES_HEALTH) < actor.max_health && !StatusEffects_active(STATUSEFFECT_Shield, actor))
423  M_Mage_Defend_Shield(actor);
424 
425  return true;
426 }
427 
428 METHOD(Mage, mr_pain, float(Mage this, entity actor, float damage_take, entity attacker, float deathtype))
429 {
430  TC(Mage, this);
431  return damage_take;
432 }
433 
434 METHOD(Mage, mr_death, bool(Mage this, entity actor))
435 {
436  TC(Mage, this);
437  setanim(actor, actor.anim_die1, false, true, true);
438  return true;
439 }
440 
441 #endif
442 #ifdef GAMEQC
443 METHOD(Mage, mr_anim, bool(Mage this, entity actor))
444 {
445  TC(Mage, this);
446  vector none = '0 0 0';
447  actor.anim_die1 = animfixfps(actor, '4 1 0.5', none); // 2 seconds
448  actor.anim_walk = animfixfps(actor, '1 1 1', none);
449  actor.anim_idle = animfixfps(actor, '0 1 1', none);
450  actor.anim_pain1 = animfixfps(actor, '3 1 2', none); // 0.5 seconds
451  actor.anim_shoot = animfixfps(actor, '2 1 5', none); // analyze models and set framerate
452  actor.anim_run = animfixfps(actor, '5 1 1', none);
453  return true;
454 }
455 #endif
456 #ifdef SVQC
457 .float speed;
458 METHOD(Mage, mr_setup, bool(Mage this, entity actor))
459 {
460  TC(Mage, this);
461  if(!GetResource(this, RES_HEALTH)) SetResourceExplicit(actor, RES_HEALTH, autocvar_g_monster_mage_health);
462  if(!actor.speed) { actor.speed = (autocvar_g_monster_mage_speed_walk); }
463  if(!actor.speed2) { actor.speed2 = (autocvar_g_monster_mage_speed_run); }
464  if(!actor.stopspeed) { actor.stopspeed = (autocvar_g_monster_mage_speed_stop); }
465  if(!actor.damageforcescale) { actor.damageforcescale = (autocvar_g_monster_mage_damageforcescale); }
466 
467  actor.monster_loot = ITEM_HealthBig;
468  actor.monster_attackfunc = M_Mage_Attack;
469 
470  return true;
471 }
472 #endif
const int HITTYPE_SPLASH
automatically set by RadiusDamage
Definition: all.qh:27
#define IL_EACH(this, cond, body)
float anim_finished
Definition: sv_monsters.qh:51
entity Monster_FindTarget(entity this)
Definition: sv_monsters.qc:126
float speed
Definition: subs.qh:41
skin
Definition: ent_cs.qc:143
#define NEW(cname,...)
Definition: oo.qh:105
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
Definition: mage.qh:9
CLASS(Object) Object
Definition: oo.qh:318
#define setanim(...)
Definition: anim.qh:45
float g_pickup_nails_max
Definition: world.qh:70
entity() spawn
float DAMAGE_AIM
Definition: progsdefs.qc:284
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
#define STATIC_INIT(func)
during worldspawn
Definition: static.qh:32
#define IS_MONSTER(v)
Definition: utils.qh:21
vector w_shotdir
Definition: tracing.qh:19
spawnfunc(info_player_attacker)
Definition: sv_assault.qc:283
origin
Definition: ent_cs.qc:114
string W_Sound(string w_snd)
Definition: all.qc:281
#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 ltime
Definition: progsdefs.qc:107
#define DMG_NOWEP
Definition: damage.qh:126
entity owner
Definition: main.qh:73
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
RES_HEALTH
Definition: ent_cs.qc:126
float autocvar_g_balance_health_regenstable
Definition: sv_resources.qh:28
int autocvar_g_balance_armor_regenstable
Definition: sv_resources.qh:16
entity enemy
Definition: sv_ctf.qh:143
const float MOVE_NOMONSTERS
Definition: csprogsdefs.qc:253
#define vlen2(v)
Definition: vector.qh:4
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void UpdateCSQCProjectile(entity e)
float autocvar_g_monsters_target_range
Definition: sv_monsters.qh:12
void GiveResourceWithLimit(entity receiver, Resource res_type, float amount, float limit)
Gives an entity some resource but not more than a limit.
const int MONSTERFLAG_INVINCIBLE
Definition: sv_monsters.qh:90
const int RES_LIMIT_NONE
Definition: resources.qh:46
bool weapon_prepareattack(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
float fixangle
Definition: progsdefs.qc:160
float g_pickup_rockets_max
Definition: world.qh:71
float wait
Definition: subs.qh:39
const int MONSTER_ATTACK_MELEE
Definition: sv_monsters.qh:70
#define NULL
Definition: post.qh:17
float frametime
Definition: csprogsdefs.qc:17
const float VOL_BASE
Definition: sound.qh:36
#define TC(T, sym)
Definition: _all.inc:82
const int MONSTER_ATTACK_RANGED
Definition: sv_monsters.qh:71
vector trace_endpos
Definition: csprogsdefs.qc:37
float g_pickup_shells_max
Definition: world.qh:69
bool Heal(entity targ, entity inflictor, float amount, float limit)
Definition: damage.qc:1063
const int PROJECTILE_MAGE_SPIKE
Definition: projectiles.qh:34
#define IS_DEAD(s)
Definition: utils.qh:26
const float ATTEN_NORM
Definition: sound.qh:30
float nextthink
Definition: csprogsdefs.qc:121
#define W_SetupShot_Dir(ent, wepent, s_forward, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition: tracing.qh:31
void monster_makevectors(entity this, entity targ)
Definition: sv_monsters.qc:66
const int CH_SHOTS
Definition: sound.qh:14
vector(float skel, float bonenum) _skel_get_boneabs_hidden
float MOVETYPE_FLYMISSILE
Definition: progsdefs.qc:255
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
bool Monster_Spawn(entity this, bool check_appear, Monster mon)
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition: vector.qh:8
float g_pickup_plasma_max
Definition: world.qh:73
#define ENDCLASS(cname)
Definition: oo.qh:269
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
vector v_right
Definition: csprogsdefs.qc:31
entity realowner
Definition: common.qh:25
const float SOLID_BBOX
Definition: csprogsdefs.qc:246
setorigin(ent, v)
#define setthink(e, f)
vector trace_plane_normal
Definition: csprogsdefs.qc:38
vector angles
Definition: csprogsdefs.qc:104
#define sound(e, c, s, v, a)
Definition: sound.qh:52
#define SOUND(name, path)
Definition: all.qh:30
IntrusiveList g_monsters
Definition: sv_monsters.qh:144
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
float g_pickup_cells_max
Definition: world.qh:72
float time
Definition: csprogsdefs.qc:16
vector velocity
Definition: csprogsdefs.qc:103
const int CH_WEAPON_B
Definition: sound.qh:8
int dir
Definition: impulse.qc:89
#define makevectors
Definition: post.qh:21
float trace_fraction
Definition: csprogsdefs.qc:36
void set_movetype(entity this, int mt)
#define IS_PLAYER(v)
Definition: utils.qh:9
var void func_null()
float attack_finished_single[MAX_WEAPONSLOTS]
Definition: weaponsystem.qh:36
vector v_forward
Definition: csprogsdefs.qc:31
entity monster_follow
Definition: sv_monsters.qh:39
int projectiledeathtype
Definition: common.qh:20