[Bug Fix] Send Entity ID in Death Events to resolve #3721 (#3779)

* [Bug Fix] Send Entity ID in Death Events to resolve #3721

# Notes
- Due to some pointers becoming invalid you may get an invalid entity ID on the killed mob if we don't just directly send the entity ID in the export string.

* Update attack.cpp

* Remove GetID() export.
This commit is contained in:
Alex King 2023-12-17 20:43:41 -05:00 committed by GitHub
parent 2cd3d27c67
commit b19ad64800
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 73 deletions

View File

@ -2705,6 +2705,69 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
Corpse* corpse = nullptr;
// Parse quests even if we're killed by an NPC
if (oos) {
if (IsNPC()) {
auto emote_id = GetEmoteID();
if (emote_id) {
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid);
}
}
if (oos->IsNPC()) {
if (parse->HasQuestSub(oos->GetNPCTypeID(), EVENT_NPC_SLAY)) {
parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0);
}
auto emote_id = oos->GetEmoteID();
if (emote_id) {
oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id);
}
if (killer_mob) {
killer_mob->TrySpellOnKill(killed_level, spell);
}
}
}
if (killer_mob && killer_mob->IsBot()) {
if (parse->BotHasQuestSub(EVENT_NPC_SLAY)) {
parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0);
}
killer_mob->TrySpellOnKill(killed_level, spell);
}
m_combat_record.Stop();
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) {
const auto& export_string = fmt::format(
"{} {} {} {}",
killer_mob ? killer_mob->GetID() : 0,
damage,
spell,
static_cast<int>(attack_skill)
);
std::vector<std::any> args = { corpse };
parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args);
}
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) {
const auto& export_string = fmt::format(
"{} {} {} {}",
killer_mob ? killer_mob->GetID() : 0,
damage,
spell,
static_cast<int>(attack_skill)
);
std::vector<std::any> args = { corpse, this };
DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args);
}
if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) &&
((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||
(killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient())))
@ -2814,38 +2877,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
entity_list.RemoveFromXTargets(this);
}
// Parse quests even if we're killed by an NPC
if (oos) {
if (IsNPC()) {
auto emote_id = GetEmoteID();
if (emote_id) {
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid);
}
}
if (oos->IsNPC()) {
if (parse->HasQuestSub(oos->GetNPCTypeID(), EVENT_NPC_SLAY)) {
parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0);
}
auto emote_id = oos->GetEmoteID();
if (emote_id) {
oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id);
}
if (killer_mob) {
killer_mob->TrySpellOnKill(killed_level, spell);
}
}
}
if (killer_mob && killer_mob->IsBot()) {
if (parse->BotHasQuestSub(EVENT_NPC_SLAY)) {
parse->EventBot(EVENT_NPC_SLAY, killer_mob->CastToBot(), this, "", 0);
}
killer_mob->TrySpellOnKill(killed_level, spell);
}
WipeHateList();
p_depop = true;
@ -2854,37 +2885,6 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
entity_list.UpdateFindableNPCState(this, true);
m_combat_record.Stop();
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) {
const auto& export_string = fmt::format(
"{} {} {} {}",
killer_mob ? killer_mob->GetID() : 0,
damage,
spell,
static_cast<int>(attack_skill)
);
std::vector<std::any> args = { corpse };
parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0, &args);
}
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) {
const auto& export_string = fmt::format(
"{} {} {} {}",
killer_mob ? killer_mob->GetID() : 0,
damage,
spell,
static_cast<int>(attack_skill)
);
std::vector<std::any> args = { corpse, this };
DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args);
}
return true;
}

View File

@ -1891,19 +1891,17 @@ void PerlembParser::ExportEventVariables(
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]);
ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]);
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
if (extra_pointers && extra_pointers->size() >= 1)
{
Corpse* corpse = std::any_cast<Corpse*>(extra_pointers->at(0));
if (corpse)
{
if (extra_pointers && extra_pointers->size() >= 1) {
Corpse *corpse = std::any_cast<Corpse *>(extra_pointers->at(0));
if (corpse) {
ExportVar(package_name.c_str(), "killed_corpse_id", corpse->GetID());
}
}
if (extra_pointers && extra_pointers->size() >= 2)
{
NPC* killed = std::any_cast<NPC*>(extra_pointers->at(1));
if (killed)
{
if (extra_pointers && extra_pointers->size() >= 2) {
NPC *killed = std::any_cast<NPC *>(extra_pointers->at(1));
if (killed) {
ExportVar(package_name.c_str(), "killed_entity_id", killed->GetID());
ExportVar(package_name.c_str(), "killed_bot_id", killed->IsBot() ? killed->CastToBot()->GetBotID() : 0);
ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0);