58 f -= (teamkills * (teamkills - 1)) * 0.5;
72 if (
MUTATOR_CALLHOOK(GiveFragsForKill, attacker, targ, f, deathtype, attacker.(weaponentity)))
75 attacker.totalfrags += f;
86 int w = player.(weaponentity).
m_weapon.m_id;
88 w = player.(weaponentity).
cnt;
89 if (w != 0 || slot == 0)
104 string s =
strcat(
":kill:", mode,
105 ":",
ftos(killer.playerid),
106 ":",
ftos(killed.playerid));
109 if (killed != killer)
111 s =
strcat(s,
":victimitems=");
122 string s1,
string s2,
string s3,
string s4,
123 float f1,
float f2,
float f3)
127 backtrace(
"Obituary_SpecialDeath called without a special deathtype?\n");
134 backtrace(
"Obituary_SpecialDeath: Could not find deathtype entity!\n");
138 if (
g_cts && deathtype == DEATH_KILL.m_id)
142 ? (murder ? deathent.death_msg_ent_murder : deathent.death_msg_ent_self)
143 : (murder ? deathent.death_msgmurder : deathent.death_msgself);
158 death_message.nent_msginfo,
169 string s1,
string s2,
string s3,
173 if (death_weapon == WEP_Null)
195 death_message.nent_msginfo,
202 "Obituary_WeaponDeath(): ^1Deathtype ^7(%d)^1 has no notification for weapon %s!\n",
212 if (deathtype == DEATH_FIRE.m_id)
215 Send_Notification(NOTIF_ONE, targ, MSG_CHOICE, CHOICE_FRAGGED_FIRE, attacker_name, kill_count_to_target,
GetResource(attacker, RES_HEALTH),
GetResource(attacker,
RES_ARMOR), (
IS_BOT_CLIENT(attacker) ? -1 :
CS(attacker).
ping));
219 return MUTATOR_CALLHOOK(FragCenterMessage, attacker, targ, deathtype, kill_count_to_attacker, kill_count_to_target);
227 backtrace(
"Obituary called on non-player?!\n");
232 float notif_firstblood =
false;
233 float kill_count_to_attacker, kill_count_to_target;
234 bool notif_anonymous =
false;
235 string attacker_name = attacker.netname;
238 targ.death_origin = targ.origin;
242 if (
MUTATOR_CALLHOOK(ClientObituary, inflictor, attacker, targ, deathtype, attacker.(weaponentity)))
244 CS(targ).killcount = 0;
247 notif_anonymous =
M_ARGV(5,
bool);
252 attacker_name =
"???";
254 #ifdef NOTIFICATIONS_DEBUG
255 Debug_Notification(sprintf(
256 "Obituary(%s, %s, %s, %s = %d);\n",
268 if (targ == attacker)
272 if (deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
273 Obituary_SpecialDeath(targ,
false, 0, deathtype, targ.netname, deathlocation,
"",
"", targ.team, 0, 0);
278 case DEATH_MIRRORDAMAGE:
279 Obituary_SpecialDeath(targ,
false, 0, deathtype, targ.netname, deathlocation,
"",
"",
CS(targ).
killcount, 0, 0);
281 case DEATH_HURTTRIGGER:
283 bool msg_from_ent = (inflictor && inflictor.message !=
"");
286 (msg_from_ent ? inflictor.message : deathlocation),
287 (msg_from_ent ? deathlocation :
""),
293 Obituary_SpecialDeath(targ,
false, 0, deathtype, targ.netname, deathlocation,
"",
"",
CS(targ).
killcount, 0, 0);
300 backtrace(
"SUICIDE: what the hell happened here?\n");
303 LogDeath(
"suicide", deathtype, targ, targ);
304 if (deathtype != DEATH_AUTOTEAMCHANGE.m_id)
305 GiveFrags(attacker, targ, -1, deathtype, weaponentity);
315 LogDeath(
"tk", deathtype, attacker, targ);
316 GiveFrags(attacker, targ, -1, deathtype, weaponentity);
318 CS(attacker).killcount = 0;
320 Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAG, targ.netname);
321 Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAGGED, attacker_name);
329 LogDeath(
"frag", deathtype, attacker, targ);
330 GiveFrags(attacker, targ, 1, deathtype, weaponentity);
332 CS(attacker).taunt_soundtime =
time + 1;
333 ++
CS(attacker).killcount;
335 ++attacker.killsound;
339 #define SPREE_ITEM(counta,countb,center,normal,gentle) \
341 Send_Notification(NOTIF_ONE, attacker, MSG_ANNCE, ANNCE_KILLSTREAK_##countb); \
343 PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
357 notif_firstblood =
true;
362 kill_count_to_attacker = -1;
363 kill_count_to_target = -2;
367 kill_count_to_attacker =
CS(attacker).killcount;
368 kill_count_to_target = 0;
379 kill_count_to_attacker,
388 kill_count_to_target,
402 kill_count_to_attacker,
411 kill_count_to_target,
421 if (
DEATH_ENT(deathtype) == DEATH_HURTTRIGGER)
423 bool msg_from_ent = (inflictor && inflictor.message2 !=
"");
427 (msg_from_ent ? inflictor.message2 : deathlocation),
428 (msg_from_ent ? deathlocation :
""),
433 Obituary_SpecialDeath(targ,
true, 0, deathtype, targ.netname, attacker_name, deathlocation,
"",
CS(targ).
killcount, kill_count_to_attacker, f3);
448 case DEATH_HURTTRIGGER:
450 bool msg_from_ent = (inflictor && inflictor.message !=
"");
453 (msg_from_ent ? inflictor.message : deathlocation),
454 (msg_from_ent ? deathlocation :
""),
474 Obituary_SpecialDeath(targ,
false, 0, deathtype, targ.netname, deathlocation,
"",
"",
CS(targ).
killcount, 0, 0);
478 LogDeath(
"accident", deathtype, targ, targ);
479 GiveFrags(targ, targ, -1, deathtype, weaponentity);
490 CS(targ).killcount = 0;
503 entity attacker_save = attacker;
505 float complainteamdamage = 0;
506 float mirrordamage = 0;
507 float mirrorforce = 0;
509 if (deathtype == DEATH_KILL.m_id || deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
518 if (deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
527 else if (deathtype == DEATH_MIRRORDAMAGE.m_id || deathtype == DEATH_NOAMMO.m_id)
534 if (deathtype != DEATH_TELEFRAG.m_id
549 else if (attacker != targ)
555 attacker.dmg_team += damage;
565 attacker.dmg_team += damage;
567 if (complainteamdamage > 0)
576 attacker.dmg_take += v.x;
577 attacker.dmg_save += v.y;
578 attacker.dmg_inflictor = inflictor;
586 targ.dmg_take += v.x;
587 targ.dmg_save += v.y;
588 targ.dmg_inflictor = inflictor;
594 else if (!targ.canteamdamage)
611 MUTATOR_CALLHOOK(Damage_Calculate, inflictor, attacker, targ, deathtype, damage, mirrordamage, force, attacker.(weaponentity));
612 damage =
M_ARGV(4,
float);
613 mirrordamage =
M_ARGV(5,
float);
616 if (
IS_PLAYER(targ) && damage > 0 && attacker)
620 if (targ.(went).hook && targ.(went).hook.aiment == attacker)
624 if (targ == attacker)
628 if (attacker && targ != attacker
630 && deathtype != DEATH_BUFF.m_id
647 if (deathtype != DEATH_FIRE.m_id)
650 ++attacker.typehitsound;
652 attacker.hitsound_damage_dealt += damage;
665 if (deathtype != DEATH_FIRE.m_id)
666 ++attacker.typehitsound;
667 if (complainteamdamage > 0
670 CS(attacker).teamkill_complain =
time + 5;
671 CS(attacker).teamkill_soundtime =
time + 0.4;
672 CS(attacker).teamkill_soundsource = targ;
680 if (targ.damageforcescale && force
686 entity farcent =
new(farce);
687 farcent.enemy = targ;
688 farcent.movedir = farce * 10;
690 farcent.movedir *= targ.mass;
691 farcent.origin = hitloc;
693 farcent.nextthink =
time + 0.1;
697 targ.velocity += farce;
702 if ((damage != 0 || (targ.damageforcescale && force))
703 && targ.event_damage)
704 targ.event_damage(targ, inflictor, attacker, damage, deathtype, weaponentity, hitloc, force);
708 && (mirrordamage > 0 || mirrorforce > 0))
710 attacker = attacker_save;
712 force =
normalize(attacker.origin + attacker.view_ofs - hitloc) * mirrorforce;
713 Damage(attacker, inflictor, attacker, mirrordamage, DEATH_MIRRORDAMAGE.m_id, weaponentity, attacker.origin, force);
720 float coredamage,
float edgedamage,
float rad,
entity cantbe,
entity mustbe,
721 bool inflictorselfdamage,
float forceintensity,
vector forcexyzscale,
722 int deathtype, .
entity weaponentity,
entity directhitentity)
726 backtrace(
"RadiusDamage called recursively! Expect stuff to go HORRIBLY wrong.");
738 float stat_damagedone = 0;
739 float total_damage_to_creatures = 0;
744 force = inflictorvelocity;
745 if (force ==
'0 0 0')
749 if (forceintensity >= 0)
750 Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
752 Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
756 for (; targ; targ = targ.chain)
757 if ((targ != inflictor || inflictorselfdamage)
758 && (((cantbe != targ) && !mustbe) || mustbe == targ)
764 vector nearest = targ.WarpZone_findradius_nearest;
769 vector inflictororigin_wz = targ.WarpZone_findradius_nearest + targ.WarpZone_findradius_dist;
771 inflictororigin_wz + inflictor.mins, inflictororigin_wz + inflictor.maxs, nearest);
772 vector diff = inflictornearest - nearest;
779 float f = (rad > 0) ? 1 - (dist / rad) : 1;
781 float finaldmg = coredamage * f + edgedamage * (1 - f);
792 if (targ != attacker)
793 center = targ.origin + ((targ.mins + targ.maxs) * 0.5);
800 vector mi =
'0 0 0', ma =
'0 0 0';
810 tracebox(center, mi, ma, center + dv,
MOVE_NORMAL, targ);
819 center.z += targ.(weaponentity).
movedir.z;
835 force =
normalize(center - inflictororigin_wz);
836 force *= (finaldmg /
max(coredamage, edgedamage)) * forceintensity;
841 force.x *= forcexyzscale.x;
843 force.y *= forcexyzscale.y;
845 force.z *= forcexyzscale.z;
847 if (targ != directhitentity)
852 float mininv_f, mininv_d;
866 LOG_INFOF(
"THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg,
vlen(force), mininv_d, mininv_f);
868 total = 0.25 * (
max(mininv_f, mininv_d) ** 2);
879 LOG_INFOF(
" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 *
sqrt(total)),
vlen(force) * (1-tfloorforce) / (2 *
sqrt(total)));
881 for (c = 0; c < total; ++c)
893 nearest.x = targ.origin.x + targ.mins.x +
random() * targ.size.x;
894 nearest.y = targ.origin.y + targ.mins.y +
random() * targ.size.y;
895 nearest.z = targ.origin.z + targ.mins.z +
random() * targ.size.z;
898 nearest = hitloc * (1 /
max(1, hits));
899 hitratio = hits / total;
900 a =
bound(0, tfloordmg + (1 - tfloordmg) * hitratio, 1);
902 a =
bound(0, tfloorforce + (1 - tfloorforce) * hitratio, 1);
916 if (finaldmg || force)
920 total_damage_to_creatures += finaldmg;
923 stat_damagedone += finaldmg;
927 Damage(targ, inflictor, attacker, finaldmg, deathtype, weaponentity, nearest, force);
929 Damage(targ, inflictor, attacker, finaldmg, deathtype |
HITTYPE_SPLASH, weaponentity, nearest, force);
940 return total_damage_to_creatures;
945 float coredamage,
float edgedamage,
float rad,
entity cantbe,
entity mustbe,
946 float forceintensity,
947 int deathtype, .
entity weaponentity,
entity directhitentity)
950 inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker,
951 coredamage, edgedamage, rad, cantbe, mustbe,
952 false, forceintensity,
'1 1 1',
953 deathtype, weaponentity, directhitentity
965 bool healed = (targ.event_heal)
966 ? targ.event_heal(targ, inflictor, amount, limit)
988 float mintime = fireendtime -
time;
989 float maxtime =
max(mintime, t);
991 float mindps = e.fire_damagepersec;
992 float maxdps =
max(mindps, dps);
994 if (maxtime > mintime || maxdps > mindps)
999 float mindamage = mindps * mintime;
1002 float maxdamage = mindamage + d;
1005 float totaldamage =
min(maxdamage, maxtime * maxdps);
1028 float totaltime =
min(maxtime, totaldamage / mindps);
1050 e.fire_damagepersec = totaldamage / totaltime;
1052 if (totaldamage > 1.2 * mindamage)
1054 e.fire_deathtype = dt;
1055 if (e.fire_owner != o)
1058 e.fire_hitsound =
false;
1063 return max(0, totaldamage - mindamage);
1070 e.fire_damagepersec = dps;
1072 e.fire_deathtype = dt;
1074 e.fire_hitsound =
false;
1085 for (t = 0, o = e.owner; o.owner && t < 16; o = o.owner, ++t);
1091 float d = e.fire_damagepersec * t;
1093 float hi = e.fire_owner.hitsound_damage_dealt;
1094 float ty = e.fire_owner.typehitsound;
1095 Damage(e, e, e.fire_owner, d, e.fire_deathtype,
DMG_NOWEP, e.origin,
'0 0 0');
1096 if (e.fire_hitsound && e.fire_owner)
1098 e.fire_owner.hitsound_damage_dealt = hi;
1099 e.fire_owner.typehitsound = ty;
1101 e.fire_hitsound =
true;
1106 if (!IS_DEAD(it) && it.takedamage && !IS_INDEPENDENT_PLAYER(it)
1107 && boxesoverlap(e.absmin, e.absmax, it.absmin, it.absmax))
1109 t = autocvar_g_balance_firetransfer_time * (fireendtime - time);
1110 d = autocvar_g_balance_firetransfer_damage * e.fire_damagepersec * t;
1111 Fire_AddDamage(it, o, d, t, DEATH_FIRE.m_id);
void accuracy_add(entity this, Weapon w, float fired, float hit, float real)
update accuracy stats
bool accuracy_isgooddamage(entity attacker, entity targ)
does this damage count towards accuracy stats?
void tracebox_antilag(entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
#define ANTILAG_LATENCY(e)
#define MUTATOR_CALLHOOK(id,...)
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 SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
virtual void wr_suicidemessage()
(SERVER) notification number for suicide message (may inspect w_deathtype for details)
string netname
M: refname : reference name name.
virtual void wr_killmessage()
(SERVER) notification number for kill message (may inspect w_deathtype for details)
bool IsFlying(entity this)
#define IS_NOT_A_CLIENT(s)
#define PHYS_INPUT_BUTTON_CHAT(s)
vector healtharmor_applydamage(float a, float armorblock, int deathtype, float damage)
const int FRAGS_SPECTATOR
const float MOVE_NOMONSTERS
void UpdateCSQCProjectile(entity e)
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
bool Heal(entity targ, entity inflictor, float amount, float limit)
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
void GiveFrags(entity attacker, entity targ, float f, int deathtype,.entity weaponentity)
float Obituary_WeaponDeath(entity notif_target, float murder, int deathtype, string s1, string s2, string s3, float f1, float f2)
void Obituary_SpecialDeath(entity notif_target, float murder, bool msg_from_ent, int deathtype, string s1, string s2, string s3, string s4, float f1, float f2, float f3)
float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
bool frag_centermessage_override(entity attacker, entity targ, int deathtype, int kill_count_to_attacker, int kill_count_to_target, string attacker_name)
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)
void Fire_ApplyDamage(entity e)
string AppendItemcodes(string s, entity player)
void Obituary(entity attacker, entity inflictor, entity targ, int deathtype,.entity weaponentity)
void LogDeath(string mode, int deathtype, entity killer, entity killed)
bool RadiusDamage_running
bool autocvar_g_mirrordamage_virtual
bool autocvar_g_mirrordamage_onlyweapons
int autocvar_g_player_damageplayercenter
float autocvar_g_throughfloor_force_max_stddev
float autocvar_g_friendlyfire_virtual_force
float autocvar_g_throughfloor_damage_max_stddev
float autocvar_g_balance_armor_blockpercent
IntrusiveList g_damagedbycontents
float autocvar_g_throughfloor_force
float autocvar_g_balance_selfdamagepercent
bool autocvar_g_throughfloor_debug
float checkrules_firstblood
float autocvar_g_friendlyfire_virtual
float autocvar_g_teamdamage_threshold
float autocvar_g_throughfloor_min_steps_other
float autocvar_g_friendlyfire
float autocvar_g_throughfloor_min_steps_player
float autocvar_g_balance_damagepush_speedfactor
float autocvar_g_throughfloor_damage
float autocvar_g_throughfloor_max_steps_other
float autocvar_g_throughfloor_max_steps_player
float autocvar_g_mirrordamage
bool autocvar_g_teamkill_punishing
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
string Deathtype_Name(int deathtype)
#define DEATH_ISWEAPON(t, w)
#define DEATH_ISSPECIAL(t)
#define DEATH_WEAPONOF(t)
void SUB_Remove(entity this)
Remove entity.
const float FORCETYPE_FORCEATPOS
void GameLogEcho(string s)
bool autocvar_sv_eventlog
#define IL_EACH(this, cond, body)
entity WarpZone_FindRadius(vector org, float rad, bool needlineofsight)
void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
vector WarpZone_UnTransformOrigin(entity wz, vector v)
#define UNSET_ONGROUND(s)
const int MOVETYPE_PHYSICS
const int MOVETYPE_NOCLIP
@ STATUSEFFECT_REMOVE_CLEAR
Effect is being forcibly removed without calling any additional mechanics.
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
spree_inf s1 s2 s3loc s2 s1
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
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
void Send_Notification_WOCOVA(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)
entity Notification
always last
#define APP_TEAM_NUM(num, prefix)
float autocvar_notification_server_allows_location
const string PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD
const string PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM
const string PLAYERSTATS_ACHIEVEMENT_BOTLIKE
#define PlayerStats_GameReport_Event_Player(ent, eventid, val)
#define REGISTRY_GET(id, i)
string NearestLocation(vector p)
#define IS_INDEPENDENT_PLAYER(e)
void RemoveHook(entity this)
ClientState CS(Client this)
void StatusEffects_remove(StatusEffect this, entity actor, int removal_type)
float StatusEffects_gettime(StatusEffect this, entity actor)
bool StatusEffects_active(StatusEffect this, entity actor)
void StatusEffects_apply(StatusEffect this, entity actor, float eff_time, int eff_flags)
entity buff_FirstFromFlags(entity actor)
Header file that describes the resource system.
#define GameRules_scoring_add(client, fld, value)
#define GameRules_scoring_add_team(client, fld, value)
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
#define CENTER_OR_VIEWOFS(ent)
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
ERASEABLE vector NearestPointOnBoundingBox(vector mi, vector ma, vector org)
const int MAX_WEAPONSLOTS
entity weaponentities[MAX_WEAPONSLOTS]
float autocvar_g_weaponforcefactor
float autocvar_g_weapondamagefactor