Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
player.qh File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void CopyBody (entity this, float keepvelocity)
void CopyBody_Think (entity this)
void player_anim (entity this)
void player_setupanimsformodel (entity this)
void PlayerCorpseDamage (entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
void PlayerDamage (entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
bool PlayerHeal (entity targ, entity inflictor, float amount, float limit)
void precache_all_playermodels (string pattern)
 STATIC_INIT (g_clones)
 void (entity this) CopyBody_think

Variables

float autocvar_g_spawnshield_blockdamage
float autocvar_g_spawnshieldtime
bool autocvar_sv_defaultcharacter
bool autocvar_sv_defaultcharacterskin
string autocvar_sv_defaultplayercolors
string autocvar_sv_defaultplayermodel
string autocvar_sv_defaultplayermodel_blue
string autocvar_sv_defaultplayermodel_pink
string autocvar_sv_defaultplayermodel_red
string autocvar_sv_defaultplayermodel_yellow
int autocvar_sv_defaultplayerskin
int autocvar_sv_defaultplayerskin_blue
int autocvar_sv_defaultplayerskin_pink
int autocvar_sv_defaultplayerskin_red
int autocvar_sv_defaultplayerskin_yellow
float autocvar_sv_gibhealth
bool autocvar_sv_precacheplayermodels
float CopyBody_nextthink
IntrusiveList g_clones
bool istypefrag
entity pusher
float pushltime
float score_frame_dmg
float score_frame_dmgtaken

Function Documentation

◆ CopyBody()

void CopyBody ( entity this,
float keepvelocity )

Definition at line 64 of file player.qc.

65{
66 if (this.effects & EF_NODRAW)
67 return;
68 entity clone = new(body);
69 clone.enemy = this;
70 clone.lip = this.lip;
71 clone.colormap = this.colormap;
72 clone.iscreature = this.iscreature;
73 clone.teleportable = this.teleportable;
74 clone.damagedbycontents = this.damagedbycontents;
75 if(clone.damagedbycontents)
77 clone.angles = this.angles;
78 clone.v_angle = this.v_angle;
79 clone.avelocity = this.avelocity;
80 clone.damageforcescale = this.damageforcescale;
81 clone.effects = this.effects;
82 clone.glowmod = this.glowmod;
83 clone.event_damage = this.event_damage;
84 clone.event_heal = this.event_heal;
85 clone.anim_state = this.anim_state;
86 clone.anim_time = this.anim_time;
87 clone.anim_lower_action = this.anim_lower_action;
88 clone.anim_lower_time = this.anim_lower_time;
89 clone.anim_upper_action = this.anim_upper_action;
90 clone.anim_upper_time = this.anim_upper_time;
91 clone.anim_implicit_state = this.anim_implicit_state;
92 clone.anim_implicit_time = this.anim_implicit_time;
93 clone.anim_lower_implicit_action = this.anim_lower_implicit_action;
94 clone.anim_lower_implicit_time = this.anim_lower_implicit_time;
95 clone.anim_upper_implicit_action = this.anim_upper_implicit_action;
96 clone.anim_upper_implicit_time = this.anim_upper_implicit_time;
97 clone.dphitcontentsmask = this.dphitcontentsmask;
98 clone.death_time = this.death_time;
99 clone.pain_finished = this.pain_finished;
100 SetResourceExplicit(clone, RES_HEALTH, GetResource(this, RES_HEALTH));
102 clone.armortype = this.armortype;
103 clone.model = this.model;
104 clone.modelindex = this.modelindex;
105 clone.skin = this.skin;
106 clone.species = this.species;
107 clone.move_qcphysics = false; // don't run gamecode logic on clones, too many
108 set_movetype(clone, this.move_movetype);
109 clone.solid = this.solid;
110 clone.takedamage = this.takedamage;
111 setcefc(clone, getcefc(this));
112 clone.uncustomizeentityforclient = this.uncustomizeentityforclient;
113 clone.uncustomizeentityforclient_set = this.uncustomizeentityforclient_set;
114 if (keepvelocity == 1)
115 clone.velocity = this.velocity;
116 clone.oldvelocity = clone.velocity;
117 clone.alpha = this.alpha;
118 clone.fade_time = this.fade_time;
119 clone.fade_rate = this.fade_rate;
120 //clone.weapon = this.weapon;
121 setorigin(clone, this.origin);
122 setsize(clone, this.mins, this.maxs);
123 clone.reset = SUB_Remove;
124 clone._ps = this._ps;
125
126 Drag_MoveDrag(this, clone);
127
128 if(clone.colormap <= maxclients && clone.colormap > 0)
129 clone.colormap = 1024 + this.clientcolors;
130 clone.sv_entnum = etof(this); // sent to CSQC for color mapping purposes
131
132 CSQCMODEL_AUTOINIT(clone);
133 clone.CopyBody_nextthink = this.nextthink;
134 clone.CopyBody_think = getthink(this);
135 clone.nextthink = time;
136 setthink(clone, CopyBody_Think);
137 // "bake" the current animation frame for clones (they don't get clientside animation)
140
141 IL_PUSH(g_clones, clone);
142
143 MUTATOR_CALLHOOK(CopyBody, this, clone, keepvelocity);
144}
float frame1time
start time of framegroup animation
Definition anim.qh:22
float frame2time
start time of framegroup animation
Definition anim.qh:24
float frame2
secondary framegroup animation (strength = lerpfrac)
Definition anim.qh:8
float frame
primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4)
Definition anim.qh:6
void animdecide_load_if_needed(entity e)
Definition animdecide.qc:53
void animdecide_setframes(entity e, float support_blending,.float fld_frame,.float fld_frame1time,.float fld_frame2,.float fld_frame2time)
float anim_lower_implicit_time
float anim_lower_time
float anim_implicit_time
float anim_upper_implicit_action
float anim_lower_implicit_action
float anim_upper_time
int anim_state
float anim_upper_action
float anim_time
int anim_implicit_state
float anim_lower_action
float anim_upper_implicit_time
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
void Drag_MoveDrag(entity from, entity to)
Definition cheats.qc:1006
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float pain_finished
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
float alpha
Definition items.qc:13
vector v_angle
Definition player.qh:237
float maxclients
float modelindex
vector avelocity
vector mins
vector velocity
float effects
float skin
float time
vector maxs
float nextthink
float colormap
vector origin
const float EF_NODRAW
float dphitcontentsmask
vector glowmod
float death_time
#define CSQCMODEL_AUTOINIT(e)
float damagedbycontents
Definition damage.qh:45
IntrusiveList g_damagedbycontents
Definition damage.qh:135
float damageforcescale
void SUB_Remove(entity this)
Remove entity.
Definition defer.qh:13
RES_ARMOR
Definition ent_cs.qc:130
ent angles
Definition ent_cs.qc:121
model
Definition ent_cs.qc:139
clientcolors
Definition ent_cs.qc:147
solid
Definition ent_cs.qc:165
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
float uncustomizeentityforclient_set
Definition net.qh:157
#define etof(e)
Definition misc.qh:25
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
float move_movetype
Definition movetypes.qh:76
float armortype
Definition progsdefs.qc:178
fade_rate
Definition projectile.qh:14
#define setthink(e, f)
#define getthink(e)
#define getcefc(e)
#define setcefc(e, f)
float species
Definition main.qh:47
bool iscreature
Definition main.qh:46
void CopyBody_Think(entity this)
Definition player.qc:50
void CopyBody(entity this, float keepvelocity)
Definition player.qc:64
IntrusiveList g_clones
Definition player.qh:45
float fade_time
Definition common.qh:23
PlayerState _ps
Definition state.qh:17
float lip
Definition subs.qh:40
float takedamage
Definition subs.qh:78
float teleportable

References _ps, alpha, angles, anim_implicit_state, anim_implicit_time, anim_lower_action, anim_lower_implicit_action, anim_lower_implicit_time, anim_lower_time, anim_state, anim_time, anim_upper_action, anim_upper_implicit_action, anim_upper_implicit_time, anim_upper_time, animdecide_load_if_needed(), animdecide_setframes(), armortype, avelocity, clientcolors, colormap, CopyBody(), CopyBody_Think(), CSQCMODEL_AUTOINIT, damagedbycontents, damageforcescale, death_time, dphitcontentsmask, Drag_MoveDrag(), EF_NODRAW, effects, entity(), etof, fade_rate, fade_time, frame, frame1time, frame2, frame2time, g_clones, g_damagedbycontents, getcefc, GetResource(), getthink, glowmod, IL_PUSH(), iscreature, lip, maxclients, maxs, mins, model, modelindex, move_movetype, MUTATOR_CALLHOOK, nextthink, origin, pain_finished, RES_ARMOR, set_movetype(), setcefc, SetResourceExplicit(), setthink, skin, solid, species, SUB_Remove(), takedamage, teleportable, time, uncustomizeentityforclient_set, v_angle, and velocity.

Referenced by CheatImpulse(), CopyBody(), MUTATOR_HOOKABLE(), MUTATOR_HOOKFUNCTION(), and respawn().

◆ CopyBody_Think()

void CopyBody_Think ( entity this)

Definition at line 50 of file player.qc.

51{
53 {
54 this.CopyBody_think(this);
55 if(wasfreed(this))
56 return;
57 this.CopyBody_nextthink = this.nextthink;
58 this.CopyBody_think = getthink(this);
60 }
62 this.nextthink = time;
63}
#define CSQCMODEL_AUTOUPDATE(e)
float CopyBody_nextthink
Definition player.qh:28

References CopyBody_nextthink, CopyBody_Think(), CSQCMODEL_AUTOUPDATE, entity(), getthink, nextthink, setthink, and time.

Referenced by CopyBody(), CopyBody_Think(), and PlayerDamage().

◆ player_anim()

void player_anim ( entity this)

Definition at line 153 of file player.qc.

154{
155 int deadbits = (this.anim_state & (ANIMSTATE_DEAD1 | ANIMSTATE_DEAD2));
156 if(IS_DEAD(this)) {
157 if (!deadbits) {
158 // Decide on which death animation to use.
159 if(random() < 0.5)
160 deadbits = ANIMSTATE_DEAD1;
161 else
162 deadbits = ANIMSTATE_DEAD2;
163 }
164 } else {
165 // Clear a previous death animation.
166 deadbits = 0;
167 }
168 int animbits = deadbits;
169 if(StatusEffects_active(STATUSEFFECT_Frozen, this))
170 animbits |= ANIMSTATE_FROZEN;
172 animbits |= ANIMSTATE_FOLLOW;
173 if(IS_DUCKED(this))
174 animbits |= ANIMSTATE_DUCK;
175
176 MUTATOR_CALLHOOK(PlayerAnim, this, animbits);
177 animbits = M_ARGV(1, int);
178
179 animdecide_setstate(this, animbits, false);
181}
void animdecide_setimplicitstate(entity e, float onground)
void animdecide_setstate(entity e, int newstate, float restart)
const int ANIMSTATE_FROZEN
const int ANIMSTATE_DEAD1
const int ANIMSTATE_FOLLOW
const int ANIMSTATE_DEAD2
const int ANIMSTATE_DUCK
#define M_ARGV(x, type)
Definition events.qh:17
#define IS_DEAD(s)
Definition player.qh:245
#define IS_DUCKED(s)
Definition player.qh:210
float random(void)
const int MOVETYPE_FOLLOW
Definition movetypes.qh:141
#define IS_ONGROUND(s)
Definition movetypes.qh:16
bool StatusEffects_active(StatusEffect this, entity actor)

References anim_state, animdecide_setimplicitstate(), animdecide_setstate(), ANIMSTATE_DEAD1, ANIMSTATE_DEAD2, ANIMSTATE_DUCK, ANIMSTATE_FOLLOW, ANIMSTATE_FROZEN, entity(), IS_DEAD, IS_DUCKED, IS_ONGROUND, M_ARGV, move_movetype, MOVETYPE_FOLLOW, MUTATOR_CALLHOOK, random(), and StatusEffects_active().

Referenced by PlayerThink().

◆ player_setupanimsformodel()

void player_setupanimsformodel ( entity this)

Definition at line 146 of file player.qc.

147{
148 // load animation info
150 animdecide_setstate(this, 0, false);
151}

References animdecide_load_if_needed(), animdecide_setstate(), and entity().

Referenced by setplayermodel().

◆ PlayerCorpseDamage()

void PlayerCorpseDamage ( entity this,
entity inflictor,
entity attacker,
float damage,
int deathtype,
.entity weaponentity,
vector hitloc,
vector force )

Definition at line 183 of file player.qc.

184{
185 float take, save;
186 vector v;
187 Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, this, attacker);
188
190 take = v.x;
191 save = v.y;
192
193 if(sound_allowed(MSG_BROADCAST, attacker))
194 {
195 if (save > 10)
196 sound (this, CH_SHOTS, SND_ARMORIMPACT, VOL_BASE, ATTEN_NORM);
197 else if (take > 30)
198 sound (this, CH_SHOTS, SND_BODYIMPACT2, VOL_BASE, ATTEN_NORM);
199 else if (take > 10)
200 sound (this, CH_SHOTS, SND_BODYIMPACT1, VOL_BASE, ATTEN_NORM);
201 }
202
203 if (take > 50)
204 Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, this, attacker);
205 if (take > 100)
206 Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, this, attacker);
207
208 TakeResource(this, RES_ARMOR, save);
209 TakeResource(this, RES_HEALTH, take);
210 // pause regeneration for 5 seconds
212
213 this.dmg_save = this.dmg_save + save;//max(save - 10, 0);
214 this.dmg_take = this.dmg_take + take;//max(take - 10, 0);
215 this.dmg_inflictor = inflictor;
216
217 if (GetResource(this, RES_HEALTH) <= -autocvar_sv_gibhealth && this.alpha >= 0)
218 {
219 // don't use any animations as a gib
220 this.frame = 0;
221 // view just above the floor
222 this.view_ofs = '0 0 4';
223
224 Violence_GibSplash(this, 1, 1, attacker);
225 this.alpha = -1;
226 this.solid = SOLID_NOT; // restore later
227 this.takedamage = DAMAGE_NO; // restore later
228 if(this.damagedbycontents)
230 this.damagedbycontents = false;
231 }
232}
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
vector healtharmor_applydamage(float a, float armorblock, int deathtype, float damage)
Definition util.qc:1313
const float SOLID_NOT
float autocvar_g_balance_armor_blockpercent
Definition damage.qh:21
void Violence_GibSplash(entity source, float type, float amount, entity attacker)
Definition gibs.qc:53
void Violence_GibSplash_At(vector org, vector dir, float type, float amount, entity gibowner, entity attacker)
Definition gibs.qc:23
ERASEABLE void IL_REMOVE(IntrusiveList this, entity it)
Remove any element, anywhere in the list.
float bound(float min, float value, float max)
float MSG_BROADCAST
Definition menudefs.qc:55
float max(float f,...)
vector view_ofs
Definition progsdefs.qc:151
float dmg_save
Definition progsdefs.qc:199
entity dmg_inflictor
Definition progsdefs.qc:200
vector
Definition self.qh:92
float pauseregen_finished
Definition client.qh:337
float autocvar_sv_gibhealth
Definition player.qh:19
const float VOL_BASE
Definition sound.qh:36
const int CH_SHOTS
Definition sound.qh:14
const float ATTEN_NORM
Definition sound.qh:30
#define sound(e, c, s, v, a)
Definition sound.qh:52
bool sound_allowed(int to, entity e)
Definition all.qc:9
const int DAMAGE_NO
Definition subs.qh:79
float autocvar_g_balance_pause_health_regen
float dmg_take
Definition view.qh:123

References alpha, ATTEN_NORM, autocvar_g_balance_armor_blockpercent, autocvar_g_balance_pause_health_regen, autocvar_sv_gibhealth, bound(), CH_SHOTS, DAMAGE_NO, damagedbycontents, dmg_inflictor, dmg_save, dmg_take, entity(), frame, g_damagedbycontents, GetResource(), healtharmor_applydamage(), IL_REMOVE(), max(), MSG_BROADCAST, pauseregen_finished, RES_ARMOR, solid, SOLID_NOT, sound, sound_allowed(), takedamage, TakeResource(), time, vector, view_ofs, Violence_GibSplash(), Violence_GibSplash_At(), and VOL_BASE.

Referenced by PlayerDamage().

◆ PlayerDamage()

void PlayerDamage ( entity this,
entity inflictor,
entity attacker,
float damage,
int deathtype,
.entity weaponentity,
vector hitloc,
vector force )

Definition at line 234 of file player.qc.

235{
236 vector v;
237 float initial_health = max(GetResource(this, RES_HEALTH), 0);
238 float initial_armor = max(GetResource(this, RES_ARMOR), 0);
239 float take = 0, save = 0;
240
241 if (damage)
242 {
243 if(!DEATH_ISSPECIAL(deathtype))
244 {
245 damage *= Handicap_GetTotalHandicap(this, true);
246 if (this != attacker && IS_PLAYER(attacker))
247 {
248 damage /= Handicap_GetTotalHandicap(attacker, false);
249 }
250 }
251
252 if (StatusEffects_active(STATUSEFFECT_SpawnShield, this) && autocvar_g_spawnshield_blockdamage < 1)
253 damage *= 1 - bound(0, autocvar_g_spawnshield_blockdamage, 1);
254
255 if(deathtype & HITTYPE_SOUND) // sound based attacks cause bleeding from the ears
256 {
257 vector ear1, ear2;
258 vector d;
259 float f;
260 ear1 = this.origin;
261 ear1_z += 0.125 * this.view_ofs.z + 0.875 * this.maxs.z; // 7/8
262 ear2 = ear1;
263 makevectors(this.angles);
264 ear1 += v_right * -10;
265 ear2 += v_right * +10;
266 d = inflictor.origin - this.origin;
267 if (d)
268 f = (d * v_right) / vlen(d); // this is cos of angle of d and v_right!
269 else
270 f = 0; // Assum ecenter.
271 force = v_right * vlen(force);
272 Violence_GibSplash_At(ear1, force * -1, 2, bound(0, damage, 25) / 2 * (0.5 - 0.5 * f), this, attacker);
273 Violence_GibSplash_At(ear2, force, 2, bound(0, damage, 25) / 2 * (0.5 + 0.5 * f), this, attacker);
274 if(f > 0)
275 {
276 hitloc = ear1;
277 force = force * -1;
278 }
279 else
280 {
281 hitloc = ear2;
282 // force is already good
283 }
284 }
285 else
286 Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, this, attacker);
287
289 take = v.x;
290 save = v.y;
291 }
292
293 if(attacker == this)
294 {
295 // don't reset pushltime for self damage as it may be an attempt to
296 // escape a lava pit or similar
297 //this.pushltime = 0;
298 this.istypefrag = 0;
299 }
300 else if(IS_PLAYER(attacker))
301 {
302 this.pusher = attacker;
305 }
306 else if(time < this.pushltime)
307 {
308 attacker = this.pusher;
309 this.pushltime = max(this.pushltime, time + 0.6);
310 }
311 else if(IS_MONSTER(attacker) && IS_PLAYER(attacker.realowner))
312 {
313 attacker = attacker.realowner;
314 this.istypefrag = 0;
315 }
316 else
317 {
318 this.pushltime = 0;
319 this.istypefrag = 0;
320 }
321
322 MUTATOR_CALLHOOK(PlayerDamage_SplitHealthArmor, inflictor, attacker, this, force, take, save, deathtype, damage);
323 take = bound(0, M_ARGV(4, float), GetResource(this, RES_HEALTH));
324 save = bound(0, M_ARGV(5, float), GetResource(this, RES_ARMOR));
325 float excess = max(0, damage - take - save);
326
327 if(sound_allowed(MSG_BROADCAST, attacker))
328 {
329 if (save > 10 && (initial_health - take) > 0) // don't play armor sound if the attack is fatal
330 sound (this, CH_SHOTS, SND_ARMORIMPACT, VOL_BASE, ATTEN_NORM);
331 else if (take > 30)
332 sound (this, CH_SHOTS, SND_BODYIMPACT2, VOL_BASE, ATTEN_NORM);
333 else if (take > 10)
334 sound (this, CH_SHOTS, SND_BODYIMPACT1, VOL_BASE, ATTEN_NORM); // FIXME possibly remove them?
335 }
336
337 if (take > 50)
338 Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, this, attacker);
339 if (take > 100)
340 Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, this, attacker);
341
342 if (!StatusEffects_active(STATUSEFFECT_SpawnShield, this) || autocvar_g_spawnshield_blockdamage < 1)
343 {
344 if (!(this.flags & FL_GODMODE))
345 {
346 TakeResource(this, RES_ARMOR, save);
347 TakeResource(this, RES_HEALTH, take);
348 // pause regeneration for 5 seconds
349 if(take)
351
352 if (time > this.pain_finished && !STAT(FROZEN, this) && !StatusEffects_active(STATUSEFFECT_Frozen, this)) // Don't switch pain sequences like crazy
353 {
354 this.pain_finished = time + 0.5; //Supajoe
355
356 if(autocvar_sv_gentle < 1) {
357 if(this.classname != "body") // pain anim is BORKED on our ZYMs, FIXME remove this once we have good models
358 {
359 if (!this.animstate_override)
360 {
361 if (random() > 0.5)
363 else
365 }
366 }
367 float myhp = GetResource(this, RES_HEALTH);
368 if(myhp > 1)
369 if(myhp < 25 || !(DEATH_WEAPONOF(deathtype).spawnflags & WEP_FLAG_CANCLIMB) || take > 20 || attacker != this)
370 if(sound_allowed(MSG_BROADCAST, attacker))
371 // exclude pain sounds for laserjumps as long as you aren't REALLY low on health and would die of the next two
372 {
373 if(deathtype == DEATH_FALL.m_id)
374 PlayerSound(this, playersound_fall, CH_PAIN, VOL_BASE, VOICETYPE_PLAYERSOUND);
375 else if(myhp > 75)
376 PlayerSound(this, playersound_pain100, CH_PAIN, VOL_BASE, VOICETYPE_PLAYERSOUND);
377 else if(myhp > 50)
378 PlayerSound(this, playersound_pain75, CH_PAIN, VOL_BASE, VOICETYPE_PLAYERSOUND);
379 else if(myhp > 25)
380 PlayerSound(this, playersound_pain50, CH_PAIN, VOL_BASE, VOICETYPE_PLAYERSOUND);
381 else
382 PlayerSound(this, playersound_pain25, CH_PAIN, VOL_BASE, VOICETYPE_PLAYERSOUND);
383 }
384 }
385 }
386
387 // throw off bot aim temporarily
388 float shake;
389 if(IS_BOT_CLIENT(this) && GetResource(this, RES_HEALTH) >= 1)
390 {
391 shake = damage * 5 / (bound(0,skill,100) + 1);
392 this.v_angle_x = this.v_angle.x + (random() * 2 - 1) * shake;
393 this.v_angle_y = this.v_angle.y + (random() * 2 - 1) * shake;
394 this.v_angle_x = bound(-90, this.v_angle.x, 90);
395 }
396 }
397 else
398 this.max_armorvalue += (save + take);
399 }
400 this.dmg_save = this.dmg_save + save;//max(save - 10, 0);
401 this.dmg_take = this.dmg_take + take;//max(take - 10, 0);
402 this.dmg_inflictor = inflictor;
403
404 bool abot = (IS_BOT_CLIENT(attacker));
405 bool vbot = (IS_BOT_CLIENT(this));
406
407 bool valid_damage_for_weaponstats = false;
408 Weapon awep = WEP_Null;
409
411 if(vbot || IS_REAL_CLIENT(this))
412 if(abot || IS_REAL_CLIENT(attacker))
413 if(attacker && this != attacker)
414 if (DIFF_TEAM(this, attacker) && (!STAT(FROZEN, this) || this.freeze_time > time))
415 {
416 if(DEATH_ISSPECIAL(deathtype))
417 awep = attacker.(weaponentity).m_weapon;
418 else
419 awep = DEATH_WEAPONOF(deathtype);
420 valid_damage_for_weaponstats = true;
421 }
422
423 float dh = initial_health - max(GetResource(this, RES_HEALTH), 0); // health difference
424 float da = initial_armor - max(GetResource(this, RES_ARMOR), 0); // armor difference
425 if(valid_damage_for_weaponstats)
426 {
427 WeaponStats_LogDamage(awep.m_id, abot, this.(weaponentity).m_weapon.m_id, vbot, dh + da);
428 }
429
430 bool forbid_logging_damage = MUTATOR_CALLHOOK(PlayerDamaged, attacker, this, dh, da, hitloc, deathtype, damage);
431
432 if ((dh || da) && !forbid_logging_damage)
433 {
434 float realdmg = damage - excess;
435 if ((this != attacker || deathtype == DEATH_KILL.m_id) && realdmg
437 {
438 // accumulate damage, it will be logged later in this frame
439 if (IS_PLAYER(attacker) && DIFF_TEAM(attacker, this) && deathtype != DEATH_KILL.m_id)
440 {
441 if (accuracy_isgooddamage(attacker, this))
442 accuracy_add(attacker, awep, 0, 0, realdmg); // add to real
443 attacker.score_frame_dmg += realdmg;
444 }
445 if (IS_PLAYER(this))
446 this.score_frame_dmgtaken += realdmg;
447 }
448 }
449
450 if (GetResource(this, RES_HEALTH) < 1)
451 {
452 bool defer_ClientKill_Now_TeamChange = false;
453
454 if(this.alivetime_start)
455 {
457 this.alivetime_start = 0;
458 }
459
460 if(valid_damage_for_weaponstats)
461 WeaponStats_LogKill(awep.m_id, abot, this.(weaponentity).m_weapon.m_id, vbot);
462
463 if(autocvar_sv_gentle < 1)
464 if(sound_allowed(MSG_BROADCAST, attacker))
465 {
466 if(deathtype == DEATH_DROWN.m_id)
467 PlayerSound(this, playersound_drown, CH_PAIN, VOL_BASE, VOICETYPE_PLAYERSOUND);
468 else
469 PlayerSound(this, playersound_death, CH_PAIN, VOL_BASE, VOICETYPE_PLAYERSOUND);
470 }
471
472 // get rid of kill indicator
473 if(this.killindicator)
474 {
475 delete(this.killindicator);
476 this.killindicator = NULL;
478 defer_ClientKill_Now_TeamChange = true;
479
480 if(this.classname == "body")
481 if(deathtype == DEATH_KILL.m_id)
482 {
483 // for the lemmings fans, a small harmless explosion
484 Send_Effect(EFFECT_ROCKET_EXPLODE, this.origin, '0 0 0', 1);
485 }
486 }
487
488 // print an obituary message
489 if(this.classname != "body")
490 Obituary(attacker, inflictor, this, deathtype, weaponentity);
491
492 // increment frag counter for used weapon type
493 Weapon w = DEATH_WEAPONOF(deathtype);
494 if(w != WEP_Null && accuracy_isgooddamage(attacker, this))
495 CS(attacker).accuracy.(accuracy_frags[w.m_id-1]) += 1;
496
497 this.respawn_time = 0;
498 MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, this, deathtype, damage);
499 damage = M_ARGV(4, float);
500 excess = max(0, damage - take - save);
501
502 //Weapon wep = this.(weaponentity).m_weapon;
503 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
504 {
505 .entity went = weaponentities[slot];
506 if(!this.(went))
507 continue; // TODO: clones have no weapon, but we don't want to have to check this all the time
508 Weapon wep = this.(went).m_weapon;
509 wep.wr_playerdeath(wep, this, went);
510 }
511
513
515
516 this.fixangle = true;
517
518 if(defer_ClientKill_Now_TeamChange)
519 ClientKill_Now_TeamChange(this); // can turn player into spectator
520
521 // player could have been miraculously resuscitated ;)
522 if(GetResource(this, RES_HEALTH) >= 1 || !(IS_PLAYER(this) || this.classname == "body"))
523 return;
524
525 if (!this.respawn_time) // can be set in the mutator hook PlayerDies
527
528 // when we get here, player actually dies
529
530 // clear waypoints
532 // throw a weapon
533 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
534 {
535 .entity went = weaponentities[slot];
536 SpawnThrownWeapon(this, this.origin + (this.mins + this.maxs) * 0.5, this.(went).m_weapon, went);
537 }
538
539 // become fully visible
541 // make the corpse upright (not tilted)
542 this.angles_x = 0;
543 this.angles_z = 0;
544 // don't spin
545 this.avelocity = '0 0 0';
546 // view from the floor
547 this.view_ofs = '0 0 -8';
549 {
550 // don't toss the corpse in this case, it can get stuck in solid (causing low fps)
551 // or fall indefinitely into the void if out of the map
552 this.velocity = '0 0 0';
553 }
554 else
555 {
556 // toss the corpse
558 }
559 // shootable corpse
560 this.solid = SOLID_CORPSE;
561 PS(this).ballistics_density = autocvar_g_ballistics_density_corpse;
562 // don't stick to the floor
563 UNSET_ONGROUND(this);
564 // dying animation
565 this.deadflag = DEAD_DYING;
566 // don't play teleportation sounds
568
569 STAT(AIR_FINISHED, this) = 0;
570
571 this.death_time = time;
572 if (random() < 0.5)
574 else
576
577 // set damage function to corpse damage
578 this.event_damage = PlayerCorpseDamage;
579 this.event_heal = func_null;
580 // call the corpse damage function just in case it wants to gib
581 this.event_damage(this, inflictor, attacker, excess, deathtype, weaponentity, hitloc, force);
582
583 // set up to fade out later
584 SUB_SetFade (this, time + 6 + random (), 1);
585 // reset body think wrapper broken by SUB_SetFade
586 if(this.classname == "body" && getthink(this) != CopyBody_Think) {
587 this.CopyBody_think = getthink(this);
588 this.CopyBody_nextthink = this.nextthink;
590 this.nextthink = time;
591 }
592
593 if(autocvar_sv_gentle > 0 || autocvar_ekg || this.classname == "body") {
594 // remove corpse
595 // clones don't run any animation code any more, so we must gib them when they die :(
596 this.event_damage(this, inflictor, attacker, autocvar_sv_gibhealth + 1, deathtype, weaponentity, hitloc, force);
597 }
598
599 // reset fields the weapons may use just in case
600 if(this.classname != "body")
601 {
602 FOREACH(Weapons, it != WEP_Null,
603 {
604 it.wr_resetplayer(it, this);
605 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
606 {
607 ATTACK_FINISHED_FOR(this, it.m_id, slot) = 0;
608 }
609 });
610 }
611 MUTATOR_CALLHOOK(PlayerDied, this);
612 }
613}
void accuracy_add(entity this, Weapon w, float fired, float hit, float real)
update accuracy stats
Definition accuracy.qc:102
bool accuracy_isgooddamage(entity attacker, entity targ)
does this damage count towards accuracy stats?
Definition accuracy.qc:133
bool animstate_override
true for one cycle, then changed to false
Definition anim.qh:42
void animdecide_setaction(entity e, float action, float restart)
const int ANIMACTION_PAIN2
const int ANIMACTION_PAIN1
float skill
Definition api.qh:35
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition weapon.qh:44
virtual void wr_playerdeath()
(SERVER) called whenever a player dies
Definition weapon.qh:110
int m_id
Definition weapon.qh:45
void ClientKill_Now_TeamChange(entity this)
Definition clientkill.qc:18
int killindicator_teamchange
Definition clientkill.qh:8
entity killindicator
Definition clientkill.qh:7
int spawnflags
Definition ammo.qh:15
#define PHYS_INPUT_BUTTON_CHAT(s)
Definition player.qh:159
#define IS_PLAYER(s)
Definition player.qh:243
float game_starttime
Definition stats.qh:82
const int FL_GODMODE
Definition constants.qh:75
string classname
float flags
const float SOLID_CORPSE
vector v_right
void Obituary(entity attacker, entity inflictor, entity targ, int deathtype,.entity weaponentity)
Definition damage.qc:228
float autocvar_g_maxpushtime
Definition damage.qh:17
#define DEATH_ISSPECIAL(t)
Definition all.qh:39
#define DEATH_WEAPONOF(t)
Definition all.qh:45
const int HITTYPE_SOUND
Definition all.qh:33
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:124
int autocvar_ekg
Definition gibs.qh:4
#define PlayerSound(this, def, chan, vol, voicetype)
const int VOICETYPE_PLAYERSOUND
Weapons
Definition guide.qh:113
float Handicap_GetTotalHandicap(entity player, bool receiving)
Returns the total handicap of the player.
Definition handicap.qc:96
#define FOREACH(list, cond, body)
Definition iter.qh:19
float pushltime
Definition jumppads.qh:21
bool istypefrag
Definition jumppads.qh:22
entity pusher
Definition laser.qc:57
#define STAT(...)
Definition stats.qh:82
float vlen(vector v)
#define UNSET_ONGROUND(s)
Definition movetypes.qh:18
const int MOVETYPE_NOCLIP
Definition movetypes.qh:137
const int MOVETYPE_TOSS
Definition movetypes.qh:135
var void func_null()
const string PLAYERSTATS_ALIVETIME
#define PlayerStats_GameReport_Event_Player(ent, eventid, val)
void Portal_ClearAllLater(entity own)
Definition portals.qc:611
#define NULL
Definition post.qh:14
#define makevectors
Definition post.qh:21
float DEAD_DYING
Definition progsdefs.qc:275
float fixangle
Definition progsdefs.qc:160
float deadflag
Definition progsdefs.qc:149
#define round_handler_IsActive()
#define round_handler_IsRoundStarted()
void calculate_player_respawn_time(entity this)
Definition client.qc:1392
float respawn_time
Definition client.qh:321
float alivetime_start
Definition client.qh:68
void RemoveGrapplingHooks(entity pl)
Definition hook.qc:30
float max_armorvalue
Definition items.qh:25
void PlayerCorpseDamage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition player.qc:183
float score_frame_dmgtaken
Definition player.qh:26
float autocvar_g_spawnshield_blockdamage
Definition player.qh:4
const int CH_PAIN
Definition sound.qh:18
#define PS(this)
Definition state.qh:18
ClientState CS(Client this)
Definition state.qh:47
void SUB_SetFade(entity ent, float vanish_time, float fading_time)
Definition subs.qc:77
float freeze_time
#define DIFF_TEAM(a, b)
Definition teams.qh:242
const int TELEPORT_SIMPLE
void SpawnThrownWeapon(entity this, vector org, Weapon wep,.entity weaponentity)
Definition throwing.qc:160
float autocvar_g_ballistics_density_corpse
Definition tracing.qh:6
#define IS_REAL_CLIENT(v)
Definition utils.qh:17
#define IS_MONSTER(v)
Definition utils.qh:21
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
Definition utils.qh:15
void WaypointSprite_PlayerDead(entity this)
const int WEP_FLAG_CANCLIMB
Definition weapon.qh:214
const int MAX_WEAPONSLOTS
Definition weapon.qh:16
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17
void WeaponStats_LogKill(float awep, float abot, float vwep, float vbot)
void WeaponStats_LogDamage(float awep, float abot, float vwep, float vbot, float damage)
#define ATTACK_FINISHED_FOR(ent, w, slot)
Weapon m_weapon
Definition wepent.qh:26
float default_player_alpha
Definition world.qh:72

References accuracy_add(), accuracy_isgooddamage(), alivetime_start, alpha, angles, anim_state, ANIMACTION_PAIN1, ANIMACTION_PAIN2, animdecide_setaction(), animdecide_setstate(), ANIMSTATE_DEAD1, ANIMSTATE_DEAD2, animstate_override, ATTACK_FINISHED_FOR, ATTEN_NORM, autocvar_ekg, autocvar_g_balance_armor_blockpercent, autocvar_g_balance_pause_health_regen, autocvar_g_ballistics_density_corpse, autocvar_g_maxpushtime, autocvar_g_spawnshield_blockdamage, autocvar_sv_gibhealth, avelocity, bound(), calculate_player_respawn_time(), CH_PAIN, CH_SHOTS, classname, ClientKill_Now_TeamChange(), CopyBody_nextthink, CopyBody_Think(), CS(), DEAD_DYING, deadflag, DEATH_ISSPECIAL, death_time, DEATH_WEAPONOF, default_player_alpha, DIFF_TEAM, dmg_inflictor, dmg_save, dmg_take, entity(), fixangle, FL_GODMODE, flags, FOREACH, freeze_time, func_null(), game_starttime, GetResource(), getthink, Handicap_GetTotalHandicap(), healtharmor_applydamage(), HITTYPE_SOUND, IS_BOT_CLIENT, IS_MONSTER, IS_PLAYER, IS_REAL_CLIENT, istypefrag, killindicator, killindicator_teamchange, M_ARGV, Weapon::m_id, m_weapon, makevectors, max(), max_armorvalue, MAX_WEAPONSLOTS, maxs, mins, move_movetype, MOVETYPE_NOCLIP, MOVETYPE_TOSS, MSG_BROADCAST, MUTATOR_CALLHOOK, nextthink, NULL, Obituary(), origin, pain_finished, pauseregen_finished, PHYS_INPUT_BUTTON_CHAT, PlayerCorpseDamage(), PlayerSound, PLAYERSTATS_ALIVETIME, PlayerStats_GameReport_Event_Player, Portal_ClearAllLater(), PS, pusher, pushltime, random(), RemoveGrapplingHooks(), RES_ARMOR, respawn_time, round_handler_IsActive, round_handler_IsRoundStarted, score_frame_dmgtaken, Send_Effect(), set_movetype(), setthink, skill, solid, SOLID_CORPSE, sound, sound_allowed(), spawnflags, SpawnThrownWeapon(), STAT, StatusEffects_active(), SUB_SetFade(), TakeResource(), TELEPORT_SIMPLE, teleportable, time, UNSET_ONGROUND, v_angle, v_right, vector, velocity, view_ofs, Violence_GibSplash_At(), vlen(), VOICETYPE_PLAYERSOUND, VOL_BASE, WaypointSprite_PlayerDead(), weaponentities, Weapons, WeaponStats_LogDamage(), WeaponStats_LogKill(), WEP_FLAG_CANCLIMB, and Weapon::wr_playerdeath().

Referenced by bumblebee_gunner_exit(), PutPlayerInServer(), and vehicles_exit().

◆ PlayerHeal()

bool PlayerHeal ( entity targ,
entity inflictor,
float amount,
float limit )

Definition at line 615 of file player.qc.

616{
617 float hlth = GetResource(targ, RES_HEALTH);
618 if (hlth <= 0 || hlth >= limit)
619 return false;
620
621 GiveResourceWithLimit(targ, RES_HEALTH, amount, limit);
622 return true;
623}
void GiveResourceWithLimit(entity receiver, Resource res_type, float amount, float limit)
Gives an entity some resource but not more than a limit.

References entity(), GetResource(), and GiveResourceWithLimit().

Referenced by PutPlayerInServer().

◆ precache_all_playermodels()

void precache_all_playermodels ( string pattern)

Definition at line 659 of file player.qc.

660{
661 int globhandle = search_begin(pattern, true, false);
662 if (globhandle < 0) return;
663 int n = search_getsize(globhandle);
664 for (int i = 0; i < n; ++i)
665 {
666 string s = search_getfilename(globhandle, i);
668 }
669 search_end(globhandle);
670}
string search_getfilename(float handle, float num)
float search_getsize(float handle)
float search_begin(string pattern, float caseinsensitive, float quiet)
void search_end(float handle)
void precache_playermodel(string m)
Definition player.qc:625

References precache_playermodel(), search_begin(), search_end(), search_getfilename(), and search_getsize().

Referenced by PRECACHE(), and REGISTER_MUTATOR().

◆ STATIC_INIT()

STATIC_INIT ( g_clones )

Definition at line 46 of file player.qh.

46{ g_clones = IL_NEW(); }
#define IL_NEW()

References g_clones, and IL_NEW.

◆ void()

void ( entity this)

References entity(), and vector.

Variable Documentation

◆ autocvar_g_spawnshield_blockdamage

float autocvar_g_spawnshield_blockdamage

Definition at line 4 of file player.qh.

Referenced by MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), and PlayerDamage().

◆ autocvar_g_spawnshieldtime

float autocvar_g_spawnshieldtime

Definition at line 3 of file player.qh.

Referenced by PutPlayerInServer(), and TEST().

◆ autocvar_sv_defaultcharacter

bool autocvar_sv_defaultcharacter

Definition at line 6 of file player.qh.

Referenced by FixPlayermodel(), and PRECACHE().

◆ autocvar_sv_defaultcharacterskin

bool autocvar_sv_defaultcharacterskin

Definition at line 7 of file player.qh.

Referenced by FixPlayermodel().

◆ autocvar_sv_defaultplayercolors

string autocvar_sv_defaultplayercolors

Definition at line 12 of file player.qh.

Referenced by FixPlayermodel().

◆ autocvar_sv_defaultplayermodel

string autocvar_sv_defaultplayermodel

Definition at line 13 of file player.qh.

Referenced by FixPlayermodel(), and PRECACHE().

◆ autocvar_sv_defaultplayermodel_blue

string autocvar_sv_defaultplayermodel_blue

Definition at line 14 of file player.qh.

Referenced by FixPlayermodel(), and PRECACHE().

◆ autocvar_sv_defaultplayermodel_pink

string autocvar_sv_defaultplayermodel_pink

Definition at line 15 of file player.qh.

Referenced by FixPlayermodel(), and PRECACHE().

◆ autocvar_sv_defaultplayermodel_red

string autocvar_sv_defaultplayermodel_red

Definition at line 16 of file player.qh.

Referenced by FixPlayermodel(), and PRECACHE().

◆ autocvar_sv_defaultplayermodel_yellow

string autocvar_sv_defaultplayermodel_yellow

Definition at line 17 of file player.qh.

Referenced by FixPlayermodel(), and PRECACHE().

◆ autocvar_sv_defaultplayerskin

int autocvar_sv_defaultplayerskin

Definition at line 18 of file player.qh.

Referenced by FixPlayermodel().

◆ autocvar_sv_defaultplayerskin_blue

int autocvar_sv_defaultplayerskin_blue

Definition at line 8 of file player.qh.

Referenced by FixPlayermodel().

◆ autocvar_sv_defaultplayerskin_pink

int autocvar_sv_defaultplayerskin_pink

Definition at line 9 of file player.qh.

Referenced by FixPlayermodel().

◆ autocvar_sv_defaultplayerskin_red

int autocvar_sv_defaultplayerskin_red

Definition at line 10 of file player.qh.

Referenced by FixPlayermodel().

◆ autocvar_sv_defaultplayerskin_yellow

int autocvar_sv_defaultplayerskin_yellow

Definition at line 11 of file player.qh.

Referenced by FixPlayermodel().

◆ autocvar_sv_gibhealth

float autocvar_sv_gibhealth

Definition at line 19 of file player.qh.

Referenced by PlayerCorpseDamage(), and PlayerDamage().

◆ autocvar_sv_precacheplayermodels

bool autocvar_sv_precacheplayermodels

Definition at line 5 of file player.qh.

Referenced by PRECACHE().

◆ CopyBody_nextthink

float CopyBody_nextthink

Definition at line 28 of file player.qh.

Referenced by CopyBody_Think(), and PlayerDamage().

◆ g_clones

IntrusiveList g_clones

Definition at line 45 of file player.qh.

Referenced by ClientKill_TeamChange(), CopyBody(), and STATIC_INIT().

◆ istypefrag

bool istypefrag

Definition at line 23 of file player.qh.

◆ pusher

entity pusher

Definition at line 21 of file player.qh.

◆ pushltime

float pushltime

Definition at line 22 of file player.qh.

◆ score_frame_dmg

float score_frame_dmg

Definition at line 25 of file player.qh.

Referenced by PlayerFrame().

◆ score_frame_dmgtaken

float score_frame_dmgtaken

Definition at line 26 of file player.qh.

Referenced by PlayerDamage(), and PlayerFrame().