59 f -= (teamkills * (teamkills - 1)) * 0.5;
73 if (
MUTATOR_CALLHOOK(GiveFragsForKill, attacker, targ, f, deathtype, attacker.(weaponentity)))
76 attacker.totalfrags += f;
87 int w = player.(weaponentity).
m_weapon.m_id;
89 w = player.(weaponentity).
cnt;
90 if (w != 0 || slot == 0)
105 string s =
strcat(
":kill:", mode,
106 ":",
ftos(killer.playerid),
107 ":",
ftos(killed.playerid));
110 if (killed != killer)
112 s =
strcat(s,
":victimitems=");
123 string s1,
string s2,
string s3,
string s4,
124 float f1,
float f2,
float f3)
128 backtrace(
"Obituary_SpecialDeath called without a special deathtype?\n");
135 backtrace(
"Obituary_SpecialDeath: Could not find deathtype entity!\n");
139 if ((
g_cts || notif_target.killindicator_teamchange == -2) && deathtype == DEATH_KILL.m_id)
143 ? (murder ? deathent.death_msg_ent_murder : deathent.death_msg_ent_self)
144 : (murder ? deathent.death_msgmurder : deathent.death_msgself);
159 death_message.nent_msginfo,
170 string s1,
string s2,
string s3,
174 if (death_weapon == WEP_Null)
196 death_message.nent_msginfo,
203 "Obituary_WeaponDeath(): ^1Deathtype ^7(%d)^1 has no notification for weapon %s!\n",
213 if (deathtype == DEATH_FIRE.m_id)
216 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));
220 return MUTATOR_CALLHOOK(FragCenterMessage, attacker, targ, deathtype, kill_count_to_attacker, kill_count_to_target);
228 backtrace(
"Obituary called on non-player?!\n");
233 float notif_firstblood =
false;
234 float kill_count_to_attacker, kill_count_to_target;
235 bool notif_anonymous =
false;
236 string attacker_name = attacker.netname;
239 targ.death_origin = targ.origin;
243 if (
MUTATOR_CALLHOOK(ClientObituary, inflictor, attacker, targ, deathtype, attacker.(weaponentity)))
245 CS(targ).killcount = 0;
248 notif_anonymous =
M_ARGV(5,
bool);
253 attacker_name =
"???";
255 #ifdef NOTIFICATIONS_DEBUG
256 Debug_Notification(sprintf(
257 "Obituary(%s, %s, %s, %s = %d);\n",
269 if (targ == attacker)
273 if (deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
274 Obituary_SpecialDeath(targ,
false,
false, deathtype, targ.netname, deathlocation,
"",
"", targ.team, 0, 0);
279 case DEATH_MIRRORDAMAGE:
280 Obituary_SpecialDeath(targ,
false,
false, deathtype, targ.netname, deathlocation,
"",
"",
CS(targ).
killcount, 0, 0);
282 case DEATH_HURTTRIGGER:
284 bool msg_from_ent = (inflictor && inflictor.message !=
"");
287 (msg_from_ent ? inflictor.message : deathlocation),
288 (msg_from_ent ? deathlocation :
""),
294 Obituary_SpecialDeath(targ,
false,
false, deathtype, targ.netname, deathlocation,
"",
"",
CS(targ).
killcount, 0, 0);
301 backtrace(
"SUICIDE: what the hell happened here?\n");
304 LogDeath(
"suicide", deathtype, targ, targ);
305 if (deathtype != DEATH_AUTOTEAMCHANGE.m_id)
306 GiveFrags(attacker, targ, -1, deathtype, weaponentity);
316 LogDeath(
"tk", deathtype, attacker, targ);
317 GiveFrags(attacker, targ, -1, deathtype, weaponentity);
319 CS(attacker).killcount = 0;
321 Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAG, targ.netname);
322 Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAGGED, attacker_name);
330 LogDeath(
"frag", deathtype, attacker, targ);
331 GiveFrags(attacker, targ, 1, deathtype, weaponentity);
333 CS(attacker).taunt_soundtime =
time + 1;
334 ++
CS(attacker).killcount;
336 ++attacker.killsound;
340 #define SPREE_ITEM(counta,countb,center,normal,gentle) \
342 Send_Notification(NOTIF_ONE, attacker, MSG_ANNCE, ANNCE_KILLSTREAK_##countb); \
344 PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
358 notif_firstblood =
true;
363 kill_count_to_attacker = -1;
364 kill_count_to_target = -2;
368 kill_count_to_attacker =
CS(attacker).killcount;
369 kill_count_to_target = 0;
380 kill_count_to_attacker,
389 kill_count_to_target,
403 kill_count_to_attacker,
412 kill_count_to_target,
421 bool msg_from_ent = (
DEATH_ENT(deathtype) == DEATH_HURTTRIGGER && inflictor && inflictor.message2 !=
"");
425 (msg_from_ent ? inflictor.message2 : deathlocation),
426 (msg_from_ent ? deathlocation :
""),
443 case DEATH_HURTTRIGGER:
445 bool msg_from_ent = (inflictor && inflictor.message !=
"");
448 (msg_from_ent ? inflictor.message : deathlocation),
449 (msg_from_ent ? deathlocation :
""),
465 Obituary_SpecialDeath(targ,
false,
false, deathtype, targ.netname, deathlocation,
"",
"",
CS(targ).
killcount, 0, 0);
469 LogDeath(
"accident", deathtype, targ, targ);
470 GiveFrags(targ, targ, -1, deathtype, weaponentity);
481 CS(targ).killcount = 0;
494 entity attacker_save = attacker;
496 float complainteamdamage = 0;
497 float mirrordamage = 0;
498 float mirrorforce = 0;
500 if (deathtype == DEATH_KILL.m_id || deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id || damage ==
INFINITY)
510 else if (deathtype == DEATH_MIRRORDAMAGE.m_id || deathtype == DEATH_NOAMMO.m_id)
517 if (deathtype != DEATH_TELEFRAG.m_id
532 else if (attacker != targ)
538 attacker.dmg_team += damage;
548 attacker.dmg_team += damage;
550 if (complainteamdamage > 0)
560 attacker.dmg_take += v.x;
561 attacker.dmg_save += v.y;
562 attacker.dmg_inflictor = inflictor;
571 targ.dmg_take += v.x;
572 targ.dmg_save += v.y;
573 targ.dmg_inflictor = inflictor;
579 else if (!targ.canteamdamage)
596 MUTATOR_CALLHOOK(Damage_Calculate, inflictor, attacker, targ, deathtype, damage, mirrordamage, force, attacker.(weaponentity));
597 damage =
M_ARGV(4,
float);
598 mirrordamage =
M_ARGV(5,
float);
601 if (
IS_PLAYER(targ) && damage > 0 && attacker)
605 if (targ.(went).hook && targ.(went).hook.aiment == attacker)
609 if (targ == attacker)
613 if (attacker && targ != attacker
615 && deathtype != DEATH_BUFF_INFERNO.m_id
616 && deathtype != DEATH_BUFF_VENGEANCE.m_id
633 if (deathtype != DEATH_FIRE.m_id)
636 ++attacker.typehitsound;
638 attacker.hitsound_damage_dealt += damage;
651 if (deathtype != DEATH_FIRE.m_id)
652 ++attacker.typehitsound;
653 if (complainteamdamage > 0
656 CS(attacker).teamkill_complain =
time + 5;
657 CS(attacker).teamkill_soundtime =
time + 0.4;
658 CS(attacker).teamkill_soundsource = targ;
666 if (targ.damageforcescale && force
672 entity farcent =
new(farce);
673 farcent.enemy = targ;
674 farcent.movedir = farce * 10;
676 farcent.movedir *= targ.mass;
677 farcent.origin = hitloc;
679 farcent.nextthink =
time + 0.1;
683 targ.velocity += farce;
688 if ((damage != 0 || (targ.damageforcescale && force))
689 && targ.event_damage)
690 targ.event_damage(targ, inflictor, attacker, damage, deathtype, weaponentity, hitloc, force);
694 && (mirrordamage > 0 || mirrorforce > 0))
696 attacker = attacker_save;
698 force =
normalize(attacker.origin + attacker.view_ofs - hitloc) * mirrorforce;
699 Damage(attacker, inflictor, attacker, mirrordamage, DEATH_MIRRORDAMAGE.m_id, weaponentity, attacker.origin, force);
706 float coredamage,
float edgedamage,
float rad,
entity cantbe,
entity mustbe,
707 bool inflictorselfdamage,
float forceintensity,
vector forcexyzscale,
708 int deathtype, .
entity weaponentity,
entity directhitentity)
712 backtrace(
"RadiusDamage called recursively! Expect stuff to go HORRIBLY wrong.");
724 float stat_damagedone = 0;
725 float total_damage_to_creatures = 0;
730 force = inflictorvelocity;
731 if (force ==
'0 0 0')
735 if (forceintensity >= 0)
736 Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
738 Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
742 for (; targ; targ = targ.chain)
743 if ((targ != inflictor || inflictorselfdamage)
744 && (((cantbe != targ) && !mustbe) || mustbe == targ)
750 vector nearest = targ.WarpZone_findradius_nearest;
755 vector inflictororigin_wz = targ.WarpZone_findradius_nearest + targ.WarpZone_findradius_dist;
757 inflictororigin_wz + inflictor.mins, inflictororigin_wz + inflictor.maxs, nearest);
758 vector diff = inflictornearest - nearest;
765 float f = (rad > 0) ? 1 - (dist / rad) : 1;
767 float finaldmg = coredamage * f + edgedamage * (1 - f);
778 if (targ != attacker)
779 center = targ.origin + ((targ.mins + targ.maxs) * 0.5);
786 vector mi =
'0 0 0', ma =
'0 0 0';
796 tracebox(center, mi, ma, center + dv,
MOVE_NORMAL, targ);
805 center.z += targ.(weaponentity).
movedir.z;
821 force =
normalize(center - inflictororigin_wz);
822 force *= (finaldmg /
max(coredamage, edgedamage)) * forceintensity;
827 force.x *= forcexyzscale.x;
829 force.y *= forcexyzscale.y;
831 force.z *= forcexyzscale.z;
833 if (targ != directhitentity)
838 float mininv_f, mininv_d;
852 LOG_INFOF(
"THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg,
vlen(force), mininv_d, mininv_f);
854 total = 0.25 * (
max(mininv_f, mininv_d) ** 2);
865 LOG_INFOF(
" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 *
sqrt(total)),
vlen(force) * (1-tfloorforce) / (2 *
sqrt(total)));
867 for (c = 0; c < total; ++c)
879 nearest.x = targ.origin.x + targ.mins.x +
random() * targ.size.x;
880 nearest.y = targ.origin.y + targ.mins.y +
random() * targ.size.y;
881 nearest.z = targ.origin.z + targ.mins.z +
random() * targ.size.z;
884 nearest = hitloc * (1 /
max(1, hits));
885 hitratio = hits / total;
886 a =
bound(0, tfloordmg + (1 - tfloordmg) * hitratio, 1);
888 a =
bound(0, tfloorforce + (1 - tfloorforce) * hitratio, 1);
902 if (finaldmg || force)
906 total_damage_to_creatures += finaldmg;
909 stat_damagedone += finaldmg;
913 Damage(targ, inflictor, attacker, finaldmg, deathtype, weaponentity, nearest, force);
915 Damage(targ, inflictor, attacker, finaldmg, deathtype |
HITTYPE_SPLASH, weaponentity, nearest, force);
926 return total_damage_to_creatures;
931 float coredamage,
float edgedamage,
float rad,
entity cantbe,
entity mustbe,
932 float forceintensity,
933 int deathtype, .
entity weaponentity,
entity directhitentity)
936 inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker,
937 coredamage, edgedamage, rad, cantbe, mustbe,
938 false, forceintensity,
'1 1 1',
939 deathtype, weaponentity, directhitentity
951 bool healed = (targ.event_heal)
952 ? targ.event_heal(targ, inflictor, amount, limit)
974 float mintime = fireendtime -
time;
975 float maxtime =
max(mintime, t);
977 float mindps = e.fire_damagepersec;
978 float maxdps =
max(mindps, dps);
980 if (maxtime > mintime || maxdps > mindps)
985 float mindamage = mindps * mintime;
988 float maxdamage = mindamage + d;
991 float totaldamage =
min(maxdamage, maxtime * maxdps);
1014 float totaltime =
min(maxtime, totaldamage / mindps);
1036 e.fire_damagepersec = totaldamage / totaltime;
1038 if (totaldamage > 1.2 * mindamage)
1040 e.fire_deathtype = dt;
1041 if (e.fire_owner != o)
1044 e.fire_hitsound =
false;
1049 return max(0, totaldamage - mindamage);
1056 e.fire_damagepersec = dps;
1058 e.fire_deathtype = dt;
1060 e.fire_hitsound =
false;
1071 for (t = 0, o = e.owner; o.owner && t < 16; o = o.owner, ++t);
1077 float d = e.fire_damagepersec * t;
1079 float hi = e.fire_owner.hitsound_damage_dealt;
1080 float ty = e.fire_owner.typehitsound;
1081 Damage(e, e, e.fire_owner, d, e.fire_deathtype,
DMG_NOWEP, e.origin,
'0 0 0');
1082 if (e.fire_hitsound && e.fire_owner)
1084 e.fire_owner.hitsound_damage_dealt = hi;
1085 e.fire_owner.typehitsound = ty;
1087 e.fire_hitsound =
true;
1092 if (!IS_DEAD(it) && it.takedamage && !IS_INDEPENDENT_PLAYER(it)
1093 && boxesoverlap(e.absmin -
'1 1 1', e.absmax +
'1 1 1', it.absmin, it.absmax))
1095 t = autocvar_g_balance_firetransfer_time * (fireendtime - time);
1096 d = autocvar_g_balance_firetransfer_damage * e.fire_damagepersec * t;
1097 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.
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 h, float a, float armorblock, int deathtype, float damage)
const int FRAGS_SPECTATOR
engine expects this value
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 Fire_AddDamage(entity e, entity o, float d, float t, float dt)
float Obituary_WeaponDeath(entity notif_target, bool murder, int deathtype, string s1, string s2, string s3, float f1, float f2)
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)
void Obituary_SpecialDeath(entity notif_target, bool murder, bool msg_from_ent, int deathtype, string s1, string s2, string s3, string s4, float f1, float f2, float f3)
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)
const int HITTYPE_SPAM
set manually after first RadiusDamage, stops effect spam
const int HITTYPE_SPLASH
automatically set by RadiusDamage
#define DEATH_WEAPONOF(t)
const int HITTYPE_SOUND
cause bleeding from ears
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 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 f2
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_Core(NOTIF broadcast, entity client, MSG net_type, Notification net_name, string s1, string s2, string s3, string s4, float f1, float f2, float f3, float f4)
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
bool autocvar_notification_server_allows_location
entity Notification
always last
#define APP_TEAM_NUM(num, prefix)
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)
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