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

Go to the source code of this file.

Macros

#define DMG_NOWEP   (weaponentities[0])

Functions

string AppendItemcodes (string s, entity player)
 bool (entity targ, entity inflictor, float amount, float limit) event_heal
void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
void Damage_DamageInfo (vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner)
bool Damage_DamageInfo_SendEntity (entity this, entity to, int sf)
float Fire_AddDamage (entity e, entity o, float d, float t, float dt)
void Fire_ApplyDamage (entity e)
void GiveFrags (entity attacker, entity targ, float f, int deathtype,.entity weaponentity)
bool Heal (entity targ, entity inflictor, float amount, float limit)
float IsFlying (entity a)
void LogDeath (string mode, int deathtype, entity killer, entity killed)
void Obituary (entity attacker, entity inflictor, entity targ, int deathtype,.entity weaponentity)
void Obituary_SpecialDeath (entity notif_target, bool murder, bool msg_from_ent, int deathtype, string s1, string s2, string s3, string s4, float f1, float f2, float f3)
float Obituary_WeaponDeath (entity notif_target, float murder, int deathtype, string s1, string s2, string s3, float f1, float f2)
float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, bool inflictorselfdamage, float forceintensity, vector forcexyzscale, int deathtype,.entity weaponentity, entity directhitentity)
 Returns total damage applied to creatures.
 STATIC_INIT (g_damagedbycontents)
 void (entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force) event_damage
void W_SwitchWeapon_Force (Player this, Weapon w,.entity weaponentity)

Variables

float autocvar_g_balance_armor_blockpercent
float autocvar_g_balance_damagepush_speedfactor
int autocvar_g_balance_firetransfer_damage
int autocvar_g_balance_firetransfer_time
float autocvar_g_balance_selfdamagepercent
float autocvar_g_friendlyfire
float autocvar_g_friendlyfire_virtual
float autocvar_g_friendlyfire_virtual_force
float autocvar_g_maxpushtime
float autocvar_g_mirrordamage
bool autocvar_g_mirrordamage_onlyweapons
bool autocvar_g_mirrordamage_virtual
int autocvar_g_player_damageplayercenter
float autocvar_g_teamdamage_resetspeed
float autocvar_g_teamdamage_threshold
bool autocvar_g_teamkill_punishing
float autocvar_g_throughfloor_damage
float autocvar_g_throughfloor_damage_max_stddev
bool autocvar_g_throughfloor_debug
float autocvar_g_throughfloor_force
float autocvar_g_throughfloor_force_max_stddev
float autocvar_g_throughfloor_max_steps_other
float autocvar_g_throughfloor_max_steps_player
float autocvar_g_throughfloor_min_steps_other
float autocvar_g_throughfloor_min_steps_player
bool canteamdamage
float checkrules_firstblood
float damagedbycontents
float damagedbytriggers
float damageextraradius
float damageforcescale
vector death_origin
string deathmessage
float dmg
float dmg_edge
float dmg_force
float dmg_radius
float dmg_team
float fire_damagepersec
float fire_deathtype
float fire_hitsound
entity fire_owner
IntrusiveList g_damagedbycontents
float hitsound_damage_dealt
int impressive_hits
bool istypefrag
int killsound
const float MAX_DAMAGEEXTRARADIUS = 16
const float MIN_DAMAGEEXTRARADIUS = 0.1
float pain_finished
entity pusher
bool RadiusDamage_running
float spawnshieldtime
float taunt_soundtime
float teamkill_complain
entity teamkill_soundsource
float teamkill_soundtime
int totalfrags
int typehitsound
float w_deathtype
float yoda

Macro Definition Documentation

◆ DMG_NOWEP

Function Documentation

◆ AppendItemcodes()

string AppendItemcodes ( string s,
entity player )

Definition at line 82 of file damage.qc.

83{
84 for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
85 {
86 .entity weaponentity = weaponentities[slot];
87 int w = player.(weaponentity).m_weapon.m_id;
88 if (w == 0)
89 w = player.(weaponentity).cnt; // previous weapon
90 if (w != 0 || slot == 0)
91 s = strcat(s, ftos(w));
92 }
93 if (PHYS_INPUT_BUTTON_CHAT(player))
94 s = strcat(s, "T");
95 // TODO: include these codes as a flag on the item itself
96 MUTATOR_CALLHOOK(LogDeath_AppendItemCodes, player, s);
97 s = M_ARGV(1, string);
98 return s;
99}
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
float cnt
Definition powerups.qc:24
#define M_ARGV(x, type)
Definition events.qh:17
#define PHYS_INPUT_BUTTON_CHAT(s)
Definition player.qh:161
string ftos(float f)
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
const int MAX_WEAPONSLOTS
Definition weapon.qh:16
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17
Weapon m_weapon
Definition wepent.qh:26

References cnt, entity(), ftos(), M_ARGV, m_weapon, MAX_WEAPONSLOTS, MUTATOR_CALLHOOK, PHYS_INPUT_BUTTON_CHAT, strcat(), and weaponentities.

Referenced by LogDeath().

◆ bool()

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

References entity().

◆ Damage()

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

Definition at line 484 of file damage.qc.

485{
486 if (game_stopped || (IS_CLIENT(targ) && CS(targ).killcount == FRAGS_SPECTATOR))
487 return;
488
489 // special rule: gravity bombs and sound-based attacks do not affect team mates (other than for disconnecting the hook)
490 if ((DEATH_ISWEAPON(deathtype, WEP_HOOK) || (deathtype & HITTYPE_SOUND))
491 && IS_PLAYER(targ) && SAME_TEAM(targ, attacker))
492 return;
493
494 entity attacker_save = attacker;
495
496 float complainteamdamage = 0;
497 float mirrordamage = 0;
498 float mirrorforce = 0;
499
500 if (deathtype == DEATH_KILL.m_id || deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id || damage == INFINITY)
501 {
502 // exit the vehicle before killing (fixes a crash)
503 if (IS_PLAYER(targ) && targ.vehicle)
504 vehicles_exit(targ.vehicle, VHEF_RELEASE);
505
506 StatusEffects_remove(STATUSEFFECT_SpawnShield, targ, STATUSEFFECT_REMOVE_CLEAR);
507 targ.flags &= ~FL_GODMODE;
508 damage = INFINITY;
509 }
510 else if (deathtype == DEATH_MIRRORDAMAGE.m_id || deathtype == DEATH_NOAMMO.m_id)
511 {
512 // no processing
513 }
514 else
515 {
516 // nullify damage if teamplay is on
517 if (deathtype != DEATH_TELEFRAG.m_id
518 && IS_PLAYER(attacker))
519 {
520 // avoid dealing damage or force to other independent players
521 // and avoid dealing damage or force to things owned by other independent players
522 if ((IS_PLAYER(targ) && targ != attacker && (IS_INDEPENDENT_PLAYER(attacker) || IS_INDEPENDENT_PLAYER(targ)))
523 || (targ.realowner && IS_INDEPENDENT_PLAYER(targ.realowner) && attacker != targ.realowner))
524 {
525 damage = 0;
526 force = '0 0 0';
527 }
528 else if (!STAT(FROZEN, targ) && SAME_TEAM(attacker, targ))
529 {
530 if (autocvar_teamplay_mode == 1)
531 damage = 0;
532 else if (attacker != targ)
533 {
534 if (autocvar_teamplay_mode == 2)
535 {
536 if (IS_PLAYER(targ) && !IS_DEAD(targ))
537 {
538 attacker.dmg_team += damage;
539 complainteamdamage = attacker.dmg_team - autocvar_g_teamdamage_threshold;
540 }
541 }
542 else if (autocvar_teamplay_mode == 3)
543 damage = 0;
544 else if (autocvar_teamplay_mode == 4)
545 {
546 if (IS_PLAYER(targ) && !IS_DEAD(targ))
547 {
548 attacker.dmg_team += damage;
549 complainteamdamage = attacker.dmg_team - autocvar_g_teamdamage_threshold;
550 if (complainteamdamage > 0)
551 mirrordamage = autocvar_g_mirrordamage * complainteamdamage;
552 mirrorforce = autocvar_g_mirrordamage * vlen(force);
553 damage = autocvar_g_friendlyfire * damage;
554 // mirrordamage will be used LATER
555
557 {
558 vector v = healtharmor_applydamage(GetResource(attacker, RES_HEALTH), GetResource(attacker, RES_ARMOR),
559 autocvar_g_balance_armor_blockpercent, deathtype, mirrordamage);
560 attacker.dmg_take += v.x;
561 attacker.dmg_save += v.y;
562 attacker.dmg_inflictor = inflictor;
563 mirrordamage = v.z;
564 mirrorforce = 0;
565 }
566
568 {
569 vector v = healtharmor_applydamage(GetResource(targ, RES_HEALTH), GetResource(targ, RES_ARMOR),
570 autocvar_g_balance_armor_blockpercent, deathtype, damage);
571 targ.dmg_take += v.x;
572 targ.dmg_save += v.y;
573 targ.dmg_inflictor = inflictor;
574 damage = 0;
576 force = '0 0 0';
577 }
578 }
579 else if (!targ.canteamdamage)
580 damage = 0;
581 }
582 }
583 }
584 }
585
586 if (!DEATH_ISSPECIAL(deathtype))
587 {
589 mirrordamage *= autocvar_g_weapondamagefactor;
590 complainteamdamage *= autocvar_g_weapondamagefactor;
592 mirrorforce *= autocvar_g_weaponforcefactor;
593 }
594
595 // should this be changed at all? If so, in what way?
596 MUTATOR_CALLHOOK(Damage_Calculate, inflictor, attacker, targ, deathtype, damage, mirrordamage, force, attacker.(weaponentity));
597 damage = M_ARGV(4, float);
598 mirrordamage = M_ARGV(5, float);
599 force = M_ARGV(6, vector);
600
601 if (IS_PLAYER(targ) && damage > 0 && attacker)
602 for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
603 {
604 .entity went = weaponentities[slot];
605 if (targ.(went).hook && targ.(went).hook.aiment == attacker)
606 RemoveHook(targ.(went).hook);
607 }
608
609 if (targ == attacker)
610 damage *= autocvar_g_balance_selfdamagepercent; // Partial damage if the attacker hits himself
611
612 // count the damage
613 if (attacker && targ != attacker
614 && !IS_DEAD(targ)
615 && deathtype != DEATH_BUFF_INFERNO.m_id
616 && deathtype != DEATH_BUFF_VENGEANCE.m_id
617 && targ.takedamage == DAMAGE_AIM)
618 {
619 entity victim;
620 if (IS_VEHICLE(targ) && targ.owner)
621 victim = targ.owner;
622 else
623 victim = targ;
624
625 // TODO: allow the mutator hook to tell if the hit sound should be team or not
626 if (IS_PLAYER(victim) || (IS_TURRET(victim) && victim.active == ACTIVE_ACTIVE) || IS_MONSTER(victim)
627 || MUTATOR_CALLHOOK(PlayHitsound, victim, attacker))
628 {
629 if (DIFF_TEAM(victim, attacker))
630 {
631 if (damage > 0)
632 {
633 if (deathtype != DEATH_FIRE.m_id)
634 {
635 if (PHYS_INPUT_BUTTON_CHAT(victim))
636 ++attacker.typehitsound;
637 else
638 attacker.hitsound_damage_dealt += damage;
639 }
640
642
643 if (!DEATH_ISSPECIAL(deathtype)
644 && IS_PLAYER(targ) // don't do this for vehicles
645 && IsFlying(victim))
646 yoda = 1;
647 }
648 }
649 else if (IS_PLAYER(attacker) && !STAT(FROZEN, victim) && !(deathtype & HITTYPE_SPAM)) // same team
650 {
651 if (deathtype != DEATH_FIRE.m_id)
652 ++attacker.typehitsound;
653 if (complainteamdamage > 0
654 && time > CS(attacker).teamkill_complain)
655 {
656 CS(attacker).teamkill_complain = time + 5;
657 CS(attacker).teamkill_soundtime = time + 0.4;
658 CS(attacker).teamkill_soundsource = targ;
659 }
660 }
661 }
662 }
663 }
664
665 // apply push
666 if (targ.damageforcescale && force
667 && (!IS_PLAYER(targ) || !StatusEffects_active(STATUSEFFECT_SpawnShield, targ) || targ == attacker))
668 {
669 vector farce = damage_explosion_calcpush(targ.damageforcescale * force, targ.velocity, autocvar_g_balance_damagepush_speedfactor);
670 if (targ.move_movetype == MOVETYPE_PHYSICS)
671 {
672 entity farcent = new(farce);
673 farcent.enemy = targ;
674 farcent.movedir = farce * 10;
675 if (targ.mass)
676 farcent.movedir *= targ.mass;
677 farcent.origin = hitloc;
678 farcent.forcetype = FORCETYPE_FORCEATPOS;
679 farcent.nextthink = time + 0.1;
680 setthink(farcent, SUB_Remove);
681 }
682 else if (targ.move_movetype != MOVETYPE_NOCLIP)
683 targ.velocity += farce;
684 UNSET_ONGROUND(targ);
686 }
687 // apply damage
688 if ((damage != 0 || (targ.damageforcescale && force))
689 && targ.event_damage)
690 targ.event_damage(targ, inflictor, attacker, damage, deathtype, weaponentity, hitloc, force);
691
692 // apply mirror damage if any
693 if ((!autocvar_g_mirrordamage_onlyweapons || DEATH_WEAPONOF(deathtype) != WEP_Null)
694 && (mirrordamage > 0 || mirrorforce > 0))
695 {
696 attacker = attacker_save;
697
698 force = normalize(attacker.origin + attacker.view_ofs - hitloc) * mirrorforce;
699 Damage(attacker, inflictor, attacker, mirrordamage, DEATH_MIRRORDAMAGE.m_id, weaponentity, attacker.origin, force);
700 }
701}
vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor)
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
bool IsFlying(entity this)
Definition player.qc:843
#define IS_CLIENT(s)
Definition player.qh:241
#define IS_DEAD(s)
Definition player.qh:244
#define IS_PLAYER(s)
Definition player.qh:242
float game_stopped
Definition stats.qh:81
vector healtharmor_applydamage(float h, float a, float armorblock, int deathtype, float damage)
Definition util.qc:1425
const int FL_GODMODE
Definition constants.qh:67
const int FRAGS_SPECTATOR
engine expects this value
Definition constants.qh:5
float time
void UpdateCSQCProjectile(entity e)
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition damage.qc:484
bool autocvar_g_mirrordamage_virtual
Definition damage.qh:15
bool autocvar_g_mirrordamage_onlyweapons
Definition damage.qh:16
float yoda
Definition damage.qh:48
float autocvar_g_friendlyfire_virtual_force
Definition damage.qh:28
float autocvar_g_balance_armor_blockpercent
Definition damage.qh:21
int impressive_hits
Definition damage.qh:49
float autocvar_g_balance_selfdamagepercent
Definition damage.qh:25
float autocvar_g_friendlyfire_virtual
Definition damage.qh:27
float autocvar_g_teamdamage_threshold
Definition damage.qh:23
float teamkill_complain
Definition damage.qh:54
float autocvar_g_friendlyfire
Definition damage.qh:26
float autocvar_g_balance_damagepush_speedfactor
Definition damage.qh:18
float autocvar_g_mirrordamage
Definition damage.qh:14
#define DEATH_ISWEAPON(t, w)
Definition all.qh:48
#define DEATH_ISSPECIAL(t)
Definition all.qh:41
const int HITTYPE_SPAM
set manually after first RadiusDamage, stops effect spam
Definition all.qh:36
#define DEATH_WEAPONOF(t)
Definition all.qh:47
const int HITTYPE_SOUND
cause bleeding from ears
Definition all.qh:35
void SUB_Remove(entity this)
Remove entity.
Definition defer.qh:12
const int ACTIVE_ACTIVE
Definition defs.qh:37
const float FORCETYPE_FORCEATPOS
RES_ARMOR
Definition ent_cs.qc:155
#define STAT(...)
Definition stats.qh:94
#define INFINITY
Definition mathlib.qh:105
float vlen(vector v)
vector normalize(vector v)
#define UNSET_ONGROUND(s)
Definition movetypes.qh:18
const int MOVETYPE_PHYSICS
Definition movetypes.qh:146
const int MOVETYPE_NOCLIP
Definition movetypes.qh:141
@ STATUSEFFECT_REMOVE_CLEAR
Effect is being forcibly removed without calling any additional mechanics.
Definition all.qh:30
#define setthink(e, f)
vector
Definition self.qh:96
int killcount
Definition client.qh:315
#define IS_INDEPENDENT_PLAYER(e)
Definition client.qh:312
void RemoveHook(entity this)
Definition hook.qc:48
ClientState CS(Client this)
Definition state.qh:47
void StatusEffects_remove(StatusEffect this, entity actor, int removal_type)
bool StatusEffects_active(StatusEffect this, entity actor)
const int DAMAGE_AIM
Definition subs.qh:81
void vehicles_exit(entity vehic, bool eject)
const int VHEF_RELEASE
Release ownership, client possibly allready dissconnected / went spec / changed team / used "kill" (n...
int autocvar_teamplay_mode
Definition teamplay.qh:3
#define SAME_TEAM(a, b)
Definition teams.qh:241
#define DIFF_TEAM(a, b)
Definition teams.qh:242
#define IS_TURRET(v)
Definition utils.qh:25
#define IS_MONSTER(v)
Definition utils.qh:23
#define IS_VEHICLE(v)
Definition utils.qh:24
float autocvar_g_weaponforcefactor
float autocvar_g_weapondamagefactor

References ACTIVE_ACTIVE, autocvar_g_balance_armor_blockpercent, autocvar_g_balance_damagepush_speedfactor, autocvar_g_balance_selfdamagepercent, autocvar_g_friendlyfire, autocvar_g_friendlyfire_virtual, autocvar_g_friendlyfire_virtual_force, autocvar_g_mirrordamage, autocvar_g_mirrordamage_onlyweapons, autocvar_g_mirrordamage_virtual, autocvar_g_teamdamage_threshold, autocvar_g_weapondamagefactor, autocvar_g_weaponforcefactor, autocvar_teamplay_mode, CS(), Damage(), DAMAGE_AIM, damage_explosion_calcpush(), DEATH_ISSPECIAL, DEATH_ISWEAPON, DEATH_WEAPONOF, DIFF_TEAM, entity(), FL_GODMODE, FORCETYPE_FORCEATPOS, FRAGS_SPECTATOR, game_stopped, GetResource(), healtharmor_applydamage(), HITTYPE_SOUND, HITTYPE_SPAM, impressive_hits, INFINITY, IS_CLIENT, IS_DEAD, IS_INDEPENDENT_PLAYER, IS_MONSTER, IS_PLAYER, IS_TURRET, IS_VEHICLE, IsFlying(), killcount, M_ARGV, MAX_WEAPONSLOTS, MOVETYPE_NOCLIP, MOVETYPE_PHYSICS, MUTATOR_CALLHOOK, normalize(), PHYS_INPUT_BUTTON_CHAT, RemoveHook(), RES_ARMOR, SAME_TEAM, setthink, STAT, STATUSEFFECT_REMOVE_CLEAR, StatusEffects_active(), StatusEffects_remove(), SUB_Remove(), teamkill_complain, time, UNSET_ONGROUND, UpdateCSQCProjectile(), vector, vehicles_exit(), VHEF_RELEASE, vlen(), weaponentities, and yoda.

Referenced by buff_Vengeance_DelayedDamage(), bumblebee_pilot_frame(), ClientKill_Now(), CommonCommand_editmob(), CreatureFrame_FallDamage(), CreatureFrame_hotliquids(), ctf_CaptureShield_Touch(), Damage(), door_blocked(), door_generic_plat_blocked(), DrownPlayer(), Fire_ApplyDamage(), fireBullet_falloff(), generic_plat_blocked(), havocbot_role_ctf_carrier(), instagib_countdown(), M_Golem_Attack_Lightning_Explode(), M_Zombie_Attack_Leap_Touch(), misc_laser_think(), Monster_Attack_Melee(), Monster_Move(), Monster_Think(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), nade_heal_touch(), nade_spawn_DestroyDamage(), nade_translocate_DestroyDamage(), ons_CaptureShield_Touch(), Onslaught_CheckWinner(), plat_crush(), RadiusDamageForSource(), SetPlayerTeam(), target_kill_use(), tdeath(), trigger_hurt_touch(), turret_tesla_toast(), vehicles_impact(), vehicles_touch(), W_Arc_Beam_Think(), W_Fireball_Explode(), W_OverkillRocketPropelledChainsaw_Think(), W_Shotgun_Melee_Think(), and walker_melee_do_dmg().

◆ Damage_DamageInfo()

void Damage_DamageInfo ( vector org,
float coredamage,
float edgedamage,
float rad,
vector force,
int deathtype,
float bloodtype,
entity dmgowner )

Definition at line 35 of file damageeffects.qc.

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}
#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
bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf)
float clientcolors
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:167
float MSG_BROADCAST
Definition menudefs.qc:55
#define new_pure(class)
purely logical entities (not linked to the area grid)
Definition oo.qh:66
vector org
Definition self.qh:96
bool sound_allowed(int to, entity e)
Definition all.qc:9
bool teamplay
Definition teams.qh:59

References BIT, BITS, Damage_DamageInfo_SendEntity(), entity(), MSG_BROADCAST, Net_LinkEntity(), new_pure, org, sound_allowed(), teamplay, vector, and vlen().

Referenced by fireBullet_falloff(), FireRailgunBullet(), nade_normal_boom(), RadiusDamageForSource(), raptor_bomb_burst(), W_Seeker_Tag_Explode(), and W_Seeker_Tag_Touch().

◆ Damage_DamageInfo_SendEntity()

bool Damage_DamageInfo_SendEntity ( entity this,
entity to,
int sf )

Definition at line 7 of file damageeffects.qc.

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}
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 velocity
float colormap
vector origin
WriteByte(chan, ent.angles.y/DEC_FACTOR)
const int MSG_ENTITY
Definition net.qh:156
#define WriteHeader(to, id)
Definition net.qh:265
float bound(float min, float value, float max)
void WriteChar(float data, float dest, float desto)
void WriteShort(float data, float dest, float desto)
float rint(float f)
float floor(float f)
float species
Definition main.qh:47
int projectiledeathtype
Definition common.qh:33
#define vec3(_x, _y, _z)
Definition vector.qh:100

References BITS, bound(), colormap, dmg, dmg_edge, dmg_force, dmg_radius, entity(), floor(), MSG_ENTITY, org, origin, projectiledeathtype, rint(), species, vec3, vector, velocity, WriteByte(), WriteChar(), WriteHeader, and WriteShort().

Referenced by Damage_DamageInfo().

◆ Fire_AddDamage()

float Fire_AddDamage ( entity e,
entity o,
float d,
float t,
float dt )

Definition at line 968 of file damage.qc.

969{
970 if (d <= 0)
971 return -1;
972 if (IS_PLAYER(e) && IS_DEAD(e))
973 return -1;
974
975 t = max(t, 0.1);
976 float dps = d / t;
977
978 if (StatusEffects_active(STATUSEFFECT_Burning, e))
979 {
980 float fireendtime = StatusEffects_gettime(STATUSEFFECT_Burning, e);
981
982 float mintime = fireendtime - time;
983 float maxtime = max(mintime, t);
984
985 float mindps = e.fire_damagepersec;
986 float maxdps = max(mindps, dps);
987
988 if (maxtime > mintime || maxdps > mindps)
989 {
990 // Constraints:
991
992 // damage we have right now
993 float mindamage = mindps * mintime;
994
995 // damage we want to get
996 float maxdamage = mindamage + d;
997
998 // but we can't exceed maxtime * maxdps!
999 float totaldamage = min(maxdamage, maxtime * maxdps);
1000
1001 // LEMMA:
1002 // Look at:
1003 // totaldamage = min(mindamage + d, maxtime * maxdps)
1004 // We see:
1005 // totaldamage <= maxtime * maxdps
1006 // ==> totaldamage / maxdps <= maxtime.
1007 // We also see:
1008 // totaldamage / mindps = min(mindamage / mindps + d, maxtime * maxdps / mindps)
1009 // >= min(mintime, maxtime)
1010 // ==> totaldamage / maxdps >= mintime.
1011
1012 /*
1013 // how long do we damage then?
1014 // at least as long as before
1015 // but, never exceed maxdps
1016 totaltime = max(mintime, totaldamage / maxdps); // always <= maxtime due to lemma
1017 */
1018
1019 // alternate:
1020 // at most as long as maximum allowed
1021 // but, never below mindps
1022 float totaltime = min(maxtime, totaldamage / mindps); // always >= mintime due to lemma
1023
1024 // assuming t > mintime, dps > mindps:
1025 // we get d = t * dps = maxtime * maxdps
1026 // totaldamage = min(maxdamage, maxtime * maxdps) = min(... + d, maxtime * maxdps) = maxtime * maxdps
1027 // totaldamage / maxdps = maxtime
1028 // totaldamage / mindps > totaldamage / maxdps = maxtime
1029 // FROM THIS:
1030 // a) totaltime = max(mintime, maxtime) = maxtime
1031 // b) totaltime = min(maxtime, totaldamage / maxdps) = maxtime
1032
1033 // assuming t <= mintime:
1034 // we get maxtime = mintime
1035 // a) totaltime = max(mintime, ...) >= mintime, also totaltime <= maxtime by the lemma, therefore totaltime = mintime = maxtime
1036 // b) totaltime = min(maxtime, ...) <= maxtime, also totaltime >= mintime by the lemma, therefore totaltime = mintime = maxtime
1037
1038 // assuming dps <= mindps:
1039 // we get mindps = maxdps.
1040 // With this, the lemma says that mintime <= totaldamage / mindps = totaldamage / maxdps <= maxtime.
1041 // a) totaltime = max(mintime, totaldamage / maxdps) = totaldamage / maxdps
1042 // b) totaltime = min(maxtime, totaldamage / mindps) = totaldamage / maxdps
1043
1044 e.fire_damagepersec = totaldamage / totaltime;
1045 StatusEffects_apply(STATUSEFFECT_Burning, e, time + totaltime, 0);
1046 if (totaldamage > 1.2 * mindamage)
1047 {
1048 e.fire_deathtype = dt;
1049 if (e.fire_owner != o)
1050 {
1051 e.fire_owner = o;
1052 e.fire_hitsound = false;
1053 }
1054 }
1055 if (accuracy_isgooddamage(o, e))
1056 accuracy_add(o, DEATH_WEAPONOF(dt), 0, max(0, totaldamage - mindamage), 0); // add to hit
1057 return max(0, totaldamage - mindamage); // can never be negative, but to make sure
1058 }
1059 else
1060 return 0;
1061 }
1062 else
1063 {
1064 e.fire_damagepersec = dps;
1065 StatusEffects_apply(STATUSEFFECT_Burning, e, time + t, 0);
1066 e.fire_deathtype = dt;
1067 e.fire_owner = o;
1068 e.fire_hitsound = false;
1069 if (accuracy_isgooddamage(o, e))
1070 accuracy_add(o, DEATH_WEAPONOF(dt), 0, d, 0); // add to hit
1071 return d;
1072 }
1073}
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
float min(float f,...)
float max(float f,...)
float StatusEffects_gettime(StatusEffect this, entity actor)
void StatusEffects_apply(StatusEffect this, entity actor, float eff_time, int eff_flags)

References accuracy_add(), accuracy_isgooddamage(), DEATH_WEAPONOF, entity(), IS_DEAD, IS_PLAYER, max(), min(), StatusEffects_active(), StatusEffects_apply(), StatusEffects_gettime(), and time.

Referenced by CreatureFrame_hotliquids(), M_Wyvern_Attack_Fireball_Explode(), MUTATOR_HOOKFUNCTION(), W_Fireball_Firemine_Touch(), and W_LaserPlay().

◆ Fire_ApplyDamage()

void Fire_ApplyDamage ( entity e)

Definition at line 1075 of file damage.qc.

1076{
1077 entity o;
1078 float t;
1079 for (t = 0, o = e.owner; o.owner && t < 16; o = o.owner, ++t);
1080 if (IS_NOT_A_CLIENT(o))
1081 o = e.fire_owner;
1082
1083 float fireendtime = StatusEffects_gettime(STATUSEFFECT_Burning, e);
1084 t = min(frametime, fireendtime - time);
1085 float d = e.fire_damagepersec * t;
1086
1087 float hi = e.fire_owner.hitsound_damage_dealt;
1088 float ty = e.fire_owner.typehitsound;
1089 Damage(e, e, e.fire_owner, d, e.fire_deathtype, DMG_NOWEP, e.origin, '0 0 0');
1090 if (e.fire_hitsound && e.fire_owner)
1091 {
1092 e.fire_owner.hitsound_damage_dealt = hi;
1093 e.fire_owner.typehitsound = ty;
1094 }
1095 e.fire_hitsound = true;
1096
1097 if (!IS_INDEPENDENT_PLAYER(e) && !STAT(FROZEN, e) && !StatusEffects_active(STATUSEFFECT_Frozen, e))
1098 IL_EACH(g_damagedbycontents, it.damagedbycontents && it != e,
1099 {
1100 if (!IS_DEAD(it) && it.takedamage && !IS_INDEPENDENT_PLAYER(it)
1101 && boxesoverlap(e.absmin - '1 1 1', e.absmax + '1 1 1', it.absmin, it.absmax))
1102 {
1103 t = autocvar_g_balance_firetransfer_time * (fireendtime - time);
1104 d = autocvar_g_balance_firetransfer_damage * e.fire_damagepersec * t;
1105 Fire_AddDamage(it, o, d, t, DEATH_FIRE.m_id);
1106 }
1107 });
1108}
#define IS_NOT_A_CLIENT(s)
Definition player.qh:243
float frametime
IntrusiveList g_damagedbycontents
Definition damage.qh:143
#define DMG_NOWEP
Definition damage.qh:104
#define IL_EACH(this, cond, body)

◆ GiveFrags()

void GiveFrags ( entity attacker,
entity targ,
float f,
int deathtype,
.entity weaponentity )

Definition at line 44 of file damage.qc.

45{
46 // TODO route through PlayerScores instead
47 if (game_stopped)
48 return;
49
50 if (f < 0)
51 {
52 if (targ == attacker) // suicide
53 GameRules_scoring_add(attacker, SUICIDES, 1);
54 else
55 {
56 // teamkill
57 int teamkills = GameRules_scoring_add(attacker, TEAMKILLS, 1);
59 f -= (teamkills * (teamkills - 1)) * 0.5; // negative 1, 2, 4, 7, 11, 16, 22, etc.
60 }
61 }
62 else
63 {
64 // regular frag
65 GameRules_scoring_add(attacker, KILLS, 1);
66 if (!warmup_stage && targ.playerid)
67 PlayerStats_GameReport_Event_Player(attacker, sprintf("kills-%d", targ.playerid), 1);
68 }
69
70 GameRules_scoring_add(targ, DEATHS, 1);
71
72 // FIXME fix the mess this is (we have REAL points now!)
73 if (MUTATOR_CALLHOOK(GiveFragsForKill, attacker, targ, f, deathtype, attacker.(weaponentity)))
74 f = M_ARGV(2, float);
75
76 attacker.totalfrags += f;
77
78 if (f)
79 GameRules_scoring_add_team(attacker, SCORE, f);
80}
bool warmup_stage
Definition main.qh:120
bool autocvar_g_teamkill_punishing
Definition damage.qh:24
#define PlayerStats_GameReport_Event_Player(ent, eventid, val)
#define GameRules_scoring_add(client, fld, value)
Definition sv_rules.qh:85
#define GameRules_scoring_add_team(client, fld, value)
Definition sv_rules.qh:89

References autocvar_g_teamkill_punishing, entity(), game_stopped, GameRules_scoring_add, GameRules_scoring_add_team, M_ARGV, MUTATOR_CALLHOOK, PlayerStats_GameReport_Event_Player, and warmup_stage.

Referenced by MUTATOR_HOOKFUNCTION(), and Obituary().

◆ Heal()

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

Definition at line 951 of file damage.qc.

952{
953 // TODO: mutator hook to control healing
954 if (game_stopped
955 || (IS_CLIENT(targ) && CS(targ).killcount == FRAGS_SPECTATOR)
956 || STAT(FROZEN, targ) || IS_DEAD(targ))
957 return false;
958
959 bool healed = (targ.event_heal)
960 ? targ.event_heal(targ, inflictor, amount, limit)
961 : false;
962 // TODO: additional handling? what if the healing kills them? should this abort if healing would do so etc
963 // TODO: healing fx!
964 // TODO: armor healing?
965 return healed;
966}

References CS(), entity(), FRAGS_SPECTATOR, game_stopped, IS_CLIENT, IS_DEAD, killcount, and STAT.

Referenced by bumblebee_pilot_frame(), M_Mage_Defend_Heal(), MUTATOR_HOOKFUNCTION(), trigger_heal_touch(), and W_Arc_Beam_Think().

◆ IsFlying()

float IsFlying ( entity a)

Definition at line 843 of file player.qc.

844{
845 if(IS_ONGROUND(this))
846 return false;
848 return false;
849 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 24', MOVE_NORMAL, this);
850 //traceline(this.origin, this.origin - '0 0 48', MOVE_NORMAL, this);
851 if(trace_fraction < 1)
852 return false;
853 return true;
854}
float waterlevel
Definition player.qh:225
const float MOVE_NORMAL
vector mins
vector maxs
float trace_fraction
const int WATERLEVEL_SWIMMING
Definition movetypes.qh:13
#define IS_ONGROUND(s)
Definition movetypes.qh:16

References entity(), IS_ONGROUND, maxs, mins, MOVE_NORMAL, origin, trace_fraction, waterlevel, and WATERLEVEL_SWIMMING.

Referenced by Damage(), MUTATOR_HOOKABLE(), sys_phys_update(), W_Devastator_Explode(), W_Electro_Explode(), W_MineLayer_Explode(), W_Mortar_Grenade_Explode(), W_Mortar_Grenade_Explode2(), W_OverkillNex_Attack(), W_RocketMinsta_Laser_Explode(), W_Vaporizer_Attack(), and W_Vortex_Attack().

◆ LogDeath()

void LogDeath ( string mode,
int deathtype,
entity killer,
entity killed )

Definition at line 101 of file damage.qc.

102{
104 return;
105 string s = strcat(":kill:", mode,
106 ":", ftos(killer.playerid),
107 ":", ftos(killed.playerid));
108 s = strcat(s, ":type=", Deathtype_Name(deathtype), ":items=");
109 s = AppendItemcodes(s, killer);
110 if (killed != killer)
111 {
112 s = strcat(s, ":victimitems=");
113 s = AppendItemcodes(s, killed);
114 }
115 GameLogEcho(s);
116}
string AppendItemcodes(string s, entity player)
Definition damage.qc:82
string Deathtype_Name(int deathtype)
Definition all.qc:3
void GameLogEcho(string s)
Definition gamelog.qc:15
bool autocvar_sv_eventlog
Definition gamelog.qh:3

References AppendItemcodes(), autocvar_sv_eventlog, Deathtype_Name(), entity(), ftos(), GameLogEcho(), and strcat().

Referenced by Obituary().

◆ Obituary()

void Obituary ( entity attacker,
entity inflictor,
entity targ,
int deathtype,
.entity weaponentity )

Definition at line 223 of file damage.qc.

224{
225 // Sanity check
226 if (!IS_PLAYER(targ))
227 {
228 backtrace("Obituary called on non-player?!\n");
229 return;
230 }
231
232 // Declarations
233 float notif_firstblood = false;
234 float kill_count_to_attacker, kill_count_to_target;
235 bool notif_anonymous = false;
236 string attacker_name = attacker.netname;
237
238 // Set final information for the death
239 targ.death_origin = targ.origin;
240 string deathlocation = (autocvar_notification_server_allows_location ? NearestLocation(targ.death_origin) : "");
241
242 // Abort now if a mutator requests it
243 if (MUTATOR_CALLHOOK(ClientObituary, inflictor, attacker, targ, deathtype, attacker.(weaponentity)))
244 {
245 CS(targ).killcount = 0;
246 return;
247 }
248 notif_anonymous = M_ARGV(5, bool);
249
250 // TODO: Replace "???" with a translatable "Anonymous player" string
251 // https://gitlab.com/xonotic/xonotic-data.pk3dir/-/issues/2839
252 if (notif_anonymous)
253 attacker_name = "???";
254
255 #ifdef NOTIFICATIONS_DEBUG
256 Debug_Notification(sprintf(
257 "Obituary(%s, %s, %s, %s = %d);\n",
258 attacker_name,
259 inflictor.netname,
260 targ.netname,
261 Deathtype_Name(deathtype),
262 deathtype
263 ));
264 #endif
265
266 // =======
267 // SUICIDE
268 // =======
269 if (targ == attacker)
270 {
271 if (DEATH_ISSPECIAL(deathtype))
272 {
273 if (deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
274 Obituary_SpecialDeath(targ, false, false, deathtype, targ.netname, deathlocation, "", "", targ.team, 0, 0);
275 else
276 {
277 switch (DEATH_ENT(deathtype))
278 {
279 case DEATH_MIRRORDAMAGE:
280 Obituary_SpecialDeath(targ, false, false, deathtype, targ.netname, deathlocation, "", "", CS(targ).killcount, 0, 0);
281 break;
282 case DEATH_HURTTRIGGER:
283 {
284 bool msg_from_ent = (inflictor && inflictor.message != "");
285 Obituary_SpecialDeath(targ, false, msg_from_ent, deathtype,
286 targ.netname,
287 (msg_from_ent ? inflictor.message : deathlocation),
288 (msg_from_ent ? deathlocation : ""),
289 "", CS(targ).killcount, 0, 0
290 );
291 break;
292 }
293 default:
294 Obituary_SpecialDeath(targ, false, false, deathtype, targ.netname, deathlocation, "", "", CS(targ).killcount, 0, 0);
295 break;
296 }
297 }
298 }
299 else if (!Obituary_WeaponDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0))
300 {
301 backtrace("SUICIDE: what the hell happened here?\n");
302 return;
303 }
304 LogDeath("suicide", deathtype, targ, targ);
305 if (deathtype != DEATH_AUTOTEAMCHANGE.m_id) // special case: don't negate frags if auto switched
306 GiveFrags(attacker, targ, -1, deathtype, weaponentity);
307 }
308
309 // ======
310 // MURDER
311 // ======
312 else if (IS_PLAYER(attacker))
313 {
314 if (SAME_TEAM(attacker, targ))
315 {
316 LogDeath("tk", deathtype, attacker, targ);
317 GiveFrags(attacker, targ, -1, deathtype, weaponentity);
318
319 CS(attacker).killcount = 0;
320
321 Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAG, targ.netname);
322 Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAGGED, attacker_name);
323 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(targ.team, INFO_DEATH_TEAMKILL), targ.netname, attacker_name, deathlocation, CS(targ).killcount);
324
325 // In this case, the death message will ALWAYS be "foo was betrayed by bar"
326 // No need for specific death/weapon messages...
327 }
328 else
329 {
330 LogDeath("frag", deathtype, attacker, targ);
331 GiveFrags(attacker, targ, 1, deathtype, weaponentity);
332
333 CS(attacker).taunt_soundtime = time + 1;
334 ++CS(attacker).killcount;
335
336 ++attacker.killsound;
337
338 // TODO: improve SPREE_ITEM and KILL_SPREE_LIST
339 // these 2 macros are spread over multiple files
340 #define SPREE_ITEM(counta,countb,center,normal,gentle) \
341 case counta: \
342 Send_Notification(NOTIF_ONE, attacker, MSG_ANNCE, ANNCE_KILLSTREAK_##countb); \
343 if (!warmup_stage) \
344 PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
345 break;
346
347 switch (CS(attacker).killcount)
348 {
350 default:
351 break;
352 }
353 #undef SPREE_ITEM
354
356 {
358 notif_firstblood = true; // modify the current messages so that they too show firstblood information
361
362 // tell spree_inf and spree_cen that this is a first-blood and first-victim event
363 kill_count_to_attacker = -1;
364 kill_count_to_target = -2;
365 }
366 else
367 {
368 kill_count_to_attacker = CS(attacker).killcount;
369 kill_count_to_target = 0;
370 }
371
372 if (targ.istypefrag)
373 {
375 NOTIF_ONE,
376 attacker,
377 MSG_CHOICE,
378 CHOICE_TYPEFRAG,
379 targ.netname,
380 kill_count_to_attacker,
381 (IS_BOT_CLIENT(targ) ? -1 : CS(targ).ping)
382 );
384 NOTIF_ONE,
385 targ,
386 MSG_CHOICE,
387 CHOICE_TYPEFRAGGED,
388 attacker_name,
389 kill_count_to_target,
390 GetResource(attacker, RES_HEALTH),
391 GetResource(attacker, RES_ARMOR),
392 (IS_BOT_CLIENT(attacker) ? -1 : CS(attacker).ping)
393 );
394 }
395 else if (!frag_centermessage_override(attacker, targ, deathtype, kill_count_to_attacker, kill_count_to_target, attacker_name))
396 {
398 NOTIF_ONE,
399 attacker,
400 MSG_CHOICE,
401 CHOICE_FRAG,
402 targ.netname,
403 kill_count_to_attacker,
404 (IS_BOT_CLIENT(targ) ? -1 : CS(targ).ping)
405 );
407 NOTIF_ONE,
408 targ,
409 MSG_CHOICE,
410 CHOICE_FRAGGED,
411 attacker_name,
412 kill_count_to_target,
413 GetResource(attacker, RES_HEALTH),
414 GetResource(attacker, RES_ARMOR),
415 (IS_BOT_CLIENT(attacker) ? -1 : CS(attacker).ping)
416 );
417 }
418
419 if (!Obituary_WeaponDeath(targ, true, deathtype, targ.netname, attacker_name, deathlocation, CS(targ).killcount, kill_count_to_attacker))
420 {
421 bool msg_from_ent = (DEATH_ENT(deathtype) == DEATH_HURTTRIGGER && inflictor && inflictor.message2 != "");
422 Obituary_SpecialDeath(targ, true, msg_from_ent, deathtype,
423 targ.netname,
424 attacker_name,
425 (msg_from_ent ? inflictor.message2 : deathlocation),
426 (msg_from_ent ? deathlocation : ""),
427 CS(targ).killcount, kill_count_to_attacker, 0
428 );
429 }
430 }
431 }
432
433 // =============
434 // ACCIDENT/TRAP
435 // =============
436 else
437 {
438 switch (DEATH_ENT(deathtype))
439 {
440 // For now, we're just forcing HURTTRIGGER to behave as "DEATH_VOID" and giving it no special options...
441 // Later on you will only be able to make custom messages using DEATH_CUSTOM,
442 // and there will be a REAL DEATH_VOID implementation which mappers will use.
443 case DEATH_HURTTRIGGER:
444 {
445 bool msg_from_ent = (inflictor && inflictor.message != "");
446 Obituary_SpecialDeath(targ, false, msg_from_ent, deathtype,
447 targ.netname,
448 (msg_from_ent ? inflictor.message : deathlocation),
449 (msg_from_ent ? deathlocation : ""),
450 "",
451 CS(targ).killcount, 0, 0
452 );
453 break;
454 }
455 case DEATH_CUSTOM:
456 Obituary_SpecialDeath(targ, false, false, deathtype,
457 targ.netname,
458 ((strstrofs(deathmessage, "%", 0) < 0) ? strcat("%s ", deathmessage) : deathmessage),
459 deathlocation,
460 "",
461 CS(targ).killcount, 0, 0
462 );
463 break;
464 default:
465 Obituary_SpecialDeath(targ, false, false, deathtype, targ.netname, deathlocation, "", "", CS(targ).killcount, 0, 0);
466 break;
467 }
468
469 LogDeath("accident", deathtype, targ, targ);
470 GiveFrags(targ, targ, -1, deathtype, weaponentity);
471
472 if (GameRules_scoring_add(targ, SCORE, 0) == -5)
473 {
474 Send_Notification(NOTIF_ONE, targ, MSG_ANNCE, ANNCE_ACHIEVEMENT_BOTLIKE);
475 if (!warmup_stage)
477 }
478 }
479
480 // reset target kill count
481 CS(targ).killcount = 0;
482}
float ping
Definition main.qh:169
void GiveFrags(entity attacker, entity targ, float f, int deathtype,.entity weaponentity)
Definition damage.qc:44
float Obituary_WeaponDeath(entity notif_target, bool murder, int deathtype, string s1, string s2, string s3, float f1, float f2)
Definition damage.qc:166
bool frag_centermessage_override(entity attacker, entity targ, int deathtype, int kill_count_to_attacker, int kill_count_to_target, string attacker_name)
Definition damage.qc:211
void Obituary_SpecialDeath(entity notif_target, bool murder, bool msg_from_ent, int deathtype, string s1, string s2, string s3, string s4, float f1, float f2, float f3)
Definition damage.qc:118
void LogDeath(string mode, int deathtype, entity killer, entity killed)
Definition damage.qc:101
string deathmessage
Definition damage.qh:73
float checkrules_firstblood
Definition damage.qh:43
#define DEATH_ENT(t)
Definition all.qh:43
#define strstrofs
#define backtrace(msg)
Definition log.qh:96
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
Definition all.qc:1500
#define KILL_SPREE_LIST
Definition all.qh:486
bool autocvar_notification_server_allows_location
Definition all.qh:308
#define APP_TEAM_NUM(num, prefix)
Definition all.qh:88
const string PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD
const string PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM
const string PLAYERSTATS_ACHIEVEMENT_BOTLIKE
#define NULL
Definition post.qh:14
string NearestLocation(vector p)
Definition chat.qc:446
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
Definition utils.qh:15

References APP_TEAM_NUM, autocvar_notification_server_allows_location, backtrace, checkrules_firstblood, CS(), DEATH_ENT, DEATH_ISSPECIAL, deathmessage, Deathtype_Name(), entity(), frag_centermessage_override(), GameRules_scoring_add, GetResource(), GiveFrags(), IS_BOT_CLIENT, IS_PLAYER, KILL_SPREE_LIST, killcount, LogDeath(), M_ARGV, MUTATOR_CALLHOOK, NearestLocation(), NULL, Obituary_SpecialDeath(), Obituary_WeaponDeath(), ping, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, PlayerStats_GameReport_Event_Player, RES_ARMOR, SAME_TEAM, Send_Notification(), strcat(), strstrofs, time, and warmup_stage.

Referenced by PlayerDamage().

◆ Obituary_SpecialDeath()

void Obituary_SpecialDeath ( entity notif_target,
bool murder,
bool msg_from_ent,
int deathtype,
string s1,
string s2,
string s3,
string s4,
float f1,
float f2,
float f3 )

Definition at line 118 of file damage.qc.

125{
126 if (!DEATH_ISSPECIAL(deathtype))
127 {
128 backtrace("Obituary_SpecialDeath called without a special deathtype?\n");
129 return;
130 }
131
132 entity deathent = REGISTRY_GET(Deathtypes, deathtype - DT_FIRST);
133 if (!deathent)
134 {
135 backtrace("Obituary_SpecialDeath: Could not find deathtype entity!\n");
136 return;
137 }
138
139 if ((g_cts || notif_target.killindicator_teamchange == -2) && deathtype == DEATH_KILL.m_id)
140 return; // TODO: somehow put this in CTS gametype file!
141
142 Notification death_message = (msg_from_ent)
143 ? (murder ? deathent.death_msg_ent_murder : deathent.death_msg_ent_self)
144 : (murder ? deathent.death_msgmurder : deathent.death_msgself);
145 if (death_message)
146 {
148 NOTIF_ONE,
149 notif_target,
150 MSG_MULTI,
151 death_message,
152 s1, s2, s3, s4,
153 f1, f2, f3, 0
154 );
156 NOTIF_ALL_EXCEPT,
157 notif_target,
158 MSG_INFO,
159 death_message.nent_msginfo,
160 s1, s2, s3, s4,
161 f1, f2, f3, 0
162 );
163 }
164}
#define g_cts
Definition cts.qh:36
const int DT_FIRST
Definition all.qh:39
spree_inf s1 s2 s3loc s2 s1
Definition all.inc:285
spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2 f1points f2
Definition all.inc:370
spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2 f1points s1 s2
Definition all.inc:477
f1
Definition all.inc:569
void Send_Notification_Core(NOTIF broadcast, entity client, MSG net_type, Notification net_name, string s1, string s2, string s3, string s4, float f1, float f2, float f3, float f4)
Definition all.qc:1646
entity Notification
always last
Definition all.qh:85
#define REGISTRY_GET(id, i)
Definition registry.qh:62

References backtrace, DEATH_ISSPECIAL, DT_FIRST, entity(), f1, f2, g_cts, REGISTRY_GET, s1, s2, and Send_Notification_Core().

Referenced by Obituary().

◆ Obituary_WeaponDeath()

float Obituary_WeaponDeath ( entity notif_target,
float murder,
int deathtype,
string s1,
string s2,
string s3,
float f1,
float f2 )

References entity(), f1, f2, s1, and s2.

◆ RadiusDamage()

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 at line 937 of file damage.qc.

942{
944 inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker,
945 coredamage, edgedamage, rad, cantbe, mustbe,
946 false, forceintensity, '1 1 1',
947 deathtype, weaponentity, directhitentity
948 );
949}
float RadiusDamageForSource(entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, bool inflictorselfdamage, float forceintensity, vector forcexyzscale, int deathtype,.entity weaponentity, entity directhitentity)
Returns total damage applied to creatures.
Definition damage.qc:714

References entity(), and RadiusDamageForSource().

Referenced by bumblebee_blowup(), CheatImpulse(), func_breakable_destroy(), M_Golem_Attack_Lightning_Explode(), M_Golem_Attack_Smash(), M_Mage_Attack_Push(), M_Mage_Attack_Spike_Explode(), M_Spider_Attack_Web_Explode(), M_Wyvern_Attack_Fireball_Explode(), nade_normal_boom(), PlayerTouchExplode(), racer_blowup(), raptor_blowup(), raptor_bomblet_boom(), spiderbot_blowup(), turret_flac_projectile_think_explode(), turret_projectile_explode(), vehicles_projectile_explode(), W_Arc_Bolt_Explode(), W_Arc_Bolt_Touch(), W_Crylink_LinkExplode(), W_Crylink_LinkJoinEffect_Think(), W_Crylink_Touch(), W_DamageOverTime_Think(), W_Devastator_DoRemoteExplode(), W_Electro_Explode(), W_Electro_ExplodeCombo(), W_Fireball_Explode(), W_Hagar_Explode(), W_Hagar_Explode2(), W_HLAC_Touch(), W_MineLayer_DoRemoteExplode(), W_MineLayer_Explode(), W_Mortar_Grenade_Explode(), W_Mortar_Grenade_Explode2(), W_OverkillRocketPropelledChainsaw_Explode(), W_RocketMinsta_Explosion(), W_RocketMinsta_Laser_Damage(), W_Seeker_Flac_Explode(), W_Seeker_Missile_Explode(), W_Tuba_NoteOn(), and walker_rocket_explode().

◆ RadiusDamageForSource()

float RadiusDamageForSource ( entity inflictor,
vector inflictororigin,
vector inflictorvelocity,
entity attacker,
float coredamage,
float edgedamage,
float rad,
entity cantbe,
entity mustbe,
bool inflictorselfdamage,
float forceintensity,
vector forcexyzscale,
int deathtype,
.entity weaponentity,
entity directhitentity )

Returns total damage applied to creatures.

Definition at line 714 of file damage.qc.

719{
721 {
722 backtrace("RadiusDamage called recursively! Expect stuff to go HORRIBLY wrong.");
723 return 0;
724 }
725
726 if (rad < 0)
727 rad = 0;
728
730
731 float tfloordmg = autocvar_g_throughfloor_damage;
732 float tfloorforce = autocvar_g_throughfloor_force;
733
734 float stat_damagedone = 0;
735 float total_damage_to_creatures = 0;
736
737 vector force;
738 if (!(deathtype & (HITTYPE_SOUND | HITTYPE_SPAM))) // do not send bandwidth-hogging radial spam attacks
739 {
740 force = inflictorvelocity;
741 if (force == '0 0 0')
742 force = '0 0 -1';
743 else
744 force = normalize(force);
745 if (forceintensity >= 0)
746 Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
747 else
748 Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
749 }
750
756 for (; targ; targ = targ.chain)
757 {
758 // calculate distance from nearest point on target to nearest point on inflictor
759 // instead of origin to ensure full damage on impacts
760
761 vector nearest = targ.WarpZone_findradius_nearest;
762
763 // optimize code by getting inflictororigin_wz from WarpZone_FindRadius calculations instead of
764 //vector inflictororigin_wz = WarpZone_TransformOrigin(targ, inflictororigin);
765
766 vector inflictororigin_wz = targ.WarpZone_findradius_nearest + targ.WarpZone_findradius_dist;
767 vector inflictornearest = NearestPointOnBoundingBox(
768 inflictororigin_wz + inflictor.mins, inflictororigin_wz + inflictor.maxs, nearest);
769 vector diff = inflictornearest - nearest;
770
771 // round up a little on the damage to ensure full damage on impacts
772 // and turn the distance into a fraction of the radius
773 float dist = max(0, vlen(diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS));
774 if (dist > rad)
775 continue;
776
777
778 float f = (rad > 0) ? 1 - (dist / rad) : 1;
779 // at this point f can't be < 0 or > 1
780 float finaldmg = coredamage * f + edgedamage * (1 - f);
781 if (finaldmg <= 0)
782 continue;
783
784
785 vector hitloc;
786 float a, c;
787
788 // if it's a player, use the view origin as reference
789 vector center = CENTER_OR_VIEWOFS(targ);
790
792 {
793 if (targ != attacker) // always use target's bbox centerpoint
794 center = targ.origin + ((targ.mins + targ.maxs) * 0.5);
795 else // targ == attacker
796 {
797 #if 0
798 // code stolen from W_SetupShot_Dir_ProjectileSize_Range()
799 vector md = targ.(weaponentity).movedir;
800 vector dv = v_right * -md.y + v_up * md.z;
801 vector mi = '0 0 0', ma = '0 0 0';
802
803 if (IS_CLIENT(targ)) // no antilag for non-clients!
804 tracebox_antilag(targ, center, mi, ma, center + dv, MOVE_NORMAL, targ, (CS(targ).antilag_debug ? CS(targ).antilag_debug : ANTILAG_LATENCY(targ));
805 else
806 tracebox(center, mi, ma, center + dv, MOVE_NORMAL, targ);
807
808 center.z = trace_endpos.z;
809 #else
810 // very cheap way but it skips move into solid checks which is fine most of the time for now AFAIK
811 // this should only really be an issue with some rare edge cases where
812 // shot origin was prevented from going into a ceiling but it still explodes at the ceiling
813 // shot origin wasn't raised as high as possible and the shooter gets upwards knockback
814 // TL;DR: no bugs if vertical shot origin is always within player bbox
815 center.z += targ.(weaponentity).movedir.z;
816 #endif
817 }
818 }
819
820 /* debug prints
821 print(sprintf("origin vec %v\n", targ.origin));
822 print(sprintf("movedir vec %v\n", targ.(weaponentity).movedir));
823 print(sprintf("old def vec %v\n", CENTER_OR_VIEWOFS(targ)));
824 print(sprintf("origin+vofs %v\n", targ.origin + targ.view_ofs));
825 print(sprintf("bbox center %v\n", (targ.origin + ((targ.mins + targ.maxs) * 0.5))));
826 print(sprintf("center vec %v\n", center));
827 print(sprintf("shotorg vec %v\n", w_shotorg));
828 print("\n");
829 */
830
831 force = normalize(center - inflictororigin_wz);
832 force *= (finaldmg / max(coredamage, edgedamage)) * forceintensity;
833 hitloc = nearest;
834
835 // apply special force scalings
836 if (forcexyzscale.x)
837 force.x *= forcexyzscale.x;
838 if (forcexyzscale.y)
839 force.y *= forcexyzscale.y;
840 if (forcexyzscale.z)
841 force.z *= forcexyzscale.z;
842
843 if (targ != directhitentity)
844 {
845 float hits;
846 float total;
847 float hitratio;
848 float mininv_f, mininv_d;
849
850 // test line of sight to multiple positions on box,
851 // and do damage if any of them hit
852 hits = 0;
853
854 // we know: max stddev of hitratio = 1 / (2 * sqrt(n))
855 // so for a given max stddev:
856 // n = (1 / (2 * max stddev of hitratio))^2
857
858 mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev;
859 mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev;
860
862 LOG_INFOF("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f);
863
864 total = 0.25 * (max(mininv_f, mininv_d) ** 2);
865
867 LOG_INFOF(" steps=%f", total);
868
869 if (IS_PLAYER(targ))
871 else
873
875 LOG_INFOF(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total)));
876
877 for (c = 0; c < total; ++c)
878 {
879 //traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor);
880 WarpZone_TraceLine(inflictororigin, WarpZone_UnTransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor);
881 if (trace_fraction == 1 || trace_ent == targ)
882 {
883 ++hits;
884 if (hits > 1)
885 hitloc += nearest;
886 else
887 hitloc = nearest;
888 }
889 nearest.x = targ.origin.x + targ.mins.x + random() * targ.size.x;
890 nearest.y = targ.origin.y + targ.mins.y + random() * targ.size.y;
891 nearest.z = targ.origin.z + targ.mins.z + random() * targ.size.z;
892 }
893
894 nearest = hitloc * (1 / max(1, hits));
895 hitratio = hits / total;
896 a = bound(0, tfloordmg + (1 - tfloordmg) * hitratio, 1);
897 finaldmg *= a;
898 a = bound(0, tfloorforce + (1 - tfloorforce) * hitratio, 1);
899 force *= a;
900
902 LOG_INFOF(" D=%f F=%f", finaldmg, vlen(force));
903
904 /*if (targ == attacker)
905 {
906 print("hits ", ftos(hits), " / ", ftos(total));
907 print(" finaldmg ", ftos(finaldmg), " force ", ftos(vlen(force)));
908 print(" (", vtos(force), ") (", ftos(a), ")\n");
909 }*/
910 }
911
912 if (finaldmg || force)
913 {
914 if (targ.iscreature)
915 {
916 total_damage_to_creatures += finaldmg;
917
918 if (accuracy_isgooddamage(attacker, targ))
919 stat_damagedone += finaldmg;
920 }
921
922 if (targ == directhitentity || DEATH_ISSPECIAL(deathtype))
923 Damage(targ, inflictor, attacker, finaldmg, deathtype, weaponentity, nearest, force);
924 else
925 Damage(targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, weaponentity, nearest, force);
926 }
927 }
928
929 RadiusDamage_running = false;
930
931 if (!DEATH_ISSPECIAL(deathtype))
932 accuracy_add(attacker, DEATH_WEAPONOF(deathtype), 0, min(max(coredamage, edgedamage), stat_damagedone), 0); // add to hit
933
934 return total_damage_to_creatures;
935}
void tracebox_antilag(entity source, vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent, float lag)
Definition antilag.qc:216
float antilag_debug
Definition antilag.qc:18
#define ANTILAG_LATENCY(e)
Definition antilag.qh:21
vector v_up
const float MOVE_NOMONSTERS
entity trace_ent
vector v_right
vector trace_endpos
entity RadiusDamageForSource_cond_inflictor
Definition damage.qc:703
bool RadiusDamageForSource_cond_inflictorselfdamage
Definition damage.qc:706
bool RadiusDamageForSource_cond(entity targ)
Definition damage.qc:707
entity RadiusDamageForSource_cond_mustbe
Definition damage.qc:705
entity RadiusDamageForSource_cond_cantbe
Definition damage.qc:704
bool RadiusDamage_running
Definition damage.qh:111
int autocvar_g_player_damageplayercenter
Definition damage.qh:106
float autocvar_g_throughfloor_force_max_stddev
Definition damage.qh:9
float autocvar_g_throughfloor_damage_max_stddev
Definition damage.qh:8
float autocvar_g_throughfloor_force
Definition damage.qh:7
bool autocvar_g_throughfloor_debug
Definition damage.qh:5
float autocvar_g_throughfloor_min_steps_other
Definition damage.qh:12
float autocvar_g_throughfloor_min_steps_player
Definition damage.qh:10
float autocvar_g_throughfloor_damage
Definition damage.qh:6
float autocvar_g_throughfloor_max_steps_other
Definition damage.qh:13
float autocvar_g_throughfloor_max_steps_player
Definition damage.qh:11
void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner)
const float MAX_DAMAGEEXTRARADIUS
const float MIN_DAMAGEEXTRARADIUS
const int HITTYPE_SPLASH
automatically set by RadiusDamage
Definition all.qh:32
entity WarpZone_SearchInRadius(vector org, float rad, float nomonsters, WarpZone_FindRadius_cond_callback_t cb)
Modified findradius aware of warpzones, that only includes entities that meet the "cb" criteria.
Definition common.qc:680
vector WarpZone_UnTransformOrigin(entity wz, vector org)
Transforms origin org backwards through warpzone wz, as the inverse of WarpZone_TransformOrigin.
Definition common.qc:526
#define WarpZone_TraceLine(org, end, nomonsters, forent)
Definition common.qh:51
#define MOVE_NOTHING
Definition common.qh:35
#define LOG_INFOF(...)
Definition log.qh:63
vector movedir
Definition viewloc.qh:18
float ceil(float f)
float random(void)
float sqrt(float f)
#define CENTER_OR_VIEWOFS(ent)
Definition utils.qh:31
ERASEABLE vector NearestPointOnBoundingBox(vector mi, vector ma, vector org)
Definition vector.qh:200

References accuracy_add(), accuracy_isgooddamage(), antilag_debug, ANTILAG_LATENCY, autocvar_g_player_damageplayercenter, autocvar_g_throughfloor_damage, autocvar_g_throughfloor_damage_max_stddev, autocvar_g_throughfloor_debug, autocvar_g_throughfloor_force, autocvar_g_throughfloor_force_max_stddev, autocvar_g_throughfloor_max_steps_other, autocvar_g_throughfloor_max_steps_player, autocvar_g_throughfloor_min_steps_other, autocvar_g_throughfloor_min_steps_player, backtrace, bound(), ceil(), CENTER_OR_VIEWOFS, CS(), Damage(), Damage_DamageInfo(), DEATH_ISSPECIAL, DEATH_WEAPONOF, entity(), HITTYPE_SOUND, HITTYPE_SPAM, HITTYPE_SPLASH, IS_CLIENT, IS_PLAYER, LOG_INFOF, max(), MAX_DAMAGEEXTRARADIUS, min(), MIN_DAMAGEEXTRARADIUS, MOVE_NOMONSTERS, MOVE_NORMAL, MOVE_NOTHING, movedir, NearestPointOnBoundingBox(), normalize(), RadiusDamage_running, RadiusDamageForSource_cond(), RadiusDamageForSource_cond_cantbe, RadiusDamageForSource_cond_inflictor, RadiusDamageForSource_cond_inflictorselfdamage, RadiusDamageForSource_cond_mustbe, random(), sqrt(), trace_endpos, trace_ent, trace_fraction, tracebox_antilag(), v_right, v_up, vector, vlen(), WarpZone_SearchInRadius(), WarpZone_TraceLine, and WarpZone_UnTransformOrigin().

Referenced by RadiusDamage(), W_Blaster_Touch(), and W_Devastator_Explode().

◆ STATIC_INIT()

STATIC_INIT ( g_damagedbycontents )

Definition at line 144 of file damage.qh.

145{
147}
#define IL_NEW()

References g_damagedbycontents, and IL_NEW.

◆ void()

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

References entity(), and vector.

◆ W_SwitchWeapon_Force()

void W_SwitchWeapon_Force ( Player this,
Weapon w,
.entity weaponentity )

Definition at line 237 of file selection.qc.

238{
239 TC(Weapon, wep);
240 entity w_ent = this.(weaponentity);
241 w_ent.cnt = w_ent.m_switchweapon.m_id;
242 w_ent.m_switchweapon = wep;
243 w_ent.selectweapon = wep.m_id;
244}
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition weapon.qh:42
#define TC(T, sym)
Definition _all.inc:82

References entity(), Weapon::m_id, and TC.

Referenced by GiveItems(), Item_GiveTo(), MUTATOR_HOOKFUNCTION(), TEST(), W_Hagar_Attack_Auto(), W_HLAC_Attack_Frame(), W_MachineGun_Attack_Auto(), W_MachineGun_Attack_Frame(), W_OverkillHeavyMachineGun_Attack_Auto(), W_OverkillMachineGun_Attack_Auto(), W_Shotgun_Attack3_Frame1(), W_Shotgun_Attack3_Frame2(), W_ThrowWeapon(), and W_WeaponFrame().

Variable Documentation

◆ autocvar_g_balance_armor_blockpercent

◆ autocvar_g_balance_damagepush_speedfactor

float autocvar_g_balance_damagepush_speedfactor

Definition at line 18 of file damage.qh.

Referenced by ClientInit_CheckUpdate(), Damage(), and MUTATOR_HOOKFUNCTION().

◆ autocvar_g_balance_firetransfer_damage

int autocvar_g_balance_firetransfer_damage

Definition at line 19 of file damage.qh.

◆ autocvar_g_balance_firetransfer_time

int autocvar_g_balance_firetransfer_time

Definition at line 20 of file damage.qh.

◆ autocvar_g_balance_selfdamagepercent

float autocvar_g_balance_selfdamagepercent

Definition at line 25 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_friendlyfire

float autocvar_g_friendlyfire

Definition at line 26 of file damage.qh.

Referenced by Damage(), MUTATOR_HOOKFUNCTION(), and turret_damage().

◆ autocvar_g_friendlyfire_virtual

float autocvar_g_friendlyfire_virtual

Definition at line 27 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_friendlyfire_virtual_force

float autocvar_g_friendlyfire_virtual_force

Definition at line 28 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_maxpushtime

◆ autocvar_g_mirrordamage

float autocvar_g_mirrordamage

Definition at line 14 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_mirrordamage_onlyweapons

bool autocvar_g_mirrordamage_onlyweapons

Definition at line 16 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_mirrordamage_virtual

bool autocvar_g_mirrordamage_virtual

Definition at line 15 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_player_damageplayercenter

int autocvar_g_player_damageplayercenter

Definition at line 106 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ autocvar_g_teamdamage_resetspeed

float autocvar_g_teamdamage_resetspeed

Definition at line 22 of file damage.qh.

Referenced by PlayerThink().

◆ autocvar_g_teamdamage_threshold

float autocvar_g_teamdamage_threshold

Definition at line 23 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_teamkill_punishing

bool autocvar_g_teamkill_punishing

Definition at line 24 of file damage.qh.

Referenced by GiveFrags().

◆ autocvar_g_throughfloor_damage

float autocvar_g_throughfloor_damage

Definition at line 6 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ autocvar_g_throughfloor_damage_max_stddev

float autocvar_g_throughfloor_damage_max_stddev

Definition at line 8 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ autocvar_g_throughfloor_debug

bool autocvar_g_throughfloor_debug

Definition at line 5 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ autocvar_g_throughfloor_force

float autocvar_g_throughfloor_force

Definition at line 7 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ autocvar_g_throughfloor_force_max_stddev

float autocvar_g_throughfloor_force_max_stddev

Definition at line 9 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ autocvar_g_throughfloor_max_steps_other

float autocvar_g_throughfloor_max_steps_other

Definition at line 13 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ autocvar_g_throughfloor_max_steps_player

float autocvar_g_throughfloor_max_steps_player

Definition at line 11 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ autocvar_g_throughfloor_min_steps_other

float autocvar_g_throughfloor_min_steps_other

Definition at line 12 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ autocvar_g_throughfloor_min_steps_player

float autocvar_g_throughfloor_min_steps_player

Definition at line 10 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ canteamdamage

bool canteamdamage

Definition at line 65 of file damage.qh.

Referenced by spawnfunc().

◆ checkrules_firstblood

float checkrules_firstblood

Definition at line 43 of file damage.qh.

Referenced by Obituary().

◆ damagedbycontents

◆ damagedbytriggers

float damagedbytriggers

Definition at line 46 of file damage.qh.

◆ damageextraradius

float damageextraradius

Definition at line 128 of file damage.qh.

◆ damageforcescale

float damageforcescale

Definition at line 125 of file damage.qh.

◆ death_origin

vector death_origin

Definition at line 67 of file damage.qh.

Referenced by formatmessage(), IMPULSE(), IMPULSE(), and IMPULSE().

◆ deathmessage

string deathmessage

Definition at line 73 of file damage.qh.

Referenced by Obituary().

◆ dmg

float dmg

Definition at line 34 of file damage.qh.

◆ dmg_edge

float dmg_edge

Definition at line 35 of file damage.qh.

◆ dmg_force

float dmg_force

Definition at line 36 of file damage.qh.

◆ dmg_radius

float dmg_radius

Definition at line 37 of file damage.qh.

◆ dmg_team

float dmg_team

Definition at line 53 of file damage.qh.

Referenced by PlayerThink(), and PutPlayerInServer().

◆ fire_damagepersec

float fire_damagepersec

Definition at line 134 of file damage.qh.

◆ fire_deathtype

float fire_deathtype

Definition at line 135 of file damage.qh.

◆ fire_hitsound

float fire_hitsound

Definition at line 137 of file damage.qh.

◆ fire_owner

entity fire_owner

Definition at line 136 of file damage.qh.

◆ g_damagedbycontents

◆ hitsound_damage_dealt

float hitsound_damage_dealt

Definition at line 69 of file damage.qh.

◆ impressive_hits

int impressive_hits

Definition at line 49 of file damage.qh.

Referenced by Damage(), W_OverkillNex_Attack(), W_Vaporizer_Attack(), and W_Vortex_Attack().

◆ istypefrag

bool istypefrag

Definition at line 58 of file damage.qh.

◆ killsound

int killsound

Definition at line 70 of file damage.qh.

◆ MAX_DAMAGEEXTRARADIUS

const float MAX_DAMAGEEXTRARADIUS = 16

Definition at line 127 of file damage.qh.

◆ MIN_DAMAGEEXTRARADIUS

const float MIN_DAMAGEEXTRARADIUS = 0.1

Definition at line 126 of file damage.qh.

◆ pain_finished

float pain_finished

Definition at line 51 of file damage.qh.

◆ pusher

entity pusher

Definition at line 57 of file damage.qh.

◆ RadiusDamage_running

bool RadiusDamage_running

Definition at line 111 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ spawnshieldtime

◆ taunt_soundtime

float taunt_soundtime

Definition at line 59 of file damage.qh.

Referenced by PlayerPreThink().

◆ teamkill_complain

float teamkill_complain

Definition at line 54 of file damage.qh.

Referenced by Damage(), and W_Nexball_Touch().

◆ teamkill_soundsource

entity teamkill_soundsource

Definition at line 56 of file damage.qh.

◆ teamkill_soundtime

float teamkill_soundtime

Definition at line 55 of file damage.qh.

Referenced by PlayerPreThink().

◆ totalfrags

int totalfrags

Definition at line 63 of file damage.qh.

◆ typehitsound

int typehitsound

Definition at line 70 of file damage.qh.

◆ w_deathtype

float w_deathtype

Definition at line 93 of file damage.qh.

◆ yoda