Xonotic
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 Freeze (entity targ, float revivespeed, int frozen_type, bool show_waypoint)
 
void GiveFrags (entity attacker, entity targ, float f, int deathtype,.entity weaponentity)
 
bool Heal (entity targ, entity inflictor, float amount, float limit)
 
void Ice_Think (entity this)
 
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, float murder, int deathtype, string s1, string s2, string s3, 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, float inflictorselfdamage, float forceintensity, float forcezscale, int deathtype,.entity weaponentity, entity directhitentity)
 
 STATIC_INIT (g_damagedbycontents)
 
void Unfreeze (entity targ, bool reset_health)
 
void UpdateFrags (entity player, int f)
 
 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
 
bool autocvar_g_frozen_damage_trigger
 
float autocvar_g_frozen_force
 
float autocvar_g_frozen_revive_falldamage
 
int autocvar_g_frozen_revive_falldamage_health
 
float autocvar_g_maxpushtime
 
float autocvar_g_mirrordamage
 
bool autocvar_g_mirrordamage_onlyweapons
 
bool autocvar_g_mirrordamage_virtual
 
float autocvar_g_teamdamage_resetspeed
 
float autocvar_g_teamdamage_threshold
 
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
 
float freeze_time
 
entity frozen_by
 
const int FROZEN_NORMAL = 1
 
const int FROZEN_TEMP_DYING = 3
 
const int FROZEN_TEMP_REVIVING = 2
 
IntrusiveList g_damagedbycontents
 
float hitsound_damage_dealt
 
entity iceblock
 
int impressive_hits
 
bool istypefrag
 
int killsound
 
const float MAX_DAMAGEEXTRARADIUS = 16
 
const float MIN_DAMAGEEXTRARADIUS = 2
 
float pain_finished
 
entity pusher
 
float RadiusDamage_running
 
float revival_time
 
float revive_speed
 
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 87 of file damage.qc.

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

Referenced by LogDeath().

88 {
89  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
90  {
91  .entity weaponentity = weaponentities[slot];
92  int w = player.(weaponentity).m_weapon.m_id;
93  if(w == 0)
94  w = player.(weaponentity).cnt; // previous weapon
95  if(w != 0 || slot == 0)
96  s = strcat(s, ftos(w));
97  }
98  if(PHYS_INPUT_BUTTON_CHAT(player))
99  s = strcat(s, "T");
100  // TODO: include these codes as a flag on the item itself
101  MUTATOR_CALLHOOK(LogDeath_AppendItemCodes, player, s);
102  s = M_ARGV(1, string);
103  return s;
104 }
#define PHYS_INPUT_BUTTON_CHAT(s)
Definition: player.qh:155
float cnt
Definition: powerups.qc:24
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
const int MAX_WEAPONSLOTS
Definition: weapon.qh:13
#define M_ARGV(x, type)
Definition: events.qh:17
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bool()

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

◆ Damage()

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

Definition at line 583 of file damage.qc.

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_frozen_damage_trigger, autocvar_g_frozen_force, autocvar_g_frozen_revive_falldamage, autocvar_g_frozen_revive_falldamage_health, 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(), DEAD_NO, DEATH_ISSPECIAL, DEATH_ISWEAPON, DEATH_WEAPONOF, DIFF_TEAM, EF_TELEPORT_BIT, entity(), FL_GODMODE, FORCETYPE_FORCEATPOS, FRAGS_SPECTATOR, GetResource(), HITTYPE_SOUND, hook, impressive_hits, IS_CLIENT, IS_DEAD, IS_INDEPENDENT_PLAYER, IS_MONSTER, IS_PLAYER, IS_TURRET, IS_VEHICLE, IsFlying(), ITEM_DAMAGE_NEEDKILL, killcount, M_ARGV, MAX_WEAPONSLOTS, MOVETYPE_NOCLIP, MOVETYPE_PHYSICS, MUTATOR_CALLHOOK, normalize(), NULL, PHYS_INPUT_BUTTON_CHAT, RemoveHook(), RES_HEALTH, SAME_TEAM, SelectSpawnPoint(), setorigin(), SetResource(), SetResourceExplicit(), setthink, STATUSEFFECT_REMOVE_CLEAR, teamkill_complain, time, Unfreeze(), UNSET_ONGROUND, UpdateCSQCProjectile(), v, vector(), vehicles_exit(), vlen(), weaponentities, and yoda.

Referenced by buff_Vengeance_DelayedDamage(), checkpoint_passed(), ClientKill_Now(), CommonCommand_editmob(), CreatureFrame_FallDamage(), CreatureFrame_hotliquids(), ctf_CaptureShield_Touch(), Damage(), door_blocked(), door_generic_plat_blocked(), DrownPlayer(), Fire_ApplyDamage(), fireBullet_antilag(), generic_plat_blocked(), havocbot_role_ctf_carrier(), instagib_countdown(), KillPlayerForTeamChange(), Monster_Attack_Melee(), Monster_Move(), Monster_Think(), MUTATOR_HOOKFUNCTION(), ons_CaptureShield_Touch(), Onslaught_CheckWinner(), plat_crush(), RadiusDamageForSource(), vehicles_impact(), and vehicles_touch().

584 {
585  float complainteamdamage = 0;
586  float mirrordamage = 0;
587  float mirrorforce = 0;
588 
589  if (game_stopped || (IS_CLIENT(targ) && CS(targ).killcount == FRAGS_SPECTATOR))
590  return;
591 
592  entity attacker_save = attacker;
593 
594  // special rule: gravity bombs and sound-based attacks do not affect team mates (other than for disconnecting the hook)
595  if(DEATH_ISWEAPON(deathtype, WEP_HOOK) || (deathtype & HITTYPE_SOUND))
596  {
597  if(IS_PLAYER(targ) && SAME_TEAM(targ, attacker))
598  {
599  return;
600  }
601  }
602 
603  if(deathtype == DEATH_KILL.m_id || deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
604  {
605  // exit the vehicle before killing (fixes a crash)
606  if(IS_PLAYER(targ) && targ.vehicle)
607  vehicles_exit(targ.vehicle, VHEF_RELEASE);
608 
609  // These are ALWAYS lethal
610  // No damage modification here
611  // Instead, prepare the victim for his death...
612  if(deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
613  {
614  SetResourceExplicit(targ, RES_ARMOR, 0);
615  SetResourceExplicit(targ, RES_HEALTH, 0.9); // this is < 1
616  }
617  StatusEffects_remove(STATUSEFFECT_SpawnShield, targ, STATUSEFFECT_REMOVE_CLEAR);
618  targ.flags -= targ.flags & FL_GODMODE;
619  damage = 100000;
620  }
621  else if(deathtype == DEATH_MIRRORDAMAGE.m_id || deathtype == DEATH_NOAMMO.m_id)
622  {
623  // no processing
624  }
625  else
626  {
627  // nullify damage if teamplay is on
628  if(deathtype != DEATH_TELEFRAG.m_id)
629  if(IS_PLAYER(attacker))
630  {
631  if(IS_PLAYER(targ) && targ != attacker && (IS_INDEPENDENT_PLAYER(attacker) || IS_INDEPENDENT_PLAYER(targ)))
632  {
633  damage = 0;
634  force = '0 0 0';
635  }
636  else if(!STAT(FROZEN, targ) && SAME_TEAM(attacker, targ))
637  {
638  if(autocvar_teamplay_mode == 1)
639  damage = 0;
640  else if(attacker != targ)
641  {
642  if(autocvar_teamplay_mode == 2)
643  {
644  if(IS_PLAYER(targ) && !IS_DEAD(targ))
645  {
646  attacker.dmg_team = attacker.dmg_team + damage;
647  complainteamdamage = attacker.dmg_team - autocvar_g_teamdamage_threshold;
648  }
649  }
650  else if(autocvar_teamplay_mode == 3)
651  damage = 0;
652  else if(autocvar_teamplay_mode == 4)
653  {
654  if(IS_PLAYER(targ) && !IS_DEAD(targ))
655  {
656  attacker.dmg_team = attacker.dmg_team + damage;
657  complainteamdamage = attacker.dmg_team - autocvar_g_teamdamage_threshold;
658  if(complainteamdamage > 0)
659  mirrordamage = autocvar_g_mirrordamage * complainteamdamage;
660  mirrorforce = autocvar_g_mirrordamage * vlen(force);
661  damage = autocvar_g_friendlyfire * damage;
662  // mirrordamage will be used LATER
663 
665  {
666  vector v = healtharmor_applydamage(GetResource(attacker, RES_ARMOR), autocvar_g_balance_armor_blockpercent, deathtype, mirrordamage);
667  attacker.dmg_take += v.x;
668  attacker.dmg_save += v.y;
669  attacker.dmg_inflictor = inflictor;
670  mirrordamage = v.z;
671  mirrorforce = 0;
672  }
673 
675  {
676  vector v = healtharmor_applydamage(GetResource(targ, RES_ARMOR), autocvar_g_balance_armor_blockpercent, deathtype, damage);
677  targ.dmg_take += v.x;
678  targ.dmg_save += v.y;
679  targ.dmg_inflictor = inflictor;
680  damage = 0;
682  force = '0 0 0';
683  }
684  }
685  else if(!targ.canteamdamage)
686  damage = 0;
687  }
688  }
689  }
690  }
691 
692  if (!DEATH_ISSPECIAL(deathtype))
693  {
695  mirrordamage *= autocvar_g_weapondamagefactor;
696  complainteamdamage *= autocvar_g_weapondamagefactor;
697  force = force * autocvar_g_weaponforcefactor;
698  mirrorforce *= autocvar_g_weaponforcefactor;
699  }
700 
701  // should this be changed at all? If so, in what way?
702  MUTATOR_CALLHOOK(Damage_Calculate, inflictor, attacker, targ, deathtype, damage, mirrordamage, force, attacker.(weaponentity));
703  damage = M_ARGV(4, float);
704  mirrordamage = M_ARGV(5, float);
705  force = M_ARGV(6, vector);
706 
707  if(IS_PLAYER(targ) && damage > 0 && attacker)
708  {
709  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
710  {
711  .entity went = weaponentities[slot];
712  if(targ.(went).hook && targ.(went).hook.aiment == attacker)
713  RemoveHook(targ.(went).hook);
714  }
715  }
716 
717  if(STAT(FROZEN, targ) && !ITEM_DAMAGE_NEEDKILL(deathtype)
718  && deathtype != DEATH_TEAMCHANGE.m_id && deathtype != DEATH_AUTOTEAMCHANGE.m_id)
719  {
720  if(autocvar_g_frozen_revive_falldamage > 0 && deathtype == DEATH_FALL.m_id && damage >= autocvar_g_frozen_revive_falldamage)
721  {
722  Unfreeze(targ, false);
724  Send_Effect(EFFECT_ICEORGLASS, targ.origin, '0 0 0', 3);
725  Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED_FALL, targ.netname);
726  Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_FREEZETAG_REVIVE_SELF);
727  }
728 
729  damage = 0;
730  force *= autocvar_g_frozen_force;
731  }
732 
733  if(IS_PLAYER(targ) && STAT(FROZEN, targ)
735  {
736  Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
737 
738  entity spot = SelectSpawnPoint(targ, false);
739  if(spot)
740  {
741  damage = 0;
742  targ.deadflag = DEAD_NO;
743 
744  targ.angles = spot.angles;
745 
746  targ.effects = 0;
747  targ.effects |= EF_TELEPORT_BIT;
748 
749  targ.angles_z = 0; // never spawn tilted even if the spot says to
750  targ.fixangle = true; // turn this way immediately
751  targ.velocity = '0 0 0';
752  targ.avelocity = '0 0 0';
753  targ.punchangle = '0 0 0';
754  targ.punchvector = '0 0 0';
755  targ.oldvelocity = targ.velocity;
756 
757  targ.spawnorigin = spot.origin;
758  setorigin(targ, spot.origin + '0 0 1' * (1 - targ.mins.z - 24));
759  // don't reset back to last position, even if new position is stuck in solid
760  targ.oldorigin = targ.origin;
761 
762  Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
763  }
764  }
765 
766  if (targ == attacker)
767  damage = damage * autocvar_g_balance_selfdamagepercent; // Partial damage if the attacker hits himself
768 
769  // count the damage
770  if(attacker)
771  if(!IS_DEAD(targ))
772  if(deathtype != DEATH_BUFF.m_id)
773  if(targ.takedamage == DAMAGE_AIM)
774  if(targ != attacker)
775  {
776  entity victim;
777  if(IS_VEHICLE(targ) && targ.owner)
778  victim = targ.owner;
779  else
780  victim = targ;
781 
782  if(IS_PLAYER(victim) || (IS_TURRET(victim) && victim.active == ACTIVE_ACTIVE) || IS_MONSTER(victim) || MUTATOR_CALLHOOK(PlayHitsound, victim, attacker))
783  {
784  if (DIFF_TEAM(victim, attacker))
785  {
786  if(damage > 0)
787  {
788  if(deathtype != DEATH_FIRE.m_id)
789  {
790  if(PHYS_INPUT_BUTTON_CHAT(victim))
791  attacker.typehitsound += 1;
792  else
793  attacker.hitsound_damage_dealt += damage;
794  }
795 
796  impressive_hits += 1;
797 
798  if (!DEATH_ISSPECIAL(deathtype))
799  {
800  if(IS_PLAYER(targ)) // don't do this for vehicles
801  if(IsFlying(victim))
802  yoda = 1;
803  }
804  }
805  }
806  else if (IS_PLAYER(attacker) && !STAT(FROZEN, victim)) // same team
807  {
808  if (deathtype != DEATH_FIRE.m_id)
809  {
810  attacker.typehitsound += 1;
811  }
812  if(complainteamdamage > 0)
813  if(time > CS(attacker).teamkill_complain)
814  {
815  CS(attacker).teamkill_complain = time + 5;
816  CS(attacker).teamkill_soundtime = time + 0.4;
817  CS(attacker).teamkill_soundsource = targ;
818  }
819  }
820  }
821  }
822  }
823 
824  // apply push
825  if (targ.damageforcescale)
826  if (force)
827  if (!IS_PLAYER(targ) || !StatusEffects_active(STATUSEFFECT_SpawnShield, targ) || targ == attacker)
828  {
829  vector farce = damage_explosion_calcpush(targ.damageforcescale * force, targ.velocity, autocvar_g_balance_damagepush_speedfactor);
830  if(targ.move_movetype == MOVETYPE_PHYSICS)
831  {
832  entity farcent = new(farce);
833  farcent.enemy = targ;
834  farcent.movedir = farce * 10;
835  if(targ.mass)
836  farcent.movedir = farcent.movedir * targ.mass;
837  farcent.origin = hitloc;
838  farcent.forcetype = FORCETYPE_FORCEATPOS;
839  farcent.nextthink = time + 0.1;
840  setthink(farcent, SUB_Remove);
841  }
842  else if(targ.move_movetype != MOVETYPE_NOCLIP)
843  {
844  targ.velocity = targ.velocity + farce;
845  }
846  UNSET_ONGROUND(targ);
847  UpdateCSQCProjectile(targ);
848  }
849  // apply damage
850  if (damage != 0 || (targ.damageforcescale && force))
851  if (targ.event_damage)
852  targ.event_damage (targ, inflictor, attacker, damage, deathtype, weaponentity, hitloc, force);
853 
854  // apply mirror damage if any
855  if(!autocvar_g_mirrordamage_onlyweapons || DEATH_WEAPONOF(deathtype) != WEP_Null)
856  if(mirrordamage > 0 || mirrorforce > 0)
857  {
858  attacker = attacker_save;
859 
860  force = normalize(attacker.origin + attacker.view_ofs - hitloc) * mirrorforce;
861  Damage(attacker, inflictor, attacker, mirrordamage, DEATH_MIRRORDAMAGE.m_id, weaponentity, attacker.origin, force);
862  }
863 }
entity SelectSpawnPoint(entity this, bool anypoint)
Definition: spawnpoints.qc:329
#define PHYS_INPUT_BUTTON_CHAT(s)
Definition: player.qh:155
const int HITTYPE_SOUND
Definition: all.qh:30
bool autocvar_g_frozen_damage_trigger
Definition: damage.qh:30
entity hook
Definition: hook.qh:19
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
Definition: cl_resources.qc:15
const float MOVETYPE_PHYSICS
#define IS_CLIENT(v)
Definition: utils.qh:13
float teamkill_complain
Definition: damage.qh:57
#define IS_INDEPENDENT_PLAYER(e)
Definition: client.qh:314
float autocvar_g_frozen_revive_falldamage
Definition: damage.qh:28
const float FORCETYPE_FORCEATPOS
entity() spawn
vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor)
Definition: calculations.qc:45
float DAMAGE_AIM
Definition: progsdefs.qc:284
ClientState CS(Client this)
Definition: state.qh:47
float autocvar_g_friendlyfire_virtual
Definition: damage.qh:26
#define IS_MONSTER(v)
Definition: utils.qh:21
float FL_GODMODE
Definition: progsdefs.qc:237
#define DIFF_TEAM(a, b)
Definition: teams.qh:240
int killcount
Definition: client.qh:317
#define UNSET_ONGROUND(s)
Definition: movetypes.qh:18
int impressive_hits
Definition: damage.qh:52
int autocvar_g_frozen_revive_falldamage_health
Definition: damage.qh:29
#define DEATH_WEAPONOF(t)
Definition: all.qh:41
#define IS_TURRET(v)
Definition: utils.qh:23
const int EF_TELEPORT_BIT
float autocvar_g_frozen_force
Definition: damage.qh:31
RES_HEALTH
Definition: ent_cs.qc:126
void Unfreeze(entity targ, bool reset_health)
Definition: damage.qc:546
Effect is being forcibly removed without calling any additional mechanics.
Definition: all.qh:27
bool autocvar_g_mirrordamage_onlyweapons
Definition: damage.qh:16
float autocvar_g_friendlyfire_virtual_force
Definition: damage.qh:27
float autocvar_g_weapondamagefactor
Definition: weaponsystem.qh:7
float autocvar_g_balance_selfdamagepercent
Definition: damage.qh:24
float autocvar_g_teamdamage_threshold
Definition: damage.qh:23
void UpdateCSQCProjectile(entity e)
int autocvar_teamplay_mode
Definition: teamplay.qh:3
void SetResource(entity e, Resource res_type, float amount)
Sets the current amount of resource the given entity will have.
Definition: cl_resources.qc:26
const int MAX_WEAPONSLOTS
Definition: weapon.qh:13
const int ACTIVE_ACTIVE
Definition: defs.qh:37
#define NULL
Definition: post.qh:17
float autocvar_g_friendlyfire
Definition: damage.qh:25
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition: damage.qc:583
#define SAME_TEAM(a, b)
Definition: teams.qh:239
#define M_ARGV(x, type)
Definition: events.qh:17
#define IS_DEAD(s)
Definition: utils.qh:26
bool IsFlying(entity this)
Definition: player.qc:804
float autocvar_g_balance_damagepush_speedfactor
Definition: damage.qh:18
float autocvar_g_weaponforcefactor
Definition: weaponsystem.qh:6
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#define IS_VEHICLE(v)
Definition: utils.qh:22
#define ITEM_DAMAGE_NEEDKILL(dt)
Definition: items.qh:130
float MOVETYPE_NOCLIP
Definition: progsdefs.qc:254
vector v
Definition: ent_cs.qc:116
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
bool autocvar_g_mirrordamage_virtual
Definition: damage.qh:15
float autocvar_g_mirrordamage
Definition: damage.qh:14
const int FRAGS_SPECTATOR
Definition: constants.qh:4
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
setorigin(ent, v)
float DEAD_NO
Definition: progsdefs.qc:274
#define setthink(e, f)
void vehicles_exit(entity vehic, bool eject)
Definition: sv_vehicles.qc:788
#define DEATH_ISWEAPON(t, w)
Definition: all.qh:42
#define DEATH_ISSPECIAL(t)
Definition: all.qh:35
float autocvar_g_balance_armor_blockpercent
Definition: damage.qh:21
float time
Definition: csprogsdefs.qc:16
#define IS_PLAYER(v)
Definition: utils.qh:9
float yoda
Definition: damage.qh:51
void RemoveHook(entity this)
Definition: hook.qc:96
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Damage_DamageInfo()

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

Referenced by fireBullet_antilag(), FireRailgunBullet(), and RadiusDamageForSource().

+ Here is the caller graph for this function:

◆ Damage_DamageInfo_SendEntity()

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

◆ Fire_AddDamage()

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

Definition at line 1077 of file damage.qc.

References accuracy_add(), accuracy_isgooddamage(), DEATH_WEAPONOF, IS_DEAD, IS_PLAYER, max(), min(), and time.

Referenced by CreatureFrame_hotliquids(), and MUTATOR_HOOKFUNCTION().

1078 {
1079  float dps;
1080  float maxtime, mintime, maxdamage, mindamage, maxdps, mindps, totaldamage, totaltime;
1081 
1082  if(IS_PLAYER(e))
1083  {
1084  if(IS_DEAD(e))
1085  return -1;
1086  }
1087 
1088  t = max(t, 0.1);
1089  dps = d / t;
1090  if(StatusEffects_active(STATUSEFFECT_Burning, e))
1091  {
1092  float fireendtime = StatusEffects_gettime(STATUSEFFECT_Burning, e);
1093 
1094  mintime = fireendtime - time;
1095  maxtime = max(mintime, t);
1096 
1097  mindps = e.fire_damagepersec;
1098  maxdps = max(mindps, dps);
1099 
1100  if(maxtime > mintime || maxdps > mindps)
1101  {
1102  // Constraints:
1103 
1104  // damage we have right now
1105  mindamage = mindps * mintime;
1106 
1107  // damage we want to get
1108  maxdamage = mindamage + d;
1109 
1110  // but we can't exceed maxtime * maxdps!
1111  totaldamage = min(maxdamage, maxtime * maxdps);
1112 
1113  // LEMMA:
1114  // Look at:
1115  // totaldamage = min(mindamage + d, maxtime * maxdps)
1116  // We see:
1117  // totaldamage <= maxtime * maxdps
1118  // ==> totaldamage / maxdps <= maxtime.
1119  // We also see:
1120  // totaldamage / mindps = min(mindamage / mindps + d, maxtime * maxdps / mindps)
1121  // >= min(mintime, maxtime)
1122  // ==> totaldamage / maxdps >= mintime.
1123 
1124  /*
1125  // how long do we damage then?
1126  // at least as long as before
1127  // but, never exceed maxdps
1128  totaltime = max(mintime, totaldamage / maxdps); // always <= maxtime due to lemma
1129  */
1130 
1131  // alternate:
1132  // at most as long as maximum allowed
1133  // but, never below mindps
1134  totaltime = min(maxtime, totaldamage / mindps); // always >= mintime due to lemma
1135 
1136  // assuming t > mintime, dps > mindps:
1137  // we get d = t * dps = maxtime * maxdps
1138  // totaldamage = min(maxdamage, maxtime * maxdps) = min(... + d, maxtime * maxdps) = maxtime * maxdps
1139  // totaldamage / maxdps = maxtime
1140  // totaldamage / mindps > totaldamage / maxdps = maxtime
1141  // FROM THIS:
1142  // a) totaltime = max(mintime, maxtime) = maxtime
1143  // b) totaltime = min(maxtime, totaldamage / maxdps) = maxtime
1144 
1145  // assuming t <= mintime:
1146  // we get maxtime = mintime
1147  // a) totaltime = max(mintime, ...) >= mintime, also totaltime <= maxtime by the lemma, therefore totaltime = mintime = maxtime
1148  // b) totaltime = min(maxtime, ...) <= maxtime, also totaltime >= mintime by the lemma, therefore totaltime = mintime = maxtime
1149 
1150  // assuming dps <= mindps:
1151  // we get mindps = maxdps.
1152  // With this, the lemma says that mintime <= totaldamage / mindps = totaldamage / maxdps <= maxtime.
1153  // a) totaltime = max(mintime, totaldamage / maxdps) = totaldamage / maxdps
1154  // b) totaltime = min(maxtime, totaldamage / mindps) = totaldamage / maxdps
1155 
1156  e.fire_damagepersec = totaldamage / totaltime;
1157  StatusEffects_apply(STATUSEFFECT_Burning, e, time + totaltime, 0);
1158  if(totaldamage > 1.2 * mindamage)
1159  {
1160  e.fire_deathtype = dt;
1161  if(e.fire_owner != o)
1162  {
1163  e.fire_owner = o;
1164  e.fire_hitsound = false;
1165  }
1166  }
1167  if(accuracy_isgooddamage(o, e))
1168  accuracy_add(o, DEATH_WEAPONOF(dt), 0, max(0, totaldamage - mindamage));
1169  return max(0, totaldamage - mindamage); // can never be negative, but to make sure
1170  }
1171  else
1172  return 0;
1173  }
1174  else
1175  {
1176  e.fire_damagepersec = dps;
1177  StatusEffects_apply(STATUSEFFECT_Burning, e, time + t, 0);
1178  e.fire_deathtype = dt;
1179  e.fire_owner = o;
1180  e.fire_hitsound = false;
1181  if(accuracy_isgooddamage(o, e))
1182  accuracy_add(o, DEATH_WEAPONOF(dt), 0, d);
1183  return d;
1184  }
1185 }
#define DEATH_WEAPONOF(t)
Definition: all.qh:41
#define IS_DEAD(s)
Definition: utils.qh:26
void accuracy_add(entity this, Weapon w, float fired, float hit)
Definition: accuracy.qc:83
bool accuracy_isgooddamage(entity attacker, entity targ)
Definition: accuracy.qc:112
float time
Definition: csprogsdefs.qc:16
#define IS_PLAYER(v)
Definition: utils.qh:9
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Fire_ApplyDamage()

void Fire_ApplyDamage ( entity  e)

Definition at line 1187 of file damage.qc.

References Damage(), DMG_NOWEP, entity(), frametime, g_damagedbycontents, IL_EACH, IS_INDEPENDENT_PLAYER, IS_NOT_A_CLIENT, min(), and time.

1188 {
1189  float t, d, hi, ty;
1190  entity o;
1191 
1192  for(t = 0, o = e.owner; o.owner && t < 16; o = o.owner, ++t);
1193  if(IS_NOT_A_CLIENT(o))
1194  o = e.fire_owner;
1195 
1196  float fireendtime = StatusEffects_gettime(STATUSEFFECT_Burning, e);
1197  t = min(frametime, fireendtime - time);
1198  d = e.fire_damagepersec * t;
1199 
1200  hi = e.fire_owner.hitsound_damage_dealt;
1201  ty = e.fire_owner.typehitsound;
1202  Damage(e, e, e.fire_owner, d, e.fire_deathtype, DMG_NOWEP, e.origin, '0 0 0');
1203  if(e.fire_hitsound && e.fire_owner)
1204  {
1205  e.fire_owner.hitsound_damage_dealt = hi;
1206  e.fire_owner.typehitsound = ty;
1207  }
1208  e.fire_hitsound = true;
1209 
1210  if(!IS_INDEPENDENT_PLAYER(e) && !STAT(FROZEN, e))
1211  {
1212  IL_EACH(g_damagedbycontents, it.damagedbycontents && it != e,
1213  {
1214  if(!IS_DEAD(it) && it.takedamage && !IS_INDEPENDENT_PLAYER(it))
1215  if(boxesoverlap(e.absmin, e.absmax, it.absmin, it.absmax))
1216  {
1217  t = autocvar_g_balance_firetransfer_time * (fireendtime - time);
1218  d = autocvar_g_balance_firetransfer_damage * e.fire_damagepersec * t;
1219  Fire_AddDamage(it, o, d, t, DEATH_FIRE.m_id);
1220  }
1221  });
1222  }
1223 }
#define IL_EACH(this, cond, body)
#define IS_INDEPENDENT_PLAYER(e)
Definition: client.qh:314
IntrusiveList g_damagedbycontents
Definition: damage.qh:155
entity() spawn
#define DMG_NOWEP
Definition: damage.qh:126
float frametime
Definition: csprogsdefs.qc:17
#define IS_NOT_A_CLIENT(v)
was: (clienttype(v) == CLIENTTYPE_NOTACLIENT)
Definition: utils.qh:19
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition: damage.qc:583
float time
Definition: csprogsdefs.qc:16
+ Here is the call graph for this function:

◆ Freeze()

void Freeze ( entity  targ,
float  revivespeed,
int  frozen_type,
bool  show_waypoint 
)

Definition at line 494 of file damage.qc.

References entity(), floor(), FOREACH_CLIENT, Freeze(), FROZEN_TEMP_DYING, g_bot_targets, Ice_Think(), IL_REMOVE(), IS_MONSTER, IS_PLAYER, MAX_WEAPONSLOTS, MUTATOR_CALLHOOK, NULL, random(), RemoveGrapplingHooks(), RemoveHook(), RES_HEALTH, setmodel, SetResource(), setthink, start_health, Team_ColorRGB(), time, and weaponentities.

Referenced by Freeze(), and freezetag_Freeze().

495 {
496  if(!IS_PLAYER(targ) && !IS_MONSTER(targ)) // TODO: only specified entities can be freezed
497  return;
498 
499  if(STAT(FROZEN, targ))
500  return;
501 
502  float targ_maxhealth = ((IS_MONSTER(targ)) ? targ.max_health : start_health);
503 
504  STAT(FROZEN, targ) = frozen_type;
505  STAT(REVIVE_PROGRESS, targ) = ((frozen_type == FROZEN_TEMP_DYING) ? 1 : 0);
506  SetResource(targ, RES_HEALTH, ((frozen_type == FROZEN_TEMP_DYING) ? targ_maxhealth : 1));
507  targ.revive_speed = revivespeed;
508  if(targ.bot_attack)
509  IL_REMOVE(g_bot_targets, targ);
510  targ.bot_attack = false;
511  targ.freeze_time = time;
512 
513  entity ice = new(ice);
514  ice.owner = targ;
515  ice.scale = targ.scale;
516  // set_movetype(ice, MOVETYPE_FOLLOW) would rotate the ice model with the player
517  setthink(ice, Ice_Think);
518  ice.nextthink = time;
519  ice.frame = floor(random() * 21); // ice model has 20 different looking frames
520  setmodel(ice, MDL_ICE);
521  ice.alpha = 1;
522  ice.colormod = Team_ColorRGB(targ.team);
523  ice.glowmod = ice.colormod;
524  targ.iceblock = ice;
525  targ.revival_time = 0;
526 
527  Ice_Think(ice);
528 
529  RemoveGrapplingHooks(targ);
530 
532  {
533  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
534  {
535  .entity weaponentity = weaponentities[slot];
536  if(it.(weaponentity).hook.aiment == targ)
537  RemoveHook(it.(weaponentity).hook);
538  }
539  });
540 
541  // add waypoint
542  if(MUTATOR_CALLHOOK(Freeze, targ, revivespeed, frozen_type) || show_waypoint)
543  WaypointSprite_Spawn(WP_Frozen, 0, 0, targ, '0 0 64', NULL, targ.team, targ, waypointsprite_attached, true, RADARICON_WAYPOINT);
544 }
ERASEABLE void IL_REMOVE(IntrusiveList this, entity it)
Remove any element, anywhere in the list.
vector Team_ColorRGB(int teamid)
Definition: teams.qh:76
entity() spawn
void Freeze(entity targ, float revivespeed, int frozen_type, bool show_waypoint)
Definition: damage.qc:494
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
#define IS_MONSTER(v)
Definition: utils.qh:21
IntrusiveList g_bot_targets
Definition: api.qh:149
#define setmodel(this, m)
Definition: model.qh:26
RES_HEALTH
Definition: ent_cs.qc:126
void SetResource(entity e, Resource res_type, float amount)
Sets the current amount of resource the given entity will have.
Definition: cl_resources.qc:26
const int MAX_WEAPONSLOTS
Definition: weapon.qh:13
void Ice_Think(entity this)
Definition: damage.qc:481
#define NULL
Definition: post.qh:17
void RemoveGrapplingHooks(entity pl)
Definition: hook.qc:78
float start_health
Definition: world.qh:98
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
#define setthink(e, f)
float time
Definition: csprogsdefs.qc:16
const int FROZEN_TEMP_DYING
Definition: damage.qh:111
#define IS_PLAYER(v)
Definition: utils.qh:9
void RemoveHook(entity this)
Definition: hook.qc:96
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GiveFrags()

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

Definition at line 49 of file damage.qc.

References GameRules_scoring_add, M_ARGV, MUTATOR_CALLHOOK, UpdateFrags(), and warmup_stage.

Referenced by Obituary().

50 {
51  // TODO route through PlayerScores instead
52  if(game_stopped) return;
53 
54  if(f < 0)
55  {
56  if(targ == attacker)
57  {
58  // suicide
59  GameRules_scoring_add(attacker, SUICIDES, 1);
60  }
61  else
62  {
63  // teamkill
64  GameRules_scoring_add(attacker, TEAMKILLS, 1);
65  }
66  }
67  else
68  {
69  // regular frag
70  GameRules_scoring_add(attacker, KILLS, 1);
71  if(!warmup_stage && targ.playerid)
72  PlayerStats_GameReport_Event_Player(attacker, sprintf("kills-%d", targ.playerid), 1);
73  }
74 
75  GameRules_scoring_add(targ, DEATHS, 1);
76 
77  // FIXME fix the mess this is (we have REAL points now!)
78  if(MUTATOR_CALLHOOK(GiveFragsForKill, attacker, targ, f, deathtype, attacker.(weaponentity)))
79  f = M_ARGV(2, float);
80 
81  attacker.totalfrags += f;
82 
83  if(f)
84  UpdateFrags(attacker, f);
85 }
#define GameRules_scoring_add(client, fld, value)
Definition: sv_rules.qh:78
bool warmup_stage
Definition: main.qh:103
void UpdateFrags(entity player, int f)
Definition: damage.qc:44
#define M_ARGV(x, type)
Definition: events.qh:17
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Heal()

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

Definition at line 1063 of file damage.qc.

References CS(), FRAGS_SPECTATOR, IS_CLIENT, IS_DEAD, and killcount.

1064 {
1065  if(game_stopped || (IS_CLIENT(targ) && CS(targ).killcount == FRAGS_SPECTATOR) || STAT(FROZEN, targ) || IS_DEAD(targ))
1066  return false;
1067 
1068  bool healed = false;
1069  if(targ.event_heal)
1070  healed = targ.event_heal(targ, inflictor, amount, limit);
1071  // TODO: additional handling? what if the healing kills them? should this abort if healing would do so etc
1072  // TODO: healing fx!
1073  // TODO: armor healing?
1074  return healed;
1075 }
#define IS_CLIENT(v)
Definition: utils.qh:13
ClientState CS(Client this)
Definition: state.qh:47
int killcount
Definition: client.qh:317
#define IS_DEAD(s)
Definition: utils.qh:26
const int FRAGS_SPECTATOR
Definition: constants.qh:4
+ Here is the call graph for this function:

◆ Ice_Think()

void Ice_Think ( entity  this)

Definition at line 481 of file damage.qc.

References nextthink, origin, owner, setorigin(), time, and vector().

Referenced by Freeze().

482 {
483  if(!STAT(FROZEN, this.owner) || this.owner.iceblock != this)
484  {
485  delete(this);
486  return;
487  }
488  vector ice_org = this.owner.origin - '0 0 16';
489  if (this.origin != ice_org)
490  setorigin(this, ice_org);
491  this.nextthink = time;
492 }
origin
Definition: ent_cs.qc:114
entity owner
Definition: main.qh:73
float nextthink
Definition: csprogsdefs.qc:121
vector(float skel, float bonenum) _skel_get_boneabs_hidden
setorigin(ent, v)
float time
Definition: csprogsdefs.qc:16
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ IsFlying()

float IsFlying ( entity  a)

Definition at line 804 of file player.qc.

References CS(), CSQC_ClientMovement_PlayerMove_Frame(), csqcmodel_modelflags, entity(), frametime, intermission, IS_DEAD, IS_ONGROUND, IS_REAL_CLIENT, ITEMS_STAT, maxs, MF_ROCKET, mins, MOVE_NORMAL, origin, PM_UpdateButtons(), sys_phys_update(), trace_fraction, waterlevel, and WATERLEVEL_SWIMMING.

Referenced by Damage(), and sys_phys_update().

805 {
806  if(IS_ONGROUND(this))
807  return false;
808  if(this.waterlevel >= WATERLEVEL_SWIMMING)
809  return false;
810  tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 24', MOVE_NORMAL, this);
811  //traceline(this.origin, this.origin - '0 0 48', MOVE_NORMAL, this);
812  if(trace_fraction < 1)
813  return false;
814  return true;
815 }
float waterlevel
Definition: progsdefs.qc:181
const float MOVE_NORMAL
Definition: csprogsdefs.qc:252
#define IS_ONGROUND(s)
Definition: movetypes.qh:16
vector maxs
Definition: csprogsdefs.qc:113
origin
Definition: ent_cs.qc:114
vector mins
Definition: csprogsdefs.qc:113
const int WATERLEVEL_SWIMMING
Definition: movetypes.qh:13
float trace_fraction
Definition: csprogsdefs.qc:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ LogDeath()

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

Definition at line 106 of file damage.qc.

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

Referenced by Obituary().

107 {
108  string s;
110  return;
111  s = strcat(":kill:", mode);
112  s = strcat(s, ":", ftos(killer.playerid));
113  s = strcat(s, ":", ftos(killed.playerid));
114  s = strcat(s, ":type=", Deathtype_Name(deathtype));
115  s = strcat(s, ":items=");
116  s = AppendItemcodes(s, killer);
117  if(killed != killer)
118  {
119  s = strcat(s, ":victimitems=");
120  s = AppendItemcodes(s, killed);
121  }
122  GameLogEcho(s);
123 }
string Deathtype_Name(int deathtype)
Definition: all.qc:3
string AppendItemcodes(string s, entity player)
Definition: damage.qc:87
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
void GameLogEcho(string s)
Definition: gamelog.qc:12
bool autocvar_sv_eventlog
Definition: gamelog.qh:3
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Obituary()

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

Definition at line 229 of file damage.qc.

References APP_TEAM_NUM, backtrace, buff_FirstFromFlags(), checkrules_firstblood, CS(), DEATH_ENT, DEATH_ISSPECIAL, deathmessage, Deathtype_Name(), 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, RES_HEALTH, SAME_TEAM, strcat(), strstrofs, time, and warmup_stage.

Referenced by PlayerDamage().

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

◆ Obituary_SpecialDeath()

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

Definition at line 125 of file damage.qc.

References backtrace, DEATH_ISSPECIAL, DT_FIRST, entity(), g_cts, and REGISTRY_GET.

Referenced by Obituary().

131 {
132  if(!DEATH_ISSPECIAL(deathtype))
133  {
134  backtrace("Obituary_SpecialDeath called without a special deathtype?\n");
135  return;
136  }
137 
138  entity deathent = REGISTRY_GET(Deathtypes, deathtype - DT_FIRST);
139  if (!deathent)
140  {
141  backtrace("Obituary_SpecialDeath: Could not find deathtype entity!\n");
142  return;
143  }
144 
145  if(g_cts && deathtype == DEATH_KILL.m_id)
146  return; // TODO: somehow put this in CTS gamemode file!
147 
148  Notification death_message = (murder) ? deathent.death_msgmurder : deathent.death_msgself;
149  if(death_message)
150  {
151  Send_Notification_WOCOVA(
152  NOTIF_ONE,
153  notif_target,
154  MSG_MULTI,
155  death_message,
156  s1, s2, s3, "",
157  f1, f2, f3, 0
158  );
159  Send_Notification_WOCOVA(
160  NOTIF_ALL_EXCEPT,
161  notif_target,
162  MSG_INFO,
163  death_message.nent_msginfo,
164  s1, s2, s3, "",
165  f1, f2, f3, 0
166  );
167  }
168 }
spree_inf s1 s2 s3loc s2 s1
Definition: all.inc:265
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 s2loc s1 s2 f1 f1points s1 s2
Definition: all.inc:438
entity() spawn
const int DT_FIRST
Definition: all.qh:33
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1
Definition: all.inc:654
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 s2loc s1 s2 f1 f1points f2
Definition: all.inc:348
#define g_cts
Definition: cts.qh:36
#define backtrace(msg)
Definition: log.qh:105
entity Notification
always last
Definition: all.qh:82
#define DEATH_ISSPECIAL(t)
Definition: all.qh:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Obituary_WeaponDeath()

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

Definition at line 170 of file damage.qc.

References DEATH_WEAPONOF, LOG_TRACEF, Weapon::netname, and w_deathtype.

Referenced by Obituary().

176 {
177  Weapon death_weapon = DEATH_WEAPONOF(deathtype);
178  if (death_weapon == WEP_Null)
179  return false;
180 
181  w_deathtype = deathtype;
182  Notification death_message = ((murder) ? death_weapon.wr_killmessage(death_weapon) : death_weapon.wr_suicidemessage(death_weapon));
183  w_deathtype = false;
184 
185  if (death_message)
186  {
187  Send_Notification_WOCOVA(
188  NOTIF_ONE,
189  notif_target,
190  MSG_MULTI,
191  death_message,
192  s1, s2, s3, "",
193  f1, f2, 0, 0
194  );
195  // send the info part to everyone
196  Send_Notification_WOCOVA(
197  NOTIF_ALL_EXCEPT,
198  notif_target,
199  MSG_INFO,
200  death_message.nent_msginfo,
201  s1, s2, s3, "",
202  f1, f2, 0, 0
203  );
204  }
205  else
206  {
207  LOG_TRACEF(
208  "Obituary_WeaponDeath(): ^1Deathtype ^7(%d)^1 has no notification for weapon %s!\n",
209  deathtype,
210  death_weapon.netname
211  );
212  }
213 
214  return true;
215 }
spree_inf s1 s2 s3loc s2 s1
Definition: all.inc:265
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 s2loc s1 s2 f1 f1points s1 s2
Definition: all.inc:438
#define DEATH_WEAPONOF(t)
Definition: all.qh:41
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1
Definition: all.inc:654
string netname
M: refname : reference name name.
Definition: weapon.qh:76
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 s2loc s1 s2 f1 f1points f2
Definition: all.inc:348
#define LOG_TRACEF(...)
Definition: log.qh:82
float w_deathtype
Definition: damage.qh:97
entity Notification
always last
Definition: all.qh:82
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
+ Here is the caller graph for this function:

◆ 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 1057 of file damage.qc.

References RadiusDamageForSource().

Referenced by CheatImpulse(), PlayerTouchExplode(), and vehicles_projectile_explode().

1058 {
1059  return RadiusDamageForSource(inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad,
1060  cantbe, mustbe, false, forceintensity, 1, deathtype, weaponentity, directhitentity);
1061 }
float RadiusDamageForSource(entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float forcezscale, int deathtype,.entity weaponentity, entity directhitentity)
Definition: damage.qc:866
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ RadiusDamageForSource()

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

Definition at line 866 of file damage.qc.

References accuracy_add(), accuracy_isgooddamage(), 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, Damage(), Damage_DamageInfo(), DEATH_ISSPECIAL, DEATH_WEAPONOF, entity(), HITTYPE_BOUNCE, HITTYPE_SECONDARY, HITTYPE_SOUND, HITTYPE_SPLASH, IS_PLAYER, LOG_INFOF, max(), MAX_DAMAGEEXTRARADIUS, min(), MIN_DAMAGEEXTRARADIUS, MOVE_NOMONSTERS, next, normalize(), RadiusDamage_running, random(), sqrt(), trace_ent, trace_fraction, vector(), vlen(), WarpZone_FindRadius(), WarpZone_TraceLine(), WarpZone_TransformOrigin(), and WarpZone_UnTransformOrigin().

Referenced by RadiusDamage().

868 {
869  entity targ;
870  vector force;
871  float total_damage_to_creatures;
872  entity next;
873  float tfloordmg;
874  float tfloorforce;
875 
876  float stat_damagedone;
877 
879  {
880  backtrace("RadiusDamage called recursively! Expect stuff to go HORRIBLY wrong.");
881  return 0;
882  }
883 
885 
886  tfloordmg = autocvar_g_throughfloor_damage;
887  tfloorforce = autocvar_g_throughfloor_force;
888 
889  total_damage_to_creatures = 0;
890 
891  if(deathtype != (WEP_HOOK.m_id | HITTYPE_SECONDARY | HITTYPE_BOUNCE)) // only send gravity bomb damage once
892  if(!(deathtype & HITTYPE_SOUND)) // do not send radial sound damage (bandwidth hog)
893  {
894  force = inflictorvelocity;
895  if(force == '0 0 0')
896  force = '0 0 -1';
897  else
898  force = normalize(force);
899  if(forceintensity >= 0)
900  Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
901  else
902  Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
903  }
904 
905  stat_damagedone = 0;
906 
907  targ = WarpZone_FindRadius (inflictororigin, rad + MAX_DAMAGEEXTRARADIUS, false);
908  while (targ)
909  {
910  next = targ.chain;
911  if ((targ != inflictor) || inflictorselfdamage)
912  if (((cantbe != targ) && !mustbe) || (mustbe == targ))
913  if (targ.takedamage)
914  {
915  vector nearest;
916  vector diff;
917  float power;
918 
919  // LordHavoc: measure distance to nearest point on target (not origin)
920  // (this guarentees 100% damage on a touch impact)
921  nearest = targ.WarpZone_findradius_nearest;
922  diff = targ.WarpZone_findradius_dist;
923  // round up a little on the damage to ensure full damage on impacts
924  // and turn the distance into a fraction of the radius
925  power = 1 - ((vlen (diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad);
926  //bprint(" ");
927  //bprint(ftos(power));
928  //if (targ == attacker)
929  // print(ftos(power), "\n");
930  if (power > 0)
931  {
932  float finaldmg;
933  if (power > 1)
934  power = 1;
935  finaldmg = coredamage * power + edgedamage * (1 - power);
936  if (finaldmg > 0)
937  {
938  float a;
939  float c;
940  vector hitloc;
941  vector myblastorigin;
942  vector center;
943 
944  myblastorigin = WarpZone_TransformOrigin(targ, inflictororigin);
945 
946  // if it's a player, use the view origin as reference
947  center = CENTER_OR_VIEWOFS(targ);
948 
949  force = normalize(center - myblastorigin);
950  force = force * (finaldmg / coredamage) * forceintensity;
951  hitloc = nearest;
952 
953  // apply special scaling along the z axis if set
954  // NOTE: 0 value is not allowed for compatibility, in the case of weapon cvars not being set
955  if(forcezscale)
956  force.z *= forcezscale;
957 
958  if(targ != directhitentity)
959  {
960  float hits;
961  float total;
962  float hitratio;
963  float mininv_f, mininv_d;
964 
965  // test line of sight to multiple positions on box,
966  // and do damage if any of them hit
967  hits = 0;
968 
969  // we know: max stddev of hitratio = 1 / (2 * sqrt(n))
970  // so for a given max stddev:
971  // n = (1 / (2 * max stddev of hitratio))^2
972 
973  mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev;
974  mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev;
975 
977  LOG_INFOF("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f);
978 
979 
980  total = 0.25 * (max(mininv_f, mininv_d) ** 2);
981 
983  LOG_INFOF(" steps=%f", total);
984 
985 
986  if (IS_PLAYER(targ))
988  else
990 
992  LOG_INFOF(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total)));
993 
994  for(c = 0; c < total; ++c)
995  {
996  //traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor);
997  WarpZone_TraceLine(inflictororigin, WarpZone_UnTransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor);
998  if (trace_fraction == 1 || trace_ent == targ)
999  {
1000  ++hits;
1001  if (hits > 1)
1002  hitloc = hitloc + nearest;
1003  else
1004  hitloc = nearest;
1005  }
1006  nearest.x = targ.origin.x + targ.mins.x + random() * targ.size.x;
1007  nearest.y = targ.origin.y + targ.mins.y + random() * targ.size.y;
1008  nearest.z = targ.origin.z + targ.mins.z + random() * targ.size.z;
1009  }
1010 
1011  nearest = hitloc * (1 / max(1, hits));
1012  hitratio = (hits / total);
1013  a = bound(0, tfloordmg + (1-tfloordmg) * hitratio, 1);
1014  finaldmg = finaldmg * a;
1015  a = bound(0, tfloorforce + (1-tfloorforce) * hitratio, 1);
1016  force = force * a;
1017 
1019  LOG_INFOF(" D=%f F=%f", finaldmg, vlen(force));
1020  }
1021 
1022  //if (targ == attacker)
1023  //{
1024  // print("hits ", ftos(hits), " / ", ftos(total));
1025  // print(" finaldmg ", ftos(finaldmg), " force ", vtos(force));
1026  // print(" (", ftos(a), ")\n");
1027  //}
1028  if(finaldmg || force)
1029  {
1030  if(targ.iscreature)
1031  {
1032  total_damage_to_creatures += finaldmg;
1033 
1034  if(accuracy_isgooddamage(attacker, targ))
1035  stat_damagedone += finaldmg;
1036  }
1037 
1038  if(targ == directhitentity || DEATH_ISSPECIAL(deathtype))
1039  Damage(targ, inflictor, attacker, finaldmg, deathtype, weaponentity, nearest, force);
1040  else
1041  Damage(targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, weaponentity, nearest, force);
1042  }
1043  }
1044  }
1045  }
1046  targ = next;
1047  }
1048 
1050 
1051  if(!DEATH_ISSPECIAL(deathtype))
1052  accuracy_add(attacker, DEATH_WEAPONOF(deathtype), 0, min(coredamage, stat_damagedone));
1053 
1054  return total_damage_to_creatures;
1055 }
const int HITTYPE_SPLASH
automatically set by RadiusDamage
Definition: all.qh:27
const int HITTYPE_SOUND
Definition: all.qh:30
const int HITTYPE_BOUNCE
Definition: all.qh:28
float RadiusDamage_running
Definition: damage.qh:131
const float MIN_DAMAGEEXTRARADIUS
Definition: damage.qh:138
entity() spawn
vector WarpZone_TransformOrigin(entity wz, vector v)
Definition: common.qc:499
float autocvar_g_throughfloor_min_steps_other
Definition: damage.qh:12
float autocvar_g_throughfloor_damage
Definition: damage.qh:6
float autocvar_g_throughfloor_min_steps_player
Definition: damage.qh:10
#define DEATH_WEAPONOF(t)
Definition: all.qh:41
float autocvar_g_throughfloor_max_steps_other
Definition: damage.qh:13
entity trace_ent
Definition: csprogsdefs.qc:40
vector WarpZone_UnTransformOrigin(entity wz, vector v)
Definition: common.qc:535
const float MOVE_NOMONSTERS
Definition: csprogsdefs.qc:253
#define LOG_INFOF(...)
Definition: log.qh:71
#define backtrace(msg)
Definition: log.qh:105
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition: damage.qc:583
const int HITTYPE_SECONDARY
Definition: all.qh:25
entity WarpZone_FindRadius(vector org, float rad, bool needlineofsight)
Definition: common.qc:669
float autocvar_g_throughfloor_max_steps_player
Definition: damage.qh:11
#define CENTER_OR_VIEWOFS(ent)
Definition: utils.qh:28
vector(float skel, float bonenum) _skel_get_boneabs_hidden
next
Definition: all.qh:88
float autocvar_g_throughfloor_force
Definition: damage.qh:7
void accuracy_add(entity this, Weapon w, float fired, float hit)
Definition: accuracy.qc:83
void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
Definition: common.qc:338
bool accuracy_isgooddamage(entity attacker, entity targ)
Definition: accuracy.qc:112
const float MAX_DAMAGEEXTRARADIUS
Definition: damage.qh:139
void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner)
#define DEATH_ISSPECIAL(t)
Definition: all.qh:35
float autocvar_g_throughfloor_damage_max_stddev
Definition: damage.qh:8
float trace_fraction
Definition: csprogsdefs.qc:36
#define IS_PLAYER(v)
Definition: utils.qh:9
float autocvar_g_throughfloor_force_max_stddev
Definition: damage.qh:9
bool autocvar_g_throughfloor_debug
Definition: damage.qh:5
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ STATIC_INIT()

STATIC_INIT ( g_damagedbycontents  )

Definition at line 156 of file damage.qh.

References IL_NEW.

#define IL_NEW()
IntrusiveList g_damagedbycontents
Definition: damage.qh:155

◆ Unfreeze()

void Unfreeze ( entity  targ,
bool  reset_health 
)

Definition at line 546 of file damage.qc.

References autocvar_g_balance_pause_health_regen, FOREACH_CLIENT, FROZEN_TEMP_DYING, g_bot_targets, IL_PUSH(), IS_PLAYER, MAX_WEAPONSLOTS, MUTATOR_CALLHOOK, NULL, RemoveHook(), RES_HEALTH, SetResource(), start_health, time, Unfreeze(), and weaponentities.

Referenced by ClientDisconnect(), Damage(), ft_RemovePlayer(), Monster_Dead(), Monster_Frozen_Think(), Monster_Reset(), MUTATOR_HOOKFUNCTION(), PlayerDamage(), PlayerPreThink(), PutObserverInServer(), PutPlayerInServer(), reset_map(), and Unfreeze().

547 {
548  if(!STAT(FROZEN, targ))
549  return;
550 
551  if (reset_health && STAT(FROZEN, targ) != FROZEN_TEMP_DYING)
552  SetResource(targ, RES_HEALTH, ((IS_PLAYER(targ)) ? start_health : targ.max_health));
553 
554  targ.pauseregen_finished = time + autocvar_g_balance_pause_health_regen;
555 
556  STAT(FROZEN, targ) = 0;
557  STAT(REVIVE_PROGRESS, targ) = 0;
558  targ.revival_time = time;
559  if(!targ.bot_attack)
560  IL_PUSH(g_bot_targets, targ);
561  targ.bot_attack = true;
562 
563  WaypointSprite_Kill(targ.waypointsprite_attached);
564 
566  {
567  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
568  {
569  .entity weaponentity = weaponentities[slot];
570  if(it.(weaponentity).hook.aiment == targ)
571  RemoveHook(it.(weaponentity).hook);
572  }
573  });
574 
575  // remove the ice block
576  if(targ.iceblock)
577  delete(targ.iceblock);
578  targ.iceblock = NULL;
579 
580  MUTATOR_CALLHOOK(Unfreeze, targ);
581 }
float autocvar_g_balance_pause_health_regen
Definition: sv_resources.qh:35
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
IntrusiveList g_bot_targets
Definition: api.qh:149
RES_HEALTH
Definition: ent_cs.qc:126
void Unfreeze(entity targ, bool reset_health)
Definition: damage.qc:546
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void SetResource(entity e, Resource res_type, float amount)
Sets the current amount of resource the given entity will have.
Definition: cl_resources.qc:26
const int MAX_WEAPONSLOTS
Definition: weapon.qh:13
#define NULL
Definition: post.qh:17
float start_health
Definition: world.qh:98
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
float time
Definition: csprogsdefs.qc:16
const int FROZEN_TEMP_DYING
Definition: damage.qh:111
#define IS_PLAYER(v)
Definition: utils.qh:9
void RemoveHook(entity this)
Definition: hook.qc:96
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ UpdateFrags()

void UpdateFrags ( entity  player,
int  f 
)

Definition at line 44 of file damage.qc.

References GameRules_scoring_add_team.

Referenced by GiveFrags(), and kh_Scores_Event().

45 {
46  GameRules_scoring_add_team(player, SCORE, f);
47 }
#define GameRules_scoring_add_team(client, fld, value)
Definition: sv_rules.qh:80
+ Here is the caller graph for this function:

◆ void()

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

◆ W_SwitchWeapon_Force()

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

Definition at line 243 of file selection.qc.

Referenced by GiveItems(), Item_GiveTo(), MUTATOR_HOOKFUNCTION(), TEST(), W_ThrowWeapon(), and W_WeaponFrame().

244 {
245  TC(Weapon, wep);
246  entity w_ent = this.(weaponentity);
247  w_ent.cnt = w_ent.m_switchweapon.m_id;
248  w_ent.m_switchweapon = wep;
249  w_ent.selectweapon = wep.m_id;
250 }
entity() spawn
#define TC(T, sym)
Definition: _all.inc:82
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
+ Here is the caller graph for this function:

Variable Documentation

◆ autocvar_g_balance_armor_blockpercent

float 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 24 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_friendlyfire

float autocvar_g_friendlyfire

Definition at line 25 of file damage.qh.

Referenced by Damage(), and MUTATOR_HOOKFUNCTION().

◆ autocvar_g_friendlyfire_virtual

float autocvar_g_friendlyfire_virtual

Definition at line 26 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_friendlyfire_virtual_force

float autocvar_g_friendlyfire_virtual_force

Definition at line 27 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_frozen_damage_trigger

bool autocvar_g_frozen_damage_trigger

Definition at line 30 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_frozen_force

float autocvar_g_frozen_force

Definition at line 31 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_frozen_revive_falldamage

float autocvar_g_frozen_revive_falldamage

Definition at line 28 of file damage.qh.

Referenced by Damage().

◆ autocvar_g_frozen_revive_falldamage_health

int autocvar_g_frozen_revive_falldamage_health

Definition at line 29 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_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_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 68 of file damage.qh.

◆ checkrules_firstblood

float checkrules_firstblood

Definition at line 46 of file damage.qh.

Referenced by Obituary().

◆ damagedbycontents

◆ damagedbytriggers

float damagedbytriggers

Definition at line 49 of file damage.qh.

◆ damageextraradius

float damageextraradius

Definition at line 140 of file damage.qh.

◆ damageforcescale

◆ death_origin

vector death_origin

Definition at line 70 of file damage.qh.

Referenced by formatmessage(), and IMPULSE().

◆ deathmessage

string deathmessage

Definition at line 76 of file damage.qh.

Referenced by Obituary().

◆ dmg

float dmg

Definition at line 37 of file damage.qh.

◆ dmg_edge

float dmg_edge

Definition at line 38 of file damage.qh.

Referenced by STATIC_INIT().

◆ dmg_force

float dmg_force

Definition at line 39 of file damage.qh.

Referenced by STATIC_INIT().

◆ dmg_radius

float dmg_radius

Definition at line 40 of file damage.qh.

Referenced by STATIC_INIT().

◆ dmg_team

float dmg_team

Definition at line 56 of file damage.qh.

Referenced by PlayerThink(), and PutPlayerInServer().

◆ fire_damagepersec

float fire_damagepersec

Definition at line 146 of file damage.qh.

◆ fire_deathtype

float fire_deathtype

Definition at line 147 of file damage.qh.

◆ fire_hitsound

float fire_hitsound

Definition at line 149 of file damage.qh.

◆ fire_owner

entity fire_owner

Definition at line 148 of file damage.qh.

◆ freeze_time

float freeze_time

Definition at line 115 of file damage.qh.

Referenced by PlayerDamage().

◆ frozen_by

entity frozen_by

Definition at line 117 of file damage.qh.

Referenced by Monster_Frozen_Think(), and PlayerPreThink().

◆ FROZEN_NORMAL

◆ FROZEN_TEMP_DYING

const int FROZEN_TEMP_DYING = 3

Definition at line 111 of file damage.qh.

Referenced by Freeze(), Monster_Frozen_Think(), PlayerPreThink(), and Unfreeze().

◆ FROZEN_TEMP_REVIVING

const int FROZEN_TEMP_REVIVING = 2

Definition at line 110 of file damage.qh.

Referenced by Monster_Frozen_Think(), and PlayerPreThink().

◆ g_damagedbycontents

◆ hitsound_damage_dealt

float hitsound_damage_dealt

Definition at line 72 of file damage.qh.

◆ iceblock

entity iceblock

Definition at line 116 of file damage.qh.

Referenced by Monster_Frozen_Think(), Monster_Remove(), and PlayerPreThink().

◆ impressive_hits

int impressive_hits

Definition at line 52 of file damage.qh.

Referenced by Damage().

◆ istypefrag

bool istypefrag

Definition at line 61 of file damage.qh.

◆ killsound

int killsound

Definition at line 73 of file damage.qh.

◆ MAX_DAMAGEEXTRARADIUS

const float MAX_DAMAGEEXTRARADIUS = 16

Definition at line 139 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ MIN_DAMAGEEXTRARADIUS

const float MIN_DAMAGEEXTRARADIUS = 2

Definition at line 138 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ pain_finished

float pain_finished

Definition at line 54 of file damage.qh.

◆ pusher

entity pusher

Definition at line 60 of file damage.qh.

◆ RadiusDamage_running

float RadiusDamage_running

Definition at line 131 of file damage.qh.

Referenced by RadiusDamageForSource().

◆ revival_time

float revival_time

Definition at line 113 of file damage.qh.

Referenced by PutObserverInServer(), and PutPlayerInServer().

◆ revive_speed

float revive_speed

Definition at line 114 of file damage.qh.

Referenced by Monster_Frozen_Think(), and PlayerPreThink().

◆ spawnshieldtime

float spawnshieldtime

Definition at line 64 of file damage.qh.

Referenced by Item_Touch().

◆ taunt_soundtime

float taunt_soundtime

Definition at line 62 of file damage.qh.

Referenced by PlayerPreThink().

◆ teamkill_complain

float teamkill_complain

Definition at line 57 of file damage.qh.

Referenced by Damage(), and W_Nexball_Touch().

◆ teamkill_soundsource

entity teamkill_soundsource

Definition at line 59 of file damage.qh.

◆ teamkill_soundtime

float teamkill_soundtime

Definition at line 58 of file damage.qh.

Referenced by PlayerPreThink().

◆ totalfrags

int totalfrags

Definition at line 66 of file damage.qh.

◆ typehitsound

int typehitsound

Definition at line 73 of file damage.qh.

◆ w_deathtype

float w_deathtype

Definition at line 97 of file damage.qh.

Referenced by Obituary_WeaponDeath().

◆ yoda

float yoda

Definition at line 51 of file damage.qh.

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