float yoda;
float damage_goodhits;
float damage_gooddamage;
-float headshot;
-float damage_headshotbonus; // bonus multiplier for head shots, set to 0 after use
.float dmg_team;
.float teamkill_complain;
return 1;
}
-vector GetHeadshotMins(entity targ)
-{
- return '-0.5 0 0' * PL_HEAD_x + '0 -0.5 0' * PL_HEAD_y + '0 0 1' * (targ.maxs_z - PL_HEAD_z);
-}
-vector GetHeadshotMaxs(entity targ)
-{
- return '0.5 0 0' * PL_HEAD_x + '0 0.5 0' * PL_HEAD_y + '0 0 1' * targ.maxs_z;
-}
-
void UpdateFrags(entity player, float f)
{
PlayerTeamScore_AddScore(player, f);
UpdateFrags(attacker, f);
}
-string Obituary_ExtraFragInfo(entity player) // Extra fragmessage information
+/*string Obituary_ExtraFragInfo(entity player) // Extra fragmessage information
{
string health_output = string_null;
string ping_output = string_null;
}
return output;
-}
+}*/
string AppendItemcodes(string s, entity player)
{
s = strcat(":kill:", mode);
s = strcat(s, ":", ftos(killer.playerid));
s = strcat(s, ":", ftos(killed.playerid));
- s = strcat(s, ":type=", ftos(deathtype));
+ s = strcat(s, ":type=", Deathtype_Name(deathtype));
s = strcat(s, ":items=");
s = AppendItemcodes(s, killer);
if(killed != killer)
GameLogEcho(s);
}
-void Obituary_Notification(entity notif_target, string s1, string s2, string s3, float deathtype)
+#define INFO_NO_MSG 0
+
+void Obituary_SpecialDeath(entity notif_target, float murder, float deathtype, string s1, string s2, float f1, float f2, float f3)
{
- /*if(deathtype)
+ float handled = 0, hits = 0;
+ if(DEATH_ISSPECIAL(deathtype))
{
- #define DEATHTYPE(name,type,notification,first,last) \
- { if((deathtype == max(0, name)) && max(0, type) && max(0, notification)) { Send_Notification(type, notif_target, notification, s1, s2, s3); return; } }
+ #define DEATHTYPE(name,msg_death,msg_death_by,position) \
+ { if(deathtype == max(0, name)) \
+ { \
+ #if msg_death != NO_MSG \
+ if not(murder) \
+ { \
+ Send_Notification_WOVA(NOTIF_ONE, notif_target, MSG_DEATH, msg_death, s1, s2, "", "", f1, f2, f3, 0); \
+ Send_Notification_WOVA(NOTIF_ANY_EXCEPT, notif_target, MSG_INFO, INFO_##msg_death, s1, s2, "", "", f1, f2, f3, 0); \
+ ++handled; \
+ } \
+ #endif \
+ #if msg_death_by != NO_MSG \
+ if(murder) \
+ { \
+ Send_Notification_WOVA(NOTIF_ONE, notif_target, MSG_DEATH, msg_death_by, s1, s2, "", "", f1, f2, f3, 0); \
+ Send_Notification_WOVA(NOTIF_ANY_EXCEPT, notif_target, MSG_INFO, INFO_##msg_death_by, s1, s2, "", "", f1, f2, f3, 0); \
+ ++handled; \
+ } \
+ #endif \
+ ++hits; \
+ } }
DEATHTYPES
- backtrace("Unhandled deathtype. Please notify Samual!\n");
- }*/
+ #undef DEATHTYPE
+
+ if not(hits)
+ {
+ backtrace("Obituary_SpecialDeath(): Unhandled deathtype- Please notify Samual!\n");
+ }
+ if not(handled)
+ {
+ dprint(sprintf("Obituary_SpecialDeath(): ^1Deathtype ^7(%s-%d)^1 has no notification!\n", Deathtype_Name(deathtype), deathtype));
+ return;
+ }
+ }
}
-void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
+float w_deathtype;
+float Obituary_WeaponDeath(entity notif_target, float murder, float deathtype, string s1, string s2, float f1, float f2)
{
- string s, a, msg;
- float w, type;
+ float death_weapon = DEATH_WEAPONOF(deathtype);
- string s1, s2, s3;
-
- if (targ.classname == "player")
+ if(death_weapon)
{
- s = targ.netname;
- a = attacker.netname;
+ w_deathtype = deathtype;
+ float death_message = weapon_action(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
+ w_deathtype = FALSE;
- if (targ == attacker) // suicides
+ if(death_message)
{
- s1 = ((deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE) ? ColoredTeamName(targ.team) : "");
+ Send_Notification_WOVA(NOTIF_ONE, notif_target, MSG_WEAPON, death_message, s1, s2, "", "", f1, f2, 0, 0);
+ Send_Notification_WOVA(NOTIF_ANY_EXCEPT, notif_target, MSG_INFO, msg_weapon_notifs[death_message - 1].nent_msginfo.nent_id, s1, s2, "", "", f1, f2, 0, 0);
+ //print(Get_Field_Value(F_INFVAL, MSG_WEAPON, death_message), "\n");
+ }
+ else { dprint(sprintf("Obituary_WeaponDeath(): ^1Deathtype ^7(%s-%d)^1 has no notification for weapon %d!\n", Deathtype_Name(deathtype), deathtype, death_weapon)); }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void Obituary(entity attacker, entity inflictor, entity targ, float deathtype)
+{
+ // Sanity check
+ if not(targ.classname == STR_PLAYER) { backtrace("Obituary called on non-player?!\n"); return; }
- // no "killed your own dumb self" message in CTS
- if(!g_cts) { Obituary_Notification(targ, s1, "", "", deathtype); }
+ // Declarations
+ float notif_firstblood = FALSE;
- if(deathtype != DEATH_TEAMCHANGE && deathtype != DEATH_QUIET)
+ //dprint(sprintf("Obituary(): Deathtype = %s (%d), Attacker = %s, Inflictor = %s, Target = %s...\n", Deathtype_Name(deathtype), deathtype, attacker.netname, inflictor.netname, targ.netname));
+
+ // =======
+ // SUICIDE
+ // =======
+ if(targ == attacker)
+ {
+ if(DEATH_ISSPECIAL(deathtype))
+ {
+ if(deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
{
+ Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, "", targ.team, 0, 0);
+ }
+ else
+ {
+ switch(deathtype)
+ {
+ case DEATH_MIRRORDAMAGE:
+ {
+ Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, "", targ.killcount, 0, 0);
+ break;
+ }
+
+ default:
+ {
+ Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, "", targ.killcount, 0, 0);
+ break;
+ }
+ }
LogDeath("suicide", deathtype, targ, targ);
GiveFrags(attacker, targ, -1, deathtype);
}
-
- s1 = targ.netname;
- s2 = ((targ.killcount > 2) ? ftos(targ.killcount) : "");
-
- //if(teamplay && deathtype == DEATH_MIRRORDAMAGE)
- // { deathtype = ((attacker.team == FL_TEAM_1) ? KILL_TEAM_SUICIDE_RED : KILL_TEAM_SUICIDE_BLUE); }
-
- Obituary_Notification(world, s1, s2, "", deathtype);
- //Send_KillNotification(s, s2, ftos(w), deathtype, MSG_SUICIDE);
}
- else if (attacker.classname == "player")
+ else if not(Obituary_WeaponDeath(targ, FALSE, deathtype, targ.netname, "", targ.killcount, 0))
{
- if(!IsDifferentTeam(attacker, targ))
- {
- //type = ((attacker.team == FL_TEAM_1) ? KILL_TEAM_FRAG_RED : KILL_TEAM_FRAG_BLUE);
-
- GiveFrags(attacker, targ, -1, deathtype);
+ backtrace("SUICIDE: what the hell happened here?\n");
+ }
+ }
- //Send_CSQC_KillCenterprint(attacker, s, "", type);
+ // ======
+ // MURDER
+ // ======
+ else if(attacker.classname == "player")
+ {
+ if(!IsDifferentTeam(attacker, targ))
+ {
+ LogDeath("tk", deathtype, attacker, targ);
+ GiveFrags(attacker, targ, -1, deathtype);
- if (targ.killcount > 2)
- msg = ftos(targ.killcount);
- else
- msg = "";
+ attacker.killcount = 0;
+
+ Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAG, targ.netname);
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAGGED, attacker.netname);
+ Send_Notification(NOTIF_ANY, world, MSG_INFO, APP_TEAM_NUM_4(targ.team, INFO_DEATH_TEAMKILL_), targ.netname, attacker.netname, targ.killcount);
- if (attacker.killcount > 2) {
- msg = ftos(attacker.killcount);
- type = KILL_TEAM_SPREE;
+ // In this case, the death message will ALWAYS be "foo was betrayed by bar"
+ // No need for specific death/weapon messages...
+ }
+ else
+ {
+ LogDeath("frag", deathtype, attacker, targ);
+ GiveFrags(attacker, targ, 1, deathtype);
+
+ attacker.taunt_soundtime = time + 1;
+ attacker.killcount = attacker.killcount + 1;
+
+ #define SPREE_ITEM(counta,countb,center,normal,gentle) \
+ case counta: \
+ { \
+ AnnounceTo(attacker, strcat(#countb, "kills")); \
+ PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
+ break; \
}
- Send_KillNotification(a, s, msg, type, MSG_KILL);
+ switch(attacker.killcount)
+ {
+ KILL_SPREE_LIST
+ default: break;
+ }
+ #undef SPREE_ITEM
- attacker.killcount = 0;
+ if(!checkrules_firstblood)
+ {
+ checkrules_firstblood = TRUE;
+ notif_firstblood = TRUE; // modify the current messages so that they too show firstblood information
+ PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
+ PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
+ }
- LogDeath("tk", deathtype, attacker, targ);
+ float kill_count_to_attacker;
+ float kill_count_to_target;
+ if(notif_firstblood)
+ {
+ kill_count_to_attacker = -1;
+ kill_count_to_target = -2;
}
else
{
- if (!checkrules_firstblood)
- {
- checkrules_firstblood = TRUE;
- Send_KillNotification(a, "", "", KILL_FIRST_BLOOD, MSG_KILL);
- // TODO: make these print a newline if they dont
- Send_CSQC_KillCenterprint(attacker, "", "", KILL_FIRST_BLOOD, MSG_KILL);
- Send_CSQC_KillCenterprint(targ, "", "", KILL_FIRST_VICTIM, MSG_KILL);
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
- PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
- }
-
- if(targ.istypefrag) {
- Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_TYPEFRAG, MSG_KILL);
- Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_TYPEFRAGGED, MSG_KILL);
- } else {
- Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_FRAG, MSG_KILL);
- Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_FRAGGED, MSG_KILL);
- }
-
- attacker.taunt_soundtime = time + 1;
+ kill_count_to_attacker = attacker.killcount;
+ kill_count_to_target = 0;
+ }
- if (deathtype == DEATH_HURTTRIGGER && inflictor.message2 != "")
- msg = inflictor.message2;
- else if (deathtype == DEATH_CUSTOM)
- msg = deathmessage;
+ if(targ.istypefrag)
+ {
+ if(attacker.FRAG_VERBOSE)
+ Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAG_VERBOSE, targ.netname, kill_count_to_attacker, (IS_BOT_CLIENT(targ) ? NO_MSG : targ.ping));
else
- msg = "";
-
- if(strstrofs(msg, "%", 0) < 0)
- msg = strcat("%s ", msg, " by %s");
+ Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAG, targ.netname, kill_count_to_attacker);
- Send_KillNotification(a, s, msg, deathtype, MSG_KILL);
+ if(targ.FRAG_VERBOSE)
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAGGED_VERBOSE, attacker.netname, kill_count_to_target, attacker.health, attacker.armorvalue, (IS_BOT_CLIENT(attacker) ? NO_MSG : attacker.ping));
+ else
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAGGED, attacker.netname, kill_count_to_target);
+ }
+ else
+ {
+ if(attacker.FRAG_VERBOSE)
+ Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_FRAG_VERBOSE, targ.netname, kill_count_to_attacker, (IS_BOT_CLIENT(targ) ? NO_MSG : targ.ping));
+ else
+ Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_FRAG, targ.netname, kill_count_to_attacker);
- GiveFrags(attacker, targ, 1, deathtype);
+ if(targ.FRAG_VERBOSE)
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_FRAGGED_VERBOSE, attacker.netname, kill_count_to_target, attacker.health, attacker.armorvalue, (IS_BOT_CLIENT(attacker) ? NO_MSG : attacker.ping));
+ else
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_FRAGGED, attacker.netname, kill_count_to_target);
+ }
- if (targ.killcount > 2) {
- Send_KillNotification(s, ftos(targ.killcount), a, KILL_END_SPREE, MSG_SPREE);
- }
+ if not(Obituary_WeaponDeath(targ, TRUE, deathtype, targ.netname, attacker.netname, targ.killcount, kill_count_to_attacker))
+ Obituary_SpecialDeath(targ, TRUE, deathtype, targ.netname, attacker.netname, targ.killcount, kill_count_to_attacker, 0);
+ }
+ }
- attacker.killcount = attacker.killcount + 1;
+ // =============
+ // ACCIDENT/TRAP
+ // =============
+ else
+ {
+ switch(deathtype)
+ {
+ // For now, we're just forcing HURTTRIGGER to behave as "DEATH_VOID" and giving it no special options...
+ // Later on you will only be able to make custom messages using DEATH_CUSTOM,
+ // and there will be a REAL DEATH_VOID implementation which mappers will use.
+ /*case DEATH_HURTTRIGGER:
+ {
+ s1 = targ.netname;
+ s2 = inflictor.message;
+ if(strstrofs(s2, "%", 0) < 0) { s2 = strcat("%s ", s2); }
+ break;
+ }*/
- if (attacker.killcount == 3)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_3, MSG_SPREE);
- AnnounceTo(attacker, "03kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3, 1);
- }
- else if (attacker.killcount == 5)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_5, MSG_SPREE);
- AnnounceTo(attacker, "05kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5, 1);
- }
- else if (attacker.killcount == 10)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_10, MSG_SPREE);
- AnnounceTo(attacker, "10kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10, 1);
- }
- else if (attacker.killcount == 15)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_15, MSG_SPREE);
- AnnounceTo(attacker, "15kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15, 1);
- }
- else if (attacker.killcount == 20)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_20, MSG_SPREE);
- AnnounceTo(attacker, "20kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20, 1);
- }
- else if (attacker.killcount == 25)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_25, MSG_SPREE);
- AnnounceTo(attacker, "25kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25, 1);
- }
- else if (attacker.killcount == 30)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_30, MSG_SPREE);
- AnnounceTo(attacker, "30kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30, 1);
- }
- else if (attacker.killcount > 2) {
- Send_KillNotification(a, ftos(attacker.killcount), "", KILL_SPREE, MSG_SPREE);
- }
- LogDeath("frag", deathtype, attacker, targ);
+ case DEATH_CUSTOM:
+ {
+ Obituary_SpecialDeath(targ, FALSE, deathtype,
+ targ.netname,
+ ((strstrofs(deathmessage, "%", 0) < 0) ? strcat("%s ", deathmessage) : deathmessage),
+ targ.killcount,
+ 0,
+ 0);
+ break;
}
- }
- else
- {
- Send_CSQC_KillCenterprint(targ, "", "", deathtype, MSG_KILL_ACTION);
- if (deathtype == DEATH_HURTTRIGGER && inflictor.message != "")
- msg = inflictor.message;
- else if (deathtype == DEATH_CUSTOM)
- msg = deathmessage;
- else
- msg = "";
- if(strstrofs(msg, "%", 0) < 0)
- msg = strcat("%s ", msg);
-
- GiveFrags(targ, targ, -1, deathtype);
- if(PlayerScore_Add(targ, SP_SCORE, 0) == -5) {
- AnnounceTo(targ, "botlike");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
+
+ default:
+ {
+ Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, "", targ.killcount, 0, 0);
+ break;
}
- Send_KillNotification(s, msg, "", deathtype, MSG_KILL_ACTION);
-
- if (targ.killcount > 2)
- Send_KillNotification(s, ftos(targ.killcount), "", 0, MSG_KILL_ACTION_SPREE);
-
- LogDeath("accident", deathtype, targ, targ);
}
- targ.death_origin = targ.origin;
- if(targ != attacker)
- targ.killer_origin = attacker.origin;
+ LogDeath("accident", deathtype, targ, targ);
+ GiveFrags(targ, targ, -1, deathtype);
- // FIXME: this should go in PutClientInServer
- if (targ.killcount)
- targ.killcount = 0;
+ if(PlayerScore_Add(targ, SP_SCORE, 0) == -5)
+ {
+ AnnounceTo(targ, "botlike");
+ PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
+ }
}
+
+ // Set final information for the death
+ targ.death_origin = targ.origin;
+ if(targ != attacker) { targ.killer_origin = attacker.origin; }
+ if(targ.killcount) { targ.killcount = 0; }
}
// these are updated by each Damage call for use in button triggering and such
}
}
- if(deathtype == DEATH_KILL || deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE || deathtype == DEATH_QUIET)
+ if(deathtype == DEATH_KILL || deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
{
// These are ALWAYS lethal
// No damage modification here
if(targ.takedamage == DAMAGE_AIM)
if(targ != attacker)
{
- if(damage_headshotbonus)
- {
- if(targ.classname == "player")
- {
- // HEAD SHOT:
- // find height of hit on player axis
- // if above view_ofs and below maxs, and also in the middle half of the bbox, it is head shot
- vector headmins, headmaxs, org;
- org = antilag_takebackorigin(targ, time - ANTILAG_LATENCY(attacker));
- headmins = org + GetHeadshotMins(targ);
- headmaxs = org + GetHeadshotMaxs(targ);
- if(trace_hits_box(railgun_start, railgun_end, headmins, headmaxs))
- {
- deathtype |= HITTYPE_HEADSHOT;
- }
- }
- else if(targ.classname == "turret_head")
- {
- deathtype |= HITTYPE_HEADSHOT;
- }
- if(deathtype & HITTYPE_HEADSHOT)
- if(damage_headshotbonus > 0)
- damage *= 1 + damage_headshotbonus;
- }
-
entity victim;
if((targ.vehicle_flags & VHF_ISVEHICLE) && targ.owner)
victim = targ.owner;
if(g_minstagib)
if(victim.items & IT_STRENGTH)
yoda = 1;
-
- if(deathtype & HITTYPE_HEADSHOT)
- headshot = 1;
}
- if(g_ca)
- PlayerScore_Add(attacker, SP_SCORE, damage * autocvar_g_ca_damage2score_multiplier);
}
}
else