[Quest API] Fix issue with death events. (#3823)

# Notes
- Death events were happening too early so stuff checking for dead NPCs was non-functional.
This commit is contained in:
Alex King 2023-12-31 17:37:26 -05:00 committed by GitHub
parent 2f4af4f0c2
commit b93dec357f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 69 deletions

View File

@ -2705,68 +2705,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
Corpse* corpse = nullptr; Corpse* corpse = nullptr;
// Parse quests even if we're killed by an NPC const uint16 entity_id = GetID();
if (oos) {
if (IsNPC()) {
auto emote_id = GetEmoteID();
if (emote_id) {
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDeath, emoteid, killer_mob);
}
}
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, this);
}
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) && if (!HasOwner() && !IsMerc() && !GetSwarmInfo() && (!is_merchant || allow_merchant_corpse) &&
((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) || ((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) ||
@ -2877,6 +2816,39 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
entity_list.RemoveFromXTargets(this); 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, killer_mob);
}
}
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, this);
}
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(); WipeHateList();
p_depop = true; p_depop = true;
@ -2885,6 +2857,39 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
entity_list.UpdateFindableNPCState(this, true); 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),
entity_id
);
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),
entity_id
);
std::vector<std::any> args = { corpse, this };
DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args);
}
return true; return true;
} }

View File

@ -1891,6 +1891,7 @@ void PerlembParser::ExportEventVariables(
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]); 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_spell", sep.arg[2]);
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]); ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
ExportVar(package_name.c_str(), "killed_entity_id", sep.arg[4]);
if (extra_pointers && extra_pointers->size() >= 1) { if (extra_pointers && extra_pointers->size() >= 1) {
Corpse *corpse = std::any_cast<Corpse *>(extra_pointers->at(0)); Corpse *corpse = std::any_cast<Corpse *>(extra_pointers->at(0));
@ -1902,7 +1903,6 @@ void PerlembParser::ExportEventVariables(
if (extra_pointers && extra_pointers->size() >= 2) { if (extra_pointers && extra_pointers->size() >= 2) {
NPC *killed = std::any_cast<NPC *>(extra_pointers->at(1)); NPC *killed = std::any_cast<NPC *>(extra_pointers->at(1));
if (killed) { 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_bot_id", killed->IsBot() ? killed->CastToBot()->GetBotID() : 0);
ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0); ExportVar(package_name.c_str(), "killed_npc_id", killed->IsNPC() ? killed->GetNPCTypeID() : 0);
ExportVar(package_name.c_str(), "killed_x", killed->GetX()); ExportVar(package_name.c_str(), "killed_x", killed->GetX());

View File

@ -289,12 +289,13 @@ void handle_npc_death(
uint32 extra_data, uint32 extra_data,
std::vector<std::any> *extra_pointers std::vector<std::any> *extra_pointers
) { ) {
Seperator sep(data.c_str());
Lua_Mob l_mob(init); Lua_Mob l_mob(init);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L); l_mob_o.push(L);
lua_setfield(L, -2, "other"); lua_setfield(L, -2, "other");
Seperator sep(data.c_str());
lua_pushinteger(L, Strings::ToInt(sep.arg[0])); lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "killer_id"); lua_setfield(L, -2, "killer_id");
@ -317,6 +318,9 @@ void handle_npc_death(
lua_pushinteger(L, Strings::ToInt(sep.arg[3])); lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "skill_id"); lua_setfield(L, -2, "skill_id");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[4]));
lua_setfield(L, -2, "killed_entity_id");
if (extra_pointers && extra_pointers->size() >= 1) { if (extra_pointers && extra_pointers->size() >= 1) {
Lua_Corpse l_corpse(std::any_cast<Corpse*>(extra_pointers->at(0))); Lua_Corpse l_corpse(std::any_cast<Corpse*>(extra_pointers->at(0)));
luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse);
@ -600,14 +604,14 @@ void handle_player_death(
l_mob_o.push(L); l_mob_o.push(L);
lua_setfield(L, -2, "other"); lua_setfield(L, -2, "other");
lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[0]));
lua_setfield(L, -2, "killer_id"); lua_setfield(L, -2, "killer_id");
lua_pushinteger(L, Strings::ToInt(sep.arg[2])); lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "damage"); lua_setfield(L, -2, "damage");
int spell_id = Strings::ToInt(sep.arg[3]); const uint32 spell_id = Strings::ToUnsignedInt(sep.arg[2]);
if(IsValidSpell(spell_id)) { if (IsValidSpell(spell_id)) {
Lua_Spell l_spell(&spells[spell_id]); Lua_Spell l_spell(&spells[spell_id]);
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
l_spell_o.push(L); l_spell_o.push(L);
@ -619,8 +623,11 @@ void handle_player_death(
lua_setfield(L, -2, "spell"); lua_setfield(L, -2, "spell");
} }
lua_pushinteger(L, Strings::ToInt(sep.arg[4])); lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "skill"); lua_setfield(L, -2, "skill");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[4]));
lua_setfield(L, -2, "killed_entity_id");
} }
void handle_player_timer( void handle_player_timer(
@ -2136,6 +2143,9 @@ void handle_bot_death(
l_mob_o.push(L); l_mob_o.push(L);
lua_setfield(L, -2, "other"); lua_setfield(L, -2, "other");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[0]));
lua_setfield(L, -2, "killer_id");
lua_pushinteger(L, Strings::ToInt(sep.arg[1])); lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "damage"); lua_setfield(L, -2, "damage");
@ -2154,6 +2164,9 @@ void handle_bot_death(
lua_pushinteger(L, Strings::ToInt(sep.arg[3])); lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "skill"); lua_setfield(L, -2, "skill");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[4]));
lua_setfield(L, -2, "killed_entity_id");
} }
void handle_bot_popup_response( void handle_bot_popup_response(