Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
damageeffects.qc
Go to the documentation of this file.
1#include "damageeffects.qh"
2
3REGISTER_NET_LINKED(ENT_CLIENT_DAMAGEINFO)
4
5#ifdef SVQC
6
8{
9 vector org = vec3(floor(this.origin.x), floor(this.origin.y), floor(this.origin.z));
10 WriteHeader(MSG_ENTITY, ENT_CLIENT_DAMAGEINFO);
12 WriteVector(MSG_ENTITY, org);
13 WriteByte(MSG_ENTITY, bound(1, this.dmg, 255));
14 WriteByte(MSG_ENTITY, bound(0, this.dmg_radius, 255));
15 WriteByte(MSG_ENTITY, bound(1, this.dmg_edge, 255));
16
17 // we can't send the force vector compressed with compressShortVector to 1 byte since
18 // it's too inaccurate and would break decals when hitting a surface with a small angle
19 // (the traceline performed by the client to spawn a decal wouldn't hit the surface at all)
20 // so we send force direction with 3 bytes and force length with 1 byte
21 // Since this.velocity is a normalized vector we map vector components
22 // from [-1, 1] to [-127, 127]
23 WriteChar(MSG_ENTITY, rint(this.velocity.x * BITS(7)));
24 WriteChar(MSG_ENTITY, rint(this.velocity.y * BITS(7)));
25 WriteChar(MSG_ENTITY, rint(this.velocity.z * BITS(7)));
26
27 // max 255 * 4 = 1020 force length, min 0 (discards negative values)
28 WriteByte(MSG_ENTITY, bound(0, this.dmg_force / 4, BITS(8)));
29
32 return true;
33}
34
35void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner)
36{
37 // TODO maybe call this from non-edgedamage too?
38 // TODO maybe make the client do the particle effects for the weapons and the impact sounds using this info?
39
40 if(!sound_allowed(MSG_BROADCAST, dmgowner))
41 deathtype |= 0x8000;
42
43 entity e = new_pure(damageinfo);
44 // origin is just data to be sent
45 //setorigin(e, org);
46 e.origin = org;
47 e.projectiledeathtype = deathtype;
48 e.dmg = coredamage;
49 e.dmg_edge = edgedamage;
50 bool rad_negative = false;
51 if(rad < 0)
52 {
53 // make it positive (unsigned) so it can be sent as byte
54 rad_negative = true;
55 rad = -rad;
56 }
57 e.dmg_radius = rad;
58 e.dmg_force = vlen(force);
59 e.velocity = (e.dmg_force ? force / e.dmg_force : '0 0 0');
60
61 e.species = bloodtype & BITS(4); // it only uses bits from 0 to 3, see SPECIES_* constants
62 if(rad_negative)
63 e.species |= BIT(7);
64
65 e.colormap = (teamplay) ? dmgowner.team : dmgowner.clientcolors; // NOTE: doesn't work on non-clients
66
68}
69
70#endif
71
72#ifdef CSQC
73
76
77.entity tag_entity;
78
79.float cnt;
80.int state;
81
82.bool silent;
83
85{
86 // if particle distribution is enabled, slow ticrate by total number of damages
88 this.nextthink = time + autocvar_cl_damageeffect_ticrate * this.owner.total_damages;
89 else
91
92 if(time >= this.cnt || !this.owner || !this.owner.modelindex || !this.owner.drawmask)
93 {
94 // time is up or the player got gibbed / disconnected
95 this.owner.total_damages = max(0, this.owner.total_damages - 1);
96 delete(this);
97 return;
98 }
99 if(this.state && !this.owner.csqcmodel_isdead)
100 {
101 // if the player was dead but is now alive, it means they respawned
102 // if so, clear their damage effects, or damages from their dead body will be copied back
103 this.owner.total_damages = max(0, this.owner.total_damages - 1);
104 delete(this);
105 return;
106 }
107 this.state = this.owner.csqcmodel_isdead;
108 if((this.owner.isplayermodel & ISPLAYER_LOCAL) && !autocvar_chase_active)
109 return; // if we aren't using a third person camera, hide our own effects
110
111 // now generate the particles
112 vector org = gettaginfo(this, 0); // origin at attached location
113 __pointparticles(this.team, org, '0 0 0', 1);
114}
115
116string species_prefix(int specnum)
117{
118 switch(specnum)
119 {
120 case SPECIES_HUMAN: return "";
121 case SPECIES_ALIEN: return "alien_";
122 case SPECIES_ROBOT_SHINY: return "robot_";
123 case SPECIES_ROBOT_RUSTY: return "robot_"; // use the same effects, only different gibs
124 case SPECIES_ROBOT_SOLID: return "robot_"; // use the same effects, only different gibs
125 case SPECIES_ANIMAL: return "animal_";
126 case SPECIES_RESERVED: return "reserved_";
127 default: return "";
128 }
129}
130
131void DamageEffect(entity this, vector hitorg, float thedamage, int type, int specnum)
132{
133 // particle effects for players and objects damaged by weapons (eg: flames coming out of victims shot with rockets)
134
135 int nearestbone = 0;
136 float life;
137 entity e, wep;
138
140 return;
141 if(!this || !this.modelindex || !this.drawmask)
142 return;
143
144 // if this is a rigged mesh, the effect will show on the bone where damage was dealt
145 // we do this by choosing the skeletal bone closest to the impact, and attaching our entity to it
146 // if there's no skeleton, object origin will automatically be selected
147 FOR_EACH_TAG(this)
148 {
149 if(!tagnum)
150 continue; // skip empty bones
151 // blacklist bones positioned outside the mesh, or the effect will be floating
152 // TODO: Do we have to do it this way? Why do these bones exist at all?
153 if(gettaginfo_name == "master" || gettaginfo_name == "knee_L" || gettaginfo_name == "knee_R" || gettaginfo_name == "leg_L" || gettaginfo_name == "leg_R")
154 continue; // player model bone blacklist
155
156 // now choose the bone closest to impact origin
157 if(nearestbone == 0 || vlen2(hitorg - gettaginfo(this, tagnum)) <= vlen2(hitorg - gettaginfo(this, nearestbone)))
158 nearestbone = tagnum;
159 }
160 gettaginfo(this, nearestbone); // set gettaginfo_name
161
162 // return if we reached our damage effect limit or damages are disabled
163 // TODO: When the limit is reached, it would be better if the oldest damage was removed instead of not adding a new one
164 if(nearestbone)
165 {
167 return; // allow multiple damages on skeletal models
168 }
169 else
170 {
172 return; // allow a single damage on non-skeletal models
173 }
174
176
177 wep = DEATH_WEAPONOF(type);
178 string effectname = wep.wr_damageeffect_getname ? wep.wr_damageeffect_getname(wep) : strcat("damage_", wep.netname);
179 if((wep.spawnflags & WEP_FLAG_BLEED))
180 {
181 // if this weapon induces bleeding, use the effect name with the proper species prefix (blood type)
182 if((this.isplayermodel & ISPLAYER_MODEL))
183 {
184 string specstr = species_prefix(specnum);
185 effectname = strcat(specstr, effectname);
186 }
187 else { return; } // objects don't bleed
188 }
189
190 int effect = _particleeffectnum(effectname);
191 if (effect < 0)
192 return;
193
194 e = new(damage);
195 setmodel(e, MDL_Null); // necessary to attach and read origin
196 setattachment(e, this, gettaginfo_name); // attach to the given bone
197 e.owner = this;
198 e.cnt = time + life;
199 e.team = _particleeffectnum(effectname);
201 e.nextthink = time;
202 ++this.total_damages;
203}
204
205NET_HANDLE(ENT_CLIENT_DAMAGEINFO, bool isNew)
206{
207 float thedamage, rad, edge, thisdmg;
208 bool hitplayer = false;
209 int species, forcemul;
210 vector force_dir, force, thisforce;
211
212 w_deathtype = ReadShort();
213 w_issilent = (w_deathtype & 0x8000);
214 w_deathtype = (w_deathtype & 0x7FFF);
215
216 w_org = ReadVector();
217
218 thedamage = ReadByte();
219 rad = ReadByte();
220 edge = ReadByte();
221
222 // map [-127, 127] back to [-1, 1]
223 force_dir.x = ReadChar() / BITS(7);
224 force_dir.y = ReadChar() / BITS(7);
225 force_dir.z = ReadChar() / BITS(7);
226 if (force_dir == '0 0 0')
227 force_dir = '0 0 -1';
228
229 int vlen_force = ReadByte() * 4 + 2; // + 2 rounds the value and makes it > 0 so that decals can always work
230 force = force_dir * vlen_force;
231
232 species = ReadByte();
233 bool rad_negative = boolean(species & BIT(7));
234 species = (species & BITS(4));
235
236 int dmg_colors = ReadByte();
237
238 return = true;
239
240 if (!isNew)
241 return;
242
243 forcemul = (rad_negative ? -1 : 1);
244 // team color logic copied from projectiles
245 int tcolor = dmg_colors;
246 if(teamplay)
247 {
248 if(dmg_colors)
249 tcolor = (dmg_colors - 1) * 0x11;
250 else
251 tcolor = 0x00;
252 tcolor |= BIT(10); // RENDER_COLORMAPPED
253 }
254
255 // set globally so weapon impacts can use them
256 particles_colormin = colormapPaletteColor(floor(tcolor / 16), false);
257 particles_colormax = colormapPaletteColor(tcolor % 16, true);
258
259 FOREACH_ENTITY_RADIUS(w_org, rad + MAX_DAMAGEEXTRARADIUS, !it.tag_entity && !is_pure(it), {
260 vector nearest = NearestPointOnBox(it, w_org);
261 if (rad)
262 {
263 thisdmg = ((vlen(nearest - w_org) - bound(MIN_DAMAGEEXTRARADIUS, it.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad);
264 if(thisdmg >= 1)
265 continue;
266 if(thisdmg < 0)
267 thisdmg = 0;
268 if(thedamage)
269 {
270 thisdmg = thedamage + (edge - thedamage) * thisdmg;
271 thisforce = forcemul * vlen_force * (thisdmg / thedamage) * normalize(it.origin - w_org);
272 }
273 else
274 {
275 thisdmg = 0;
276 thisforce = forcemul * vlen_force * normalize(it.origin - w_org);
277 }
278 }
279 else
280 {
281 if(vdist((nearest - w_org), >, bound(MIN_DAMAGEEXTRARADIUS, it.damageextraradius, MAX_DAMAGEEXTRARADIUS)))
282 continue;
283
284 thisdmg = thedamage;
285 thisforce = forcemul * force;
286 }
287
288 if(it.damageforcescale)
289 if(vdist(thisforce, !=, 0))
290 {
291 it.velocity += damage_explosion_calcpush(it.damageforcescale * thisforce, it.velocity, damagepush_speedfactor);
292 UNSET_ONGROUND(it);
293 }
294
295 if(w_issilent)
296 it.silent = 1;
297
298 if(it.event_damage)
299 it.event_damage(it, thisdmg, w_deathtype, w_org, thisforce);
300
301 DamageEffect(it, w_org, thisdmg, w_deathtype, species);
302
303 if(it != csqcplayer && (it.isplayermodel & ISPLAYER_MODEL))
304 hitplayer = true; // this impact damaged another player
305 });
306
308 {
309 traceline(w_org - force_dir * 16, w_org + force_dir * 16, MOVE_NOMONSTERS, NULL);
310 if(trace_plane_normal != '0 0 0')
312 else
313 w_backoff = -1 * normalize(w_org - (w_org + force_dir * 16));
314
315 setorigin(this, w_org + w_backoff * 2); // for sound() calls
316
317 switch(DEATH_ENT(w_deathtype))
318 {
319 case DEATH_VH_CRUSH:
320 break;
321
322 // spiderbot
323 case DEATH_VH_SPID_MINIGUN:
325 pointparticles(EFFECT_SPIDERBOT_MINIGUN_IMPACT, this.origin, w_backoff * 1000, 1);
326 break;
327 case DEATH_VH_SPID_ROCKET:
328 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
329 pointparticles(EFFECT_SPIDERBOT_ROCKET_EXPLODE, this.origin, w_backoff * 1000, 1);
330 break;
331 case DEATH_VH_SPID_DEATH:
332 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_LOW);
333 pointparticles(EFFECT_EXPLOSION_BIG, this.origin, w_backoff * 1000, 1);
334 break;
335
336 case DEATH_VH_WAKI_GUN:
337 sound(this, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_NORM);
338 pointparticles(EFFECT_RACER_IMPACT, this.origin, w_backoff * 1000, 1);
339 break;
340 case DEATH_VH_WAKI_ROCKET:
341 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
342 pointparticles(EFFECT_RACER_ROCKET_EXPLODE, this.origin, w_backoff * 1000, 1);
343 break;
344 case DEATH_VH_WAKI_DEATH:
345 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_LOW);
346 pointparticles(EFFECT_EXPLOSION_BIG, this.origin, w_backoff * 1000, 1);
347 break;
348
349 case DEATH_VH_RAPT_CANNON:
350 sound(this, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_NORM);
351 pointparticles(EFFECT_RAPTOR_CANNON_IMPACT, this.origin, w_backoff * 1000, 1);
352 break;
353 case DEATH_VH_RAPT_FRAGMENT:
354 float i;
355 vector ang, vel;
356 for(i = 1; i < 4; ++i)
357 {
358 vel = normalize(w_org - (w_org + force_dir * 16)) + randomvec() * 128;
359 ang = vectoangles(vel);
360 RaptorCBShellfragToss(w_org, vel, ang + '0 0 1' * (120 * i));
361 }
362 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
363 pointparticles(EFFECT_RAPTOR_BOMB_SPREAD, this.origin, w_backoff * 1000, 1);
364 break;
365 case DEATH_VH_RAPT_BOMB:
366 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
367 pointparticles(EFFECT_RAPTOR_BOMB_IMPACT, this.origin, w_backoff * 1000, 1);
368 break;
369 case DEATH_VH_RAPT_DEATH:
370 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_LOW);
371 pointparticles(EFFECT_EXPLOSION_BIG, this.origin, w_backoff * 1000, 1);
372 break;
373 case DEATH_VH_BUMB_GUN:
374 sound(this, CH_SHOTS, SND_VEH_BUMBLEBEE_IMPACT, VOL_BASE, ATTEN_NORM);
375 pointparticles(EFFECT_BIGPLASMA_IMPACT, this.origin, w_backoff * 1000, 1);
376 break;
377 }
378 }
379
380
382 {
383 traceline(w_org - force_dir * 16, w_org + force_dir * 16, MOVE_NOMONSTERS, NULL);
384 if(trace_plane_normal != '0 0 0')
386 else
387 w_backoff = -1 * normalize(w_org - (w_org + force_dir * 16));
388
389 setorigin(this, w_org + w_backoff * 2); // for sound() calls
390
391 switch(DEATH_ENT(w_deathtype))
392 {
393 case DEATH_TURRET_EWHEEL:
394 sound(this, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_LOW);
395 pointparticles(EFFECT_BLASTER_IMPACT, this.origin, w_backoff * 1000, 1);
396 break;
397
398 case DEATH_TURRET_FLAC:
399 pointparticles(EFFECT_HAGAR_EXPLODE, w_org, '0 0 0', 1);
401 break;
402
403 case DEATH_TURRET_MLRS:
404 case DEATH_TURRET_HK:
405 case DEATH_TURRET_WALK_ROCKET:
406 case DEATH_TURRET_HELLION:
407 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_LOW);
408 pointparticles(EFFECT_ROCKET_EXPLODE, this.origin, w_backoff * 1000, 1);
409 break;
410
411 case DEATH_TURRET_MACHINEGUN:
412 case DEATH_TURRET_WALK_GUN:
414 pointparticles(EFFECT_MACHINEGUN_IMPACT, this.origin, w_backoff * 1000, 1);
415 break;
416
417 case DEATH_TURRET_PLASMA:
418 sound(this, CH_SHOTS, SND_TUR_PLASMA_IMPACT, VOL_BASE, ATTEN_LOW);
419 pointparticles(EFFECT_ELECTRO_IMPACT, this.origin, w_backoff * 1000, 1);
420 break;
421
422 case DEATH_TURRET_WALK_MELEE:
424 pointparticles(EFFECT_TE_SPARK, this.origin, w_backoff * 1000, 1);
425 break;
426
427 case DEATH_TURRET_PHASER:
428 break;
429
430 case DEATH_TURRET_TESLA:
431 te_smallflash(this.origin);
432 break;
433 }
434 }
435
436 MUTATOR_CALLHOOK(DamageInfo, this, w_deathtype, w_org);
437
438 // TODO spawn particle effects and sounds based on w_deathtype
440 if(!hitplayer || rad) // don't show ground impacts for hitscan weapons if a player was hit
441 {
443 w_random = prandom();
444
445 // this traceline usually starts in solid when a hitscan shot hits a surface with a very small angle
446 // if so, try another traceline starting further back (may still start in solid but only with extremely small angles)
447 traceline(w_org - force_dir * 16, w_org + force_dir * 16, MOVE_NOMONSTERS, NULL);
449 traceline(w_org - force_dir * 40, w_org + force_dir * 16, MOVE_NOMONSTERS, NULL);
450 if(trace_fraction < 1)
452 else
453 w_backoff = -force_dir;
454 setorigin(this, w_org + w_backoff * 2); // for sound() calls
455
457 {
458 if(!MUTATOR_CALLHOOK(Weapon_ImpactEffect, hitwep, this))
459 hitwep.wr_impacteffect(hitwep, this);
460 }
461 }
462}
463
464#endif
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition bits.qh:8
#define BITS(n)
Definition bits.qh:9
#define boolean(value)
Definition bool.qh:9
float dmg_force
Definition breakable.qc:15
float dmg
Definition breakable.qc:12
float dmg_edge
Definition breakable.qc:13
float dmg_radius
Definition breakable.qc:14
vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor)
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
entity csqcplayer
Definition cl_player.qh:26
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition weapon.qh:42
virtual void wr_impacteffect()
(CLIENT) impact effect for weapon explosion
Definition weapon.qh:132
float cnt
Definition powerups.qc:24
entity owner
Definition main.qh:87
int team
Definition main.qh:188
float damagepush_speedfactor
Definition main.qh:161
#define colormapPaletteColor(c, isPants)
Definition color.qh:5
#define setmodel(this, m)
Definition model.qh:26
bool autocvar_cl_gentle
Definition util.qh:236
#define FOR_EACH_TAG(v)
Definition util.qh:216
const int SPECIES_ANIMAL
Definition constants.qh:25
const int SPECIES_ROBOT_SOLID
Definition constants.qh:23
const int SPECIES_ROBOT_RUSTY
Definition constants.qh:26
const int SPECIES_RESERVED
Definition constants.qh:28
const int SPECIES_ROBOT_SHINY
Definition constants.qh:27
const int SPECIES_ALIEN
Definition constants.qh:24
const int SPECIES_HUMAN
Definition constants.qh:22
float Q3SURFACEFLAG_SKY
const float MOVE_NOMONSTERS
float drawmask
float modelindex
vector particles_colormin
vector velocity
string gettaginfo_name
float time
float trace_startsolid
float nextthink
float trace_dphitq3surfaceflags
float colormap
vector particles_colormax
vector origin
float trace_fraction
vector trace_plane_normal
entity tag_entity
int isplayermodel
string species_prefix(int specnum)
void DamageEffect_Think(entity this)
bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf)
int state
void DamageEffect(entity this, vector hitorg, float thedamage, int type, int specnum)
bool silent
int total_damages
number of effects which currently are attached to a player
void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner)
vector w_org
float autocvar_cl_damageeffect_ticrate
const float MAX_DAMAGEEXTRARADIUS
float autocvar_cl_damageeffect_lifetime
bool autocvar_cl_damageeffect_distribute
float autocvar_cl_damageeffect_lifetime_max
int w_deathtype
int autocvar_cl_damageeffect
float autocvar_cl_damageeffect_bones
float autocvar_cl_damageeffect_lifetime_min
const float MIN_DAMAGEEXTRARADIUS
float w_random
vector w_backoff
float w_issilent
#define DEATH_ENT(t)
Definition all.qh:43
#define DEATH_ISTURRET(t)
Definition all.qh:45
#define DEATH_ISSPECIAL(t)
Definition all.qh:41
#define DEATH_ISVEHICLE(t)
Definition all.qh:44
#define DEATH_WEAPONOF(t)
Definition all.qh:47
#define pointparticles(effect, org, vel, howmany)
Definition effect.qh:7
WriteByte(chan, ent.angles.y/DEC_FACTOR)
#define FOREACH_ENTITY_RADIUS(org, dist, cond, body)
Definition iter.qh:160
const int ISPLAYER_LOCAL
Definition common.qh:58
const int ISPLAYER_MODEL
Definition common.qh:56
#define NET_HANDLE(id, param)
Definition net.qh:15
const int MSG_ENTITY
Definition net.qh:156
#define ReadVector()
Definition net.qh:349
#define WriteHeader(to, id)
Definition net.qh:265
#define REGISTER_NET_LINKED(id)
Definition net.qh:91
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:167
int ReadByte()
float bound(float min, float value, float max)
void WriteChar(float data, float dest, float desto)
float vlen(vector v)
void WriteShort(float data, float dest, float desto)
vector vectoangles(vector v)
vector randomvec(void)
float rint(float f)
vector normalize(vector v)
float floor(float f)
float MSG_BROADCAST
Definition menudefs.qc:55
float max(float f,...)
#define UNSET_ONGROUND(s)
Definition movetypes.qh:18
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define is_pure(e)
Definition oo.qh:16
#define new_pure(class)
purely logical entities (not linked to the area grid)
Definition oo.qh:66
#define NULL
Definition post.qh:14
#define gettaginfo
Definition post.qh:32
float prandom()
Predictable random number generator (not seeded yet).
Definition random.qc:108
void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
#define setthink(e, f)
vector
Definition self.qh:96
vector org
Definition self.qh:96
vector vector ang
Definition self.qh:96
float species
Definition main.qh:47
int projectiledeathtype
Definition common.qh:21
const float VOL_BASE
Definition sound.qh:36
const int CH_SHOTS
Definition sound.qh:14
const float ATTEN_LOW
Definition sound.qh:29
const float ATTEN_NORM
Definition sound.qh:30
#define sound(e, c, s, v, a)
Definition sound.qh:52
Sound SND_RIC_RANDOM()
Definition all.inc:33
Sound SND_FLACEXP_RANDOM()
Definition all.inc:149
bool sound_allowed(int to, entity e)
Definition all.qc:9
bool teamplay
Definition teams.qh:59
#define vlen2(v)
Definition vector.qh:4
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt().
Definition vector.qh:8
ERASEABLE vector NearestPointOnBox(entity box, vector org)
Definition vector.qh:187
#define vec3(_x, _y, _z)
Definition vector.qh:100
int autocvar_chase_active
Definition view.qh:17
int autocvar_cl_gentle_damage
Definition view.qh:19
const int WEP_FLAG_BLEED
Definition weapon.qh:267