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);
716 float coredamage,
float edgedamage,
float rad,
entity cantbe,
entity mustbe,
717 bool inflictorselfdamage,
float forceintensity,
vector forcexyzscale,
718 int deathtype, .
entity weaponentity,
entity directhitentity)
722 backtrace(
"RadiusDamage called recursively! Expect stuff to go HORRIBLY wrong.");
734 float stat_damagedone = 0;
735 float total_damage_to_creatures = 0;
740 force = inflictorvelocity;
741 if (force ==
'0 0 0')
745 if (forceintensity >= 0)
746 Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
748 Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
756 for (; targ; targ = targ.chain)
761 vector nearest = targ.WarpZone_findradius_nearest;
766 vector inflictororigin_wz = targ.WarpZone_findradius_nearest + targ.WarpZone_findradius_dist;
768 inflictororigin_wz + inflictor.mins, inflictororigin_wz + inflictor.maxs, nearest);
769 vector diff = inflictornearest - nearest;
778 float f = (rad > 0) ? 1 - (dist / rad) : 1;
780 float finaldmg = coredamage * f + edgedamage * (1 - f);
793 if (targ != attacker)
794 center = targ.origin + ((targ.mins + targ.maxs) * 0.5);
801 vector mi =
'0 0 0', ma =
'0 0 0';
806 tracebox(center, mi, ma, center + dv,
MOVE_NORMAL, targ);
815 center.z += targ.(weaponentity).
movedir.z;
831 force =
normalize(center - inflictororigin_wz);
832 force *= (finaldmg /
max(coredamage, edgedamage)) * forceintensity;
837 force.x *= forcexyzscale.x;
839 force.y *= forcexyzscale.y;
841 force.z *= forcexyzscale.z;
843 if (targ != directhitentity)
848 float mininv_f, mininv_d;
862 LOG_INFOF(
"THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg,
vlen(force), mininv_d, mininv_f);
864 total = 0.25 * (
max(mininv_f, mininv_d) ** 2);
875 LOG_INFOF(
" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 *
sqrt(total)),
vlen(force) * (1-tfloorforce) / (2 *
sqrt(total)));
877 for (c = 0; c < total; ++c)
889 nearest.x = targ.origin.x + targ.mins.x +
random() * targ.size.x;
890 nearest.y = targ.origin.y + targ.mins.y +
random() * targ.size.y;
891 nearest.z = targ.origin.z + targ.mins.z +
random() * targ.size.z;
894 nearest = hitloc * (1 /
max(1, hits));
895 hitratio = hits / total;
896 a =
bound(0, tfloordmg + (1 - tfloordmg) * hitratio, 1);
898 a =
bound(0, tfloorforce + (1 - tfloorforce) * hitratio, 1);
912 if (finaldmg || force)
916 total_damage_to_creatures += finaldmg;
919 stat_damagedone += finaldmg;
923 Damage(targ, inflictor, attacker, finaldmg, deathtype, weaponentity, nearest, force);
925 Damage(targ, inflictor, attacker, finaldmg, deathtype |
HITTYPE_SPLASH, weaponentity, nearest, force);
934 return total_damage_to_creatures;
939 float coredamage,
float edgedamage,
float rad,
entity cantbe,
entity mustbe,
940 float forceintensity,
941 int deathtype, .
entity weaponentity,
entity directhitentity)
944 inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker,
945 coredamage, edgedamage, rad, cantbe, mustbe,
946 false, forceintensity,
'1 1 1',
947 deathtype, weaponentity, directhitentity
959 bool healed = (targ.event_heal)
960 ? targ.event_heal(targ, inflictor, amount, limit)
982 float mintime = fireendtime -
time;
983 float maxtime =
max(mintime, t);
985 float mindps = e.fire_damagepersec;
986 float maxdps =
max(mindps, dps);
988 if (maxtime > mintime || maxdps > mindps)
993 float mindamage = mindps * mintime;
996 float maxdamage = mindamage + d;
999 float totaldamage =
min(maxdamage, maxtime * maxdps);
1022 float totaltime =
min(maxtime, totaldamage / mindps);
1044 e.fire_damagepersec = totaldamage / totaltime;
1046 if (totaldamage > 1.2 * mindamage)
1048 e.fire_deathtype = dt;
1049 if (e.fire_owner != o)
1052 e.fire_hitsound =
false;
1057 return max(0, totaldamage - mindamage);
1064 e.fire_damagepersec = dps;
1066 e.fire_deathtype = dt;
1068 e.fire_hitsound =
false;
1079 for (t = 0, o = e.owner; o.owner && t < 16; o = o.owner, ++t);
1085 float d = e.fire_damagepersec * t;
1087 float hi = e.fire_owner.hitsound_damage_dealt;
1088 float ty = e.fire_owner.typehitsound;
1089 Damage(e, e, e.fire_owner, d, e.fire_deathtype,
DMG_NOWEP, e.origin,
'0 0 0');
1090 if (e.fire_hitsound && e.fire_owner)
1092 e.fire_owner.hitsound_damage_dealt = hi;
1093 e.fire_owner.typehitsound = ty;
1095 e.fire_hitsound =
true;
1100 if (!IS_DEAD(it) && it.takedamage && !IS_INDEPENDENT_PLAYER(it)
1101 && boxesoverlap(e.absmin -
'1 1 1', e.absmax +
'1 1 1', it.absmin, it.absmax))
1103 t = autocvar_g_balance_firetransfer_time * (fireendtime - time);
1104 d = autocvar_g_balance_firetransfer_damage * e.fire_damagepersec * t;
1105 Fire_AddDamage(it, o, d, t, DEATH_FIRE.m_id);
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 nomonsters, 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)
entity RadiusDamageForSource_cond_inflictor
float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
bool RadiusDamageForSource_cond_inflictorselfdamage
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)
bool RadiusDamageForSource_cond(entity targ)
float RadiusDamageForSource(entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, bool inflictorselfdamage, float forceintensity, vector forcexyzscale, int deathtype,.entity weaponentity, entity directhitentity)
Returns total damage applied to creatures.
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)
entity RadiusDamageForSource_cond_mustbe
entity RadiusDamageForSource_cond_cantbe
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_SearchInRadius(vector org, float rad, float nomonsters, WarpZone_FindRadius_cond_callback_t cb)
Modified findradius aware of warpzones, that only includes entities that meet the "cb" criteria.
vector WarpZone_UnTransformOrigin(entity wz, vector org)
Transforms origin org backwards through warpzone wz, as the inverse of WarpZone_TransformOrigin.
#define WarpZone_TraceLine(org, end, nomonsters, forent)
#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