From 1212ccefef7132221425201bc47ff53d83af1468 Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sun, 15 Oct 2023 19:40:25 -0400 Subject: [PATCH] [Quest API] Add target ID and spell exports to events (#3620) * [Quest API] Add target ID and spell exports to events # Notes - Add `$spell` export to `EVENT_CAST`, `EVENT_CAST_BEGIN`, `EVENT_CAST_BEGIN`, `EVENT_ITEM_CLICK`, `EVENT_ITEM_CLICK_CAST`, `EVENT_ITEM_CLICK_CLIENT`, `EVENT_ITEM_CLICK_CAST_CLIENT`, `EVENT_SPELL_EFFECT_BUFF_TIC_BOT`, `EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT`, `EVENT_SPELL_EFFECT_BUFF_TIC_NPC`, `EVENT_SPELL_EFFECT_BOT`, `EVENT_SPELL_EFFECT_CLIENT`, `EVENT_SPELL_EFFECT_NPC`, `EVENT_SPELL_FADE`, `EVENT_DEATH`, `EVENT_DEATH_COMPLETE`, `EVENT_DEATH_ZONE`, `EVENT_DAMAGE_GIVEN`, and `EVENT_DAMAGE_TAKEN` in Perl. - Add `$target_id` export to `EVENT_CAST`, `EVENT_CAST_BEGIN`, and `EVENT_CAST_ON` in Perl. - Add `e.target_id` export to `EVENT_CAST`, `EVENT_CAST_BEGIN`, and `EVENT_CAST_ON` in Lua. * Add $target/e.target exports. * Update spells.cpp --- zone/embparser.cpp | 70 ++++++++++++++++++++++++++++- zone/lua_parser_events.cpp | 30 +++++++++++++ zone/spells.cpp | 92 ++++++++++++++++++++++++++------------ 3 files changed, 162 insertions(+), 30 deletions(-) diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 18fa98c1a..ebcbf6612 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -1560,6 +1560,7 @@ void PerlembParser::ExportEventVariables( if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "target", "Mob", std::any_cast(extra_pointers->at(0))); } + break; } @@ -1606,9 +1607,11 @@ void PerlembParser::ExportEventVariables( case EVENT_CLICK_DOOR: { ExportVar(package_name.c_str(), "doorid", data); ExportVar(package_name.c_str(), "version", zone->GetInstanceVersion()); + if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "door", "Doors", std::any_cast(extra_pointers->at(0))); } + break; } @@ -1649,6 +1652,16 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "spell_id", sep.arg[0]); ExportVar(package_name.c_str(), "caster_id", sep.arg[1]); ExportVar(package_name.c_str(), "caster_level", sep.arg[2]); + ExportVar(package_name.c_str(), "target_id", sep.arg[3]); + + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "target", "Mob", std::any_cast(extra_pointers->at(0))); + } + + if (IsValidSpell(Strings::ToUnsignedInt(sep.arg[0]))) { + ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[Strings::ToUnsignedInt(sep.arg[0])]); + } + break; } @@ -1683,9 +1696,11 @@ void PerlembParser::ExportEventVariables( case EVENT_PLAYER_PICKUP: { ExportVar(package_name.c_str(), "picked_up_id", data); ExportVar(package_name.c_str(), "picked_up_entity_id", extradata); + if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); } + break; } @@ -1731,12 +1746,18 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "itemname", item_inst->GetItem()->Name); ExportVar(package_name.c_str(), "slotid", extradata); ExportVar(package_name.c_str(), "spell_id", item_inst->GetItem()->Click.Effect); + + if (IsValidSpell(item_inst->GetItem()->Click.Effect)) { + ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[item_inst->GetItem()->Click.Effect]); + } + break; } case EVENT_ITEM_CLICK_CAST_CLIENT: case EVENT_ITEM_CLICK_CLIENT: { ExportVar(package_name.c_str(), "slot_id", data); + if (extra_pointers && extra_pointers->size() == 1) { auto* item = std::any_cast(extra_pointers->at(0)); if (item) { @@ -1744,8 +1765,13 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "item_name", item->GetItem()->Name); ExportVar(package_name.c_str(), "spell_id", item->GetItem()->Click.Effect); ExportVar(package_name.c_str(), "item", "QuestItem", item); + + if (IsValidSpell(item->GetItem()->Click.Effect)) { + ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[item->GetItem()->Click.Effect]); + } } } + break; } @@ -1776,6 +1802,11 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "tics_remaining", sep.arg[1]); ExportVar(package_name.c_str(), "caster_level", sep.arg[2]); ExportVar(package_name.c_str(), "buff_slot", sep.arg[3]); + + if (IsValidSpell(objid)) { + ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[objid]); + } + break; } @@ -1789,34 +1820,42 @@ void PerlembParser::ExportEventVariables( case EVENT_FORAGE_SUCCESS: { ExportVar(package_name.c_str(), "foraged_item", extradata); + if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); } + break; } case EVENT_FISH_SUCCESS: { ExportVar(package_name.c_str(), "fished_item", extradata); + if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); } + break; } case EVENT_CLICK_OBJECT: { ExportVar(package_name.c_str(), "objectid", data); ExportVar(package_name.c_str(), "clicker_id", extradata); + if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "object", "Object", std::any_cast(extra_pointers->at(0))); } + break; } case EVENT_DISCOVER_ITEM: { ExportVar(package_name.c_str(), "itemid", extradata); + if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); } + break; } @@ -1843,6 +1882,10 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]); ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]); + if (IsValidSpell(Strings::ToUnsignedInt(sep.arg[2]))) { + ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[Strings::ToUnsignedInt(sep.arg[2])]); + } + if (extra_pointers && extra_pointers->size() == 1) { Mob* killed = std::any_cast(extra_pointers->at(0)); if (killed) { @@ -1867,6 +1910,10 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]); ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]); + if (IsValidSpell(Strings::ToUnsignedInt(sep.arg[2]))) { + ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[Strings::ToUnsignedInt(sep.arg[2])]); + } + if (extra_pointers && extra_pointers->size() >= 1) { Corpse* corpse = std::any_cast(extra_pointers->at(0)); if (corpse) { @@ -1909,6 +1956,7 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "slot_id", extradata); ExportVar(package_name.c_str(), "item", "QuestItem", item_instance); } + break; } @@ -1936,8 +1984,7 @@ void PerlembParser::ExportEventVariables( std::string tradeskill_id = "-1"; if (strcmp(sep.arg[0], "check_zone") == 0) { zone_id = sep.arg[1]; - } - else if (strcmp(sep.arg[0], "check_tradeskill") == 0) { + } else if (strcmp(sep.arg[0], "check_tradeskill") == 0) { tradeskill_id = sep.arg[1]; } @@ -1966,17 +2013,21 @@ void PerlembParser::ExportEventVariables( case EVENT_CONSIDER: { ExportVar(package_name.c_str(), "entity_id", Strings::ToInt(data)); + if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "target", "Mob", std::any_cast(extra_pointers->at(0))); } + break; } case EVENT_CONSIDER_CORPSE: { ExportVar(package_name.c_str(), "corpse_entity_id", Strings::ToInt(data)); + if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "corpse", "Corpse", std::any_cast(extra_pointers->at(0))); } + break; } @@ -1991,9 +2042,11 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "item_id", extradata); ExportVar(package_name.c_str(), "item_quantity", sep.arg[0]); ExportVar(package_name.c_str(), "slot_id", sep.arg[1]); + if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); } + break; } @@ -2003,9 +2056,11 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "item_id", extradata); ExportVar(package_name.c_str(), "item_quantity", sep.arg[0]); ExportVar(package_name.c_str(), "slot_id", sep.arg[1]); + if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "item", "QuestItem", std::any_cast(extra_pointers->at(0))); } + break; } @@ -2111,9 +2166,11 @@ void PerlembParser::ExportEventVariables( case EVENT_INSPECT: { ExportVar(package_name.c_str(), "target_id", extradata); + if (extra_pointers && extra_pointers->size() == 1) { ExportVar(package_name.c_str(), "target", "Mob", std::any_cast(extra_pointers->at(0))); } + break; } @@ -2138,6 +2195,7 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "area_id", *std::any_cast(extra_pointers->at(0))); ExportVar(package_name.c_str(), "area_type", *std::any_cast(extra_pointers->at(1))); } + break; } @@ -2177,6 +2235,11 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "buff_slot", sep.arg[6]); ExportVar(package_name.c_str(), "is_buff_tic", sep.arg[7]); ExportVar(package_name.c_str(), "special_attack", sep.arg[8]); + + if (IsValidSpell(Strings::ToUnsignedInt(sep.arg[2]))) { + ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[Strings::ToUnsignedInt(sep.arg[2])]); + } + break; } @@ -2188,6 +2251,7 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "quantity", inst->IsStackable() ? inst->GetCharges() : 1); ExportVar(package_name.c_str(), "item", "QuestItem", inst); } + break; } @@ -2198,9 +2262,11 @@ void PerlembParser::ExportEventVariables( Seperator sep(data); ExportVar(package_name.c_str(), "slot_id", sep.arg[0]); ExportVar(package_name.c_str(), "spell_id", sep.arg[1]); + if (IsValidSpell(Strings::ToUnsignedInt(sep.arg[1]))) { ExportVar(package_name.c_str(), "spell", "Spell", (void*)&spells[Strings::ToUnsignedInt(sep.arg[1])]); } + break; } diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index ca351b4a6..969518408 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -354,6 +354,16 @@ void handle_npc_cast( lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[2])); lua_setfield(L, -2, "caster_level"); + + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[3])); + lua_setfield(L, -2, "target_id"); + + if (extra_pointers && extra_pointers->size() == 1) { + Lua_Mob l_mob(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "target"); + } } void handle_npc_area( @@ -715,6 +725,16 @@ void handle_player_cast( lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[2])); lua_setfield(L, -2, "caster_level"); + + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[3])); + lua_setfield(L, -2, "target_id"); + + if (extra_pointers && extra_pointers->size() == 1) { + Lua_Mob l_mob(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "target"); + } } void handle_player_task_fail( @@ -1955,6 +1975,16 @@ void handle_bot_cast( lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[2])); lua_setfield(L, -2, "caster_level"); + + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[3])); + lua_setfield(L, -2, "target_id"); + + if (extra_pointers && extra_pointers->size() == 1) { + Lua_Mob l_mob(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "target"); + } } void handle_bot_combat( diff --git a/zone/spells.cpp b/zone/spells.cpp index faecbf48b..714312413 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -238,13 +238,16 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, if (IsClient()) { if (parse->PlayerHasQuestSub(EVENT_CAST_BEGIN)) { + Mob* spell_target = entity_list.GetMobID(target_id); + std::vector args = { spell_target }; const auto& export_string = fmt::format( - "{} {} {}", + "{} {} {} {}", spell_id, GetID(), - GetCasterLevel(spell_id) + GetCasterLevel(spell_id), + target_id ); - if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), export_string, 0) != 0) { + if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), export_string, 0, &args) != 0) { if (IsDiscipline(spell_id)) { CastToClient()->SendDisciplineTimer(spells[spell_id].timer_id, 0); } @@ -256,23 +259,29 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, } } else if (IsNPC()) { if (parse->HasQuestSub(GetNPCTypeID(), EVENT_CAST_BEGIN)) { + Mob* spell_target = entity_list.GetMobID(target_id); + std::vector args = { spell_target }; const auto& export_string = fmt::format( - "{} {} {}", + "{} {} {} {}", spell_id, GetID(), - GetCasterLevel(spell_id) + GetCasterLevel(spell_id), + target_id ); - parse->EventNPC(EVENT_CAST_BEGIN, CastToNPC(), nullptr, export_string, 0); + parse->EventNPC(EVENT_CAST_BEGIN, CastToNPC(), nullptr, export_string, 0, &args); } } else if (IsBot()) { if (parse->BotHasQuestSub(EVENT_CAST_BEGIN)) { + Mob* spell_target = entity_list.GetMobID(target_id); + std::vector args = { spell_target }; const auto& export_string = fmt::format( - "{} {} {}", + "{} {} {} {}", spell_id, GetID(), - GetCasterLevel(spell_id) + GetCasterLevel(spell_id), + target_id ); - parse->EventBot(EVENT_CAST_BEGIN, CastToBot(), nullptr, export_string, 0); + parse->EventBot(EVENT_CAST_BEGIN, CastToBot(), nullptr, export_string, 0, &args); } } @@ -1648,24 +1657,41 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo // at this point the spell has successfully been cast // - const auto& export_string = fmt::format( - "{} {} {}", - spell_id, - GetID(), - GetCasterLevel(spell_id) - ); - if (IsClient()) { if (parse->PlayerHasQuestSub(EVENT_CAST)) { - parse->EventPlayer(EVENT_CAST, CastToClient(), export_string, 0); + std::vector args = { spell_target }; + const auto& export_string = fmt::format( + "{} {} {} {}", + spell_id, + GetID(), + GetCasterLevel(spell_id), + target_id + ); + parse->EventPlayer(EVENT_CAST, CastToClient(), export_string, 0, &args); } } else if (IsNPC()) { if (parse->HasQuestSub(GetNPCTypeID(), EVENT_CAST)) { - parse->EventNPC(EVENT_CAST, CastToNPC(), nullptr, export_string, 0); + std::vector args = { spell_target }; + const auto& export_string = fmt::format( + "{} {} {} {}", + spell_id, + GetID(), + GetCasterLevel(spell_id), + target_id + ); + parse->EventNPC(EVENT_CAST, CastToNPC(), nullptr, export_string, 0, &args); } } else if (IsBot()) { if (parse->BotHasQuestSub(EVENT_CAST)) { - parse->EventBot(EVENT_CAST, CastToBot(), nullptr, export_string, 0); + std::vector args = { spell_target }; + const auto& export_string = fmt::format( + "{} {} {} {}", + spell_id, + GetID(), + GetCasterLevel(spell_id), + target_id + ); + parse->EventBot(EVENT_CAST, CastToBot(), nullptr, export_string, 0, &args); } } @@ -3664,10 +3690,14 @@ bool Mob::SpellOnTarget( } // select target + uint16 target_id = 0; + if (IsEffectInSpell(spell_id, SE_BindSight)) { action->target = GetID(); + target_id = GetID(); } else { action->target = spelltar->GetID(); + target_id = spelltar->GetID(); } action->spell_level = action->level = caster_level; // caster level, for animation only @@ -3700,33 +3730,39 @@ bool Mob::SpellOnTarget( if (spelltar->IsNPC()) { if (parse->HasQuestSub(spelltar->GetNPCTypeID(), EVENT_CAST_ON)) { + std::vector args = { spelltar }; const auto& export_string = fmt::format( - "{} {} {}", + "{} {} {} {}", spell_id, GetID(), - caster_level + caster_level, + target_id ); - parse->EventNPC(EVENT_CAST_ON, spelltar->CastToNPC(), this, export_string, 0); + parse->EventNPC(EVENT_CAST_ON, spelltar->CastToNPC(), this, export_string, 0, &args); } } else if (spelltar->IsClient()) { if (parse->PlayerHasQuestSub(EVENT_CAST_ON)) { + std::vector args = { spelltar }; const auto& export_string = fmt::format( - "{} {} {}", + "{} {} {} {}", spell_id, GetID(), - caster_level + caster_level, + target_id ); - parse->EventPlayer(EVENT_CAST_ON, spelltar->CastToClient(), export_string, 0); + parse->EventPlayer(EVENT_CAST_ON, spelltar->CastToClient(), export_string, 0, &args); } } else if (spelltar->IsBot()) { if (parse->BotHasQuestSub(EVENT_CAST_ON)) { + std::vector args = { spelltar }; const auto& export_string = fmt::format( - "{} {} {}", + "{} {} {} {}", spell_id, GetID(), - caster_level + caster_level, + target_id ); - parse->EventBot(EVENT_CAST_ON, spelltar->CastToBot(), this, export_string, 0); + parse->EventBot(EVENT_CAST_ON, spelltar->CastToBot(), this, export_string, 0, &args); } }