From 1dbd494f4f1d5d5319e360061c76d82ce3689fb4 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Wed, 4 Jun 2025 22:36:44 -0400 Subject: [PATCH] Add other events, finish Lua --- zone/attack.cpp | 19 +++ zone/client_packet.cpp | 16 +++ zone/corpse.cpp | 15 +++ zone/embparser.cpp | 60 +++++++-- zone/entity.cpp | 5 + zone/lua_parser.cpp | 20 ++- zone/lua_parser_events.cpp | 244 +++++++++++++++++++++++++++++++++++++ zone/lua_parser_events.h | 108 ++++++++++++++++ zone/lua_zone.cpp | 77 ++++++++++++ zone/lua_zone.h | 11 ++ zone/npc.cpp | 5 + zone/object.cpp | 24 ++++ zone/perl_zone.cpp | 12 ++ zone/zone.cpp | 23 ++++ zone/zone.h | 4 + 15 files changed, 631 insertions(+), 12 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index e28eac7cc..9c6581a32 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3039,6 +3039,25 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy DispatchZoneControllerEvent(EVENT_DEATH_ZONE, owner_or_self, export_string, 0, &args); } + if (parse->ZoneHasQuestSub(EVENT_DEATH_ZONE)) { + const auto& export_string = fmt::format( + "{} {} {} {} {} {} {} {} {}", + killer_mob ? killer_mob->GetID() : 0, + damage, + spell, + static_cast(attack_skill), + entity_id, + m_combat_record.GetStartTime(), + m_combat_record.GetEndTime(), + m_combat_record.GetDamageReceived(), + m_combat_record.GetHealingReceived() + ); + + std::vector args = { corpse, this, owner_or_self }; + + parse->EventZone(EVENT_DEATH_ZONE, zone, export_string, 0, &args); + } + return true; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a69a6b96e..87b0a747d 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4709,6 +4709,12 @@ void Client::Handle_OP_ClickDoor(const EQApplicationPacket *app) quest_return = parse->EventPlayer(EVENT_CLICK_DOOR, this, std::to_string(cd->doorid), 0, &args); } + if (parse->ZoneHasQuestSub(EVENT_CLICK_DOOR)) { + std::vector args = { currentdoor, this }; + + quest_return = parse->EventZone(EVENT_CLICK_DOOR, zone, std::to_string(cd->doorid), 0, &args); + } + if (quest_return == 0) { currentdoor->HandleClick(this, 0); } @@ -4741,6 +4747,11 @@ void Client::Handle_OP_ClickObject(const EQApplicationPacket *app) parse->EventPlayer(EVENT_CLICK_OBJECT, this, std::to_string(click_object->drop_id), GetID(), &args); } + if (parse->ZoneHasQuestSub(EVENT_CLICK_OBJECT)) { + std::vector args = { object, this }; + parse->EventZone(EVENT_CLICK_OBJECT, zone, std::to_string(click_object->drop_id), GetID(), &args); + } + if (IsDevToolsEnabled()) { SetObjectToolEntityId(entity->GetID()); ObjectManipulation::CommandHeader(this); @@ -12042,6 +12053,11 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) parse->EventPlayer(EVENT_POPUP_RESPONSE, this, std::to_string(popup_response->popupid), 0); } + if (parse->ZoneHasQuestSub(EVENT_POPUP_RESPONSE)) { + std::vector args = { this }; + parse->EventZone(EVENT_POPUP_RESPONSE, zone, std::to_string(popup_response->popupid), 0, &args); + } + auto t = GetTarget(); if (t) { parse->EventBotMercNPC(EVENT_POPUP_RESPONSE, t, this, [&]() { return std::to_string(popup_response->popupid); }); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index f0b04a8f5..9bd13d63b 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1586,6 +1586,21 @@ void Corpse::LootCorpseItem(Client *c, const EQApplicationPacket *app) } } + if (parse->ZoneHasQuestSub(EVENT_LOOT_ZONE)) { + const auto &export_string = fmt::format( + "{} {} {} {}", + inst->GetItem()->ID, + inst->GetCharges(), + EntityList::RemoveNumbers(corpse_name), + GetID() + ); + + std::vector args = {inst, this, c}; + if (parse->EventZone(EVENT_LOOT_ZONE, zone, export_string, 0, &args) != 0) { + prevent_loot = true; + } + } + if (inst && PlayerEventLogs::Instance()->IsEventEnabled(PlayerEvent::LOOT_ITEM) && !IsPlayerCorpse()) { auto e = PlayerEvent::LootItemEvent{ .item_id = inst->GetItem()->ID, diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 6df98d807..98376ac70 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -1675,10 +1675,14 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "doorid", data); ExportVar(package_name.c_str(), "version", zone->GetInstanceVersion()); - if (extra_pointers && extra_pointers->size() == 1) { + if (extra_pointers && extra_pointers->size() >= 1) { ExportVar(package_name.c_str(), "door", "Doors", std::any_cast(extra_pointers->at(0))); } + if (extra_pointers && extra_pointers->size() == 2) { + ExportVar(package_name.c_str(), "client", "Client", std::any_cast(extra_pointers->at(1))); + } + break; } @@ -1699,10 +1703,14 @@ void PerlembParser::ExportEventVariables( ); } - if (extra_pointers && extra_pointers->size() == 2) { + if (extra_pointers && extra_pointers->size() >= 2) { ExportVar(package_name.c_str(), "corpse", "Corpse", std::any_cast(extra_pointers->at(1))); } + if (extra_pointers && extra_pointers->size() == 3) { + ExportVar(package_name.c_str(), "client", "Client", std::any_cast(extra_pointers->at(2))); + } + break; } @@ -1769,7 +1777,7 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "picked_up_id", data); ExportVar(package_name.c_str(), "picked_up_entity_id", extra_data); - if (extra_pointers && extra_pointers->size() == 1) { + if (extra_pointers && extra_pointers->size() >= 1) { ExportVar( package_name.c_str(), "item", @@ -1778,6 +1786,10 @@ void PerlembParser::ExportEventVariables( ); } + if (extra_pointers && extra_pointers->size() == 2) { + ExportVar(package_name.c_str(), "client", "Client", std::any_cast(extra_pointers->at(1))); + } + break; } @@ -1790,6 +1802,11 @@ void PerlembParser::ExportEventVariables( case EVENT_POPUP_RESPONSE: { ExportVar(package_name.c_str(), "popupid", data); + + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "client", "Client", std::any_cast(extra_pointers->at(0))); + } + break; } @@ -1953,10 +1970,14 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "objectid", data); ExportVar(package_name.c_str(), "clicker_id", extra_data); - if (extra_pointers && extra_pointers->size() == 1) { + if (extra_pointers && extra_pointers->size() >= 1) { ExportVar(package_name.c_str(), "object", "Object", std::any_cast(extra_pointers->at(0))); } + if (extra_pointers && extra_pointers->size() == 2) { + ExportVar(package_name.c_str(), "client", "Client", std::any_cast(extra_pointers->at(1))); + } + break; } @@ -2032,6 +2053,13 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "killed_npc_id", !killed->IsMerc() && killed->IsNPC() ? killed->GetNPCTypeID() : 0); } } + + if (extra_pointers && extra_pointers->size() == 3) { + Mob* killer = std::any_cast(extra_pointers->at(2)); + if (killer) { + ExportVar(package_name.c_str(), "killer", "Mob", killer); + } + } break; } @@ -2059,10 +2087,21 @@ void PerlembParser::ExportEventVariables( } case EVENT_SPAWN_ZONE: { - ExportVar(package_name.c_str(), "spawned_entity_id", mob->GetID()); - ExportVar(package_name.c_str(), "spawned_bot_id", mob->IsBot() ? mob->CastToBot()->GetBotID() : 0); - ExportVar(package_name.c_str(), "spawned_npc_id", mob->IsNPC() ? mob->GetNPCTypeID() : 0); - ExportVar(package_name.c_str(), "spawned", "Mob", mob); + if (mob) { + ExportVar(package_name.c_str(), "spawned_entity_id", mob->GetID()); + ExportVar(package_name.c_str(), "spawned_bot_id", mob->IsBot() ? mob->CastToBot()->GetBotID() : 0); + ExportVar(package_name.c_str(), "spawned_npc_id", mob->IsNPC() ? mob->GetNPCTypeID() : 0); + ExportVar(package_name.c_str(), "spawned", "Mob", mob); + } + + if (extra_pointers && extra_pointers->size() == 1) { + Mob* spawn_mob = std::any_cast(extra_pointers->at(0)); + ExportVar(package_name.c_str(), "spawned_entity_id", spawn_mob->GetID()); + ExportVar(package_name.c_str(), "spawned_bot_id", spawn_mob->IsBot() ? spawn_mob->CastToBot()->GetBotID() : 0); + ExportVar(package_name.c_str(), "spawned_npc_id", spawn_mob->IsNPC() ? spawn_mob->GetNPCTypeID() : 0); + ExportVar(package_name.c_str(), "spawned", "Mob", spawn_mob); + } + break; } @@ -2314,6 +2353,11 @@ void PerlembParser::ExportEventVariables( ExportVar(package_name.c_str(), "despawned_entity_id", mob->GetID()); ExportVar(package_name.c_str(), "despawned_bot_id", mob->IsBot() ? mob->CastToBot()->GetBotID() : 0); ExportVar(package_name.c_str(), "despawned_npc_id", mob->IsNPC() ? mob->GetNPCTypeID() : 0); + + if (extra_pointers && extra_pointers->size() == 1) { + ExportVar(package_name.c_str(), "npc", "NPC", std::any_cast(extra_pointers->at(0))); + } + break; } diff --git a/zone/entity.cpp b/zone/entity.cpp index b87895001..0b94fc7ac 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -743,6 +743,11 @@ void EntityList::AddNPC(NPC *npc, bool send_spawn_packet, bool dont_queue) npc->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, npc, "", 0, nullptr); } + if (parse->ZoneHasQuestSub(EVENT_SPAWN_ZONE)) { + std::vector args = { npc }; + parse->EventZone(EVENT_SPAWN_ZONE, zone, "", 0, &args); + } + if (zone->HasMap() && zone->HasWaterMap()) { npc->SetSpawnedInWater(false); if (zone->watermap->InLiquid(npc->GetPosition())) { diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 29cb3fd17..79efbc29d 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -219,6 +219,7 @@ LuaParser::LuaParser() { SpellArgumentDispatch[i] = handle_spell_null; EncounterArgumentDispatch[i] = handle_encounter_null; BotArgumentDispatch[i] = handle_bot_null; + ZoneArgumentDispatch[i] = handle_zone_null; } NPCArgumentDispatch[EVENT_SAY] = handle_npc_event_say; @@ -410,10 +411,21 @@ LuaParser::LuaParser() { BotArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_bot_entity_variable; BotArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_bot_spell_blocked; - ZoneArgumentDispatch[EVENT_TIMER_PAUSE] = handle_zone_timer_pause_resume_start; - ZoneArgumentDispatch[EVENT_TIMER_RESUME] = handle_zone_timer_pause_resume_start; - ZoneArgumentDispatch[EVENT_TIMER_START] = handle_zone_timer_pause_resume_start; - ZoneArgumentDispatch[EVENT_TIMER_STOP] = handle_zone_timer_stop; + ZoneArgumentDispatch[EVENT_CLICK_DOOR] = handle_zone_click_door; + ZoneArgumentDispatch[EVENT_CLICK_OBJECT] = handle_zone_click_object; + ZoneArgumentDispatch[EVENT_DEATH_ZONE] = handle_zone_death; + ZoneArgumentDispatch[EVENT_DESPAWN_ZONE] = handle_zone_despawn; + ZoneArgumentDispatch[EVENT_LOOT_ZONE] = handle_zone_loot; + ZoneArgumentDispatch[EVENT_PAYLOAD] = handle_zone_payload; + ZoneArgumentDispatch[EVENT_PLAYER_PICKUP] = handle_zone_pickup; + ZoneArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_zone_popup; + ZoneArgumentDispatch[EVENT_SIGNAL] = handle_zone_signal; + ZoneArgumentDispatch[EVENT_SPAWN_ZONE] = handle_zone_spawn; + ZoneArgumentDispatch[EVENT_TIMER] = handle_zone_timer; + ZoneArgumentDispatch[EVENT_TIMER_PAUSE] = handle_zone_timer_pause_resume_start; + ZoneArgumentDispatch[EVENT_TIMER_RESUME] = handle_zone_timer_pause_resume_start; + ZoneArgumentDispatch[EVENT_TIMER_START] = handle_zone_timer_pause_resume_start; + ZoneArgumentDispatch[EVENT_TIMER_STOP] = handle_zone_timer_stop; #endif L = nullptr; diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index cb176e1c1..c7cdb401c 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -2875,6 +2875,250 @@ void handle_bot_spell_blocked( // Zone +void handle_zone_null( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { +} + +void handle_zone_click_door( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Door l_door(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_door_o = luabind::adl::object(L, l_door); + l_door_o.push(L); + lua_setfield(L, -2, "door"); + + Lua_Client l_client(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_click_object( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Object l_object(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_object_o = luabind::adl::object(L, l_object); + l_object_o.push(L); + lua_setfield(L, -2, "object"); + + Lua_Client l_client(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_death( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + Lua_Mob l_mob(std::any_cast(extra_pointers->at(2))); + luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob); + l_mob_o.push(L); + lua_setfield(L, -2, "other"); + + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); + lua_setfield(L, -2, "killer_id"); + + lua_pushinteger(L, Strings::ToInt(sep.arg[1])); + lua_setfield(L, -2, "damage"); + + const uint32 spell_id = Strings::ToUnsignedInt(sep.arg[2]); + if (IsValidSpell(spell_id)) { + Lua_Spell l_spell(&spells[spell_id]); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + lua_setfield(L, -2, "spell"); + } else { + Lua_Spell l_spell(nullptr); + luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell); + l_spell_o.push(L); + lua_setfield(L, -2, "spell"); + } + + lua_pushinteger(L, Strings::ToInt(sep.arg[3])); + lua_setfield(L, -2, "skill_id"); + + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[4])); + lua_setfield(L, -2, "killed_entity_id"); + + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[5])); + lua_setfield(L, -2, "combat_start_time"); + + lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[6])); + lua_setfield(L, -2, "combat_end_time"); + + lua_pushinteger(L, Strings::ToBigInt(sep.arg[7])); + lua_setfield(L, -2, "damage_received"); + + lua_pushinteger(L, Strings::ToBigInt(sep.arg[8])); + lua_setfield(L, -2, "healing_received"); + + if (extra_pointers && extra_pointers->size() >= 1) { + Lua_Corpse l_corpse(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); + l_corpse_o.push(L); + lua_setfield(L, -2, "corpse"); + } + + if (extra_pointers && extra_pointers->size() >= 2) { + Lua_NPC l_npc(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); + l_npc_o.push(L); + lua_setfield(L, -2, "killed"); + } +} + +void handle_zone_despawn( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + 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, "other"); +} + +void handle_zone_loot( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_Client l_client(std::any_cast(extra_pointers->at(2))); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); + + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); + l_item_o.push(L); + lua_setfield(L, -2, "item"); + + Lua_Corpse l_corpse(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse); + l_corpse_o.push(L); + lua_setfield(L, -2, "corpse"); +} + +void handle_zone_payload( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Seperator sep(data.c_str()); + + lua_pushinteger(L, Strings::ToInt(sep.arg[0])); + lua_setfield(L, -2, "payload_id"); + + lua_pushstring(L, sep.argplus[1]); + lua_setfield(L, -2, "payload_value"); +} + +void handle_zone_pickup( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_ItemInst l_item(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_item_o = luabind::adl::object(L, l_item); + l_item_o.push(L); + lua_setfield(L, -2, "item"); + + Lua_Client l_client(std::any_cast(extra_pointers->at(1))); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_popup( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, Strings::ToInt(data)); + lua_setfield(L, -2, "popup_id"); + + Lua_Client l_client(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_client_o = luabind::adl::object(L, l_client); + l_client_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_signal( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushinteger(L, Strings::ToInt(data)); + lua_setfield(L, -2, "signal"); +} + +void handle_zone_spawn( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + Lua_NPC l_npc(std::any_cast(extra_pointers->at(0))); + luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc); + l_npc_o.push(L); + lua_setfield(L, -2, "other"); +} + +void handle_zone_timer( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +) { + lua_pushstring(L, data.c_str()); + lua_setfield(L, -2, "timer"); +} + void handle_zone_timer_pause_resume_start( QuestInterface *parse, lua_State* L, diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index afb5a6957..7629345ae 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -1280,6 +1280,114 @@ void handle_bot_spell_blocked( ); // Zone +void handle_zone_null( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_click_door( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_click_object( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_death( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_despawn( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_loot( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_payload( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_pickup( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_popup( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_signal( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_spawn( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + +void handle_zone_timer( + QuestInterface *parse, + lua_State* L, + Zone* zone, + std::string data, + uint32 extra_data, + std::vector *extra_pointers +); + void handle_zone_timer_pause_resume_start( QuestInterface *parse, lua_State* L, diff --git a/zone/lua_zone.cpp b/zone/lua_zone.cpp index 8250296ff..3907a3ed9 100644 --- a/zone/lua_zone.cpp +++ b/zone/lua_zone.cpp @@ -772,6 +772,72 @@ bool Lua_Zone::VariableExists(const std::string& variable_name) return self->VariableExists(variable_name); } +uint32 Lua_Zone::GetTimerDuration(std::string name) +{ + Lua_Safe_Call_Int(); + return self->GetTimerDuration(name); +} + +uint32 Lua_Zone::GetTimerRemainingTime(std::string name) +{ + Lua_Safe_Call_Int(); + return self->GetTimerRemainingTime(name); +} + +bool Lua_Zone::HasTimer(std::string name) +{ + Lua_Safe_Call_Bool(); + return self->HasTimer(name); +} + +bool Lua_Zone::IsPausedTimer(std::string name) +{ + Lua_Safe_Call_Bool(); + return self->IsPausedTimer(name); +} + +void Lua_Zone::PauseTimer(std::string name) +{ + Lua_Safe_Call_Void(); + self->PauseTimer(name); +} + +void Lua_Zone::ResumeTimer(std::string name) +{ + Lua_Safe_Call_Void(); + self->ResumeTimer(name); +} + +void Lua_Zone::SetTimer(std::string name, uint32 duration) +{ + Lua_Safe_Call_Void(); + self->SetTimer(name, duration); +} + +void Lua_Zone::StopTimer(std::string name) +{ + Lua_Safe_Call_Void(); + self->StopTimer(name); +} + +void Lua_Zone::StopAllTimers() +{ + Lua_Safe_Call_Void(); + self->StopAllTimers(); +} + +void Lua_Zone::SendPayload(int payload_id, std::string payload_value) +{ + Lua_Safe_Call_Void(); + self->SendPayload(payload_id, payload_value); +} + +void Lua_Zone::Signal(int signal_id) +{ + Lua_Safe_Call_Void(); + self->Signal(signal_id); +} + luabind::scope lua_register_zone() { return luabind::class_("Zones") .def(luabind::constructor<>()) @@ -861,6 +927,8 @@ luabind::scope lua_register_zone() { .def("GetSnowDuration", (int(Lua_Zone::*)(uint8))&Lua_Zone::GetSnowDuration) .def("GetTimeType", &Lua_Zone::GetTimeType) .def("GetTimeZone", &Lua_Zone::GetTimeZone) + .def("GetTimerDuration", &Lua_Zone::GetTimerDuration) + .def("GetTimerRemainingTime", &Lua_Zone::GetTimerRemainingTime) .def("GetZoneDescription", &Lua_Zone::GetZoneDescription) .def("GetZoneID", &Lua_Zone::GetZoneID) .def("GetZoneType", &Lua_Zone::GetZoneType) @@ -875,10 +943,12 @@ luabind::scope lua_register_zone() { .def("HasMap", &Lua_Zone::HasMap) .def("HasWaterMap", &Lua_Zone::HasWaterMap) .def("HasWeather", &Lua_Zone::HasWeather) + .def("HasTimer", &Lua_Zone::HasTimer) .def("IsCity", &Lua_Zone::IsCity) .def("IsHotzone", &Lua_Zone::IsHotzone) .def("IsInstancePersistent", &Lua_Zone::IsInstancePersistent) .def("IsIdleWhenEmpty", &Lua_Zone::IsIdleWhenEmpty) + .def("IsPausedTimer", &Lua_Zone::IsPausedTimer) .def("IsPVPZone", &Lua_Zone::IsPVPZone) .def("IsRaining", &Lua_Zone::IsRaining) .def("IsSnowing", &Lua_Zone::IsSnowing) @@ -887,8 +957,11 @@ luabind::scope lua_register_zone() { .def("IsStaticZone", &Lua_Zone::IsStaticZone) .def("IsUCSServerAvailable", &Lua_Zone::IsUCSServerAvailable) .def("IsWaterZone", &Lua_Zone::IsWaterZone) + .def("PauseTimer", &Lua_Zone::PauseTimer) .def("Repop", (void(Lua_Zone::*)(void))&Lua_Zone::Repop) .def("Repop", (void(Lua_Zone::*)(bool))&Lua_Zone::Repop) + .def("ResumeTimer", &Lua_Zone::ResumeTimer) + .def("SendPayload", &Lua_Zone::SendPayload) .def("SetAAEXPModifier", &Lua_Zone::SetAAEXPModifier) .def("SetAAEXPModifierByCharacterID", &Lua_Zone::SetAAEXPModifierByCharacterID) .def("SetBucket", (void(Lua_Zone::*)(const std::string&,const std::string&))&Lua_Zone::SetBucket) @@ -898,8 +971,12 @@ luabind::scope lua_register_zone() { .def("SetInstanceTimer", &Lua_Zone::SetInstanceTimer) .def("SetInstanceTimeRemaining", &Lua_Zone::SetInstanceTimeRemaining) .def("SetIsHotzone", &Lua_Zone::SetIsHotzone) + .def("SetTimer", &Lua_Zone::SetTimer) .def("SetVariable", &Lua_Zone::SetVariable) .def("ShowZoneGlobalLoot", &Lua_Zone::ShowZoneGlobalLoot) + .def("Signal", &Lua_Zone::Signal) + .def("StopTimer", &Lua_Zone::StopTimer) + .def("StopAllTimers", &Lua_Zone::StopAllTimers) .def("VariableExists", &Lua_Zone::VariableExists); } diff --git a/zone/lua_zone.h b/zone/lua_zone.h index 48d297bb6..b1a5390c2 100644 --- a/zone/lua_zone.h +++ b/zone/lua_zone.h @@ -147,6 +147,17 @@ public: luabind::object GetVariables(lua_State* L); void SetVariable(const std::string& variable_name, const std::string& variable_value); bool VariableExists(const std::string& variable_name); + uint32 GetTimerDuration(std::string name); + uint32 GetTimerRemainingTime(std::string name); + bool HasTimer(std::string name); + bool IsPausedTimer(std::string name); + void PauseTimer(std::string name); + void ResumeTimer(std::string name); + void SetTimer(std::string name, uint32 duration); + void StopTimer(std::string name); + void StopAllTimers(); + void Signal(int signal_id); + void SendPayload(int payload_id, std::string payload_value); // data buckets void SetBucket(const std::string& bucket_name, const std::string& bucket_value); diff --git a/zone/npc.cpp b/zone/npc.cpp index ade7c8e93..1c70da2c4 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -864,6 +864,11 @@ void NPC::Depop(bool start_spawn_timer) { DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr); } + if (parse->ZoneHasQuestSub(EVENT_DESPAWN_ZONE)) { + std::vector args = { this }; + parse->EventZone(EVENT_DESPAWN_ZONE, zone, "", 0, &args); + } + p_depop = true; if (respawn2) { if (start_spawn_timer) { diff --git a/zone/object.cpp b/zone/object.cpp index eb6daad49..6da171b23 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -657,6 +657,30 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) } } + if (parse->ZoneHasQuestSub(EVENT_PLAYER_PICKUP)) { + std::vector args = { m_inst, sender }; + + if (parse->EventZone(EVENT_PLAYER_PICKUP, zone, std::to_string(item->ID), GetID(), &args)) { + auto outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct)); + + memcpy(outapp->pBuffer, click_object, sizeof(ClickObject_Struct)); + + auto co = (ClickObject_Struct*) outapp->pBuffer; + + co->drop_id = 0; + + entity_list.QueueClients(nullptr, outapp, false); + + safe_delete(outapp); + + sender->SetTradeskillObject(nullptr); + + user = nullptr; + + return true; + } + } + // Transfer item to client sender->PutItemInInventory(EQ::invslot::slotCursor, *m_inst, false); sender->SendItemPacket(EQ::invslot::slotCursor, m_inst, ItemPacketTrade); diff --git a/zone/perl_zone.cpp b/zone/perl_zone.cpp index 26696a9a5..7783c6020 100644 --- a/zone/perl_zone.cpp +++ b/zone/perl_zone.cpp @@ -643,6 +643,16 @@ void Perl_Zone_StopAllTimers(Zone* self) self->StopAllTimers(); } +void Perl_Zone_SendPayload(Zone* self, int payload_id, std::string payload_value) +{ + self->SendPayload(payload_id, payload_value); +} + +void Perl_Zone_Signal(Zone* self, int signal_id) +{ + self->Signal(signal_id); +} + void perl_register_zone() { perl::interpreter perl(PERL_GET_THX); @@ -768,6 +778,7 @@ void perl_register_zone() package.add("Repop", (void(*)(Zone*))&Perl_Zone_Repop); package.add("Repop", (void(*)(Zone*, bool))&Perl_Zone_Repop); package.add("ResumeTimer", &Perl_Zone_ResumeTimer); + package.add("SendPayload", &Perl_Zone_SendPayload); package.add("SetAAEXPModifier", &Perl_Zone_SetAAEXPModifier); package.add("SetAAEXPModifierByCharacterID", &Perl_Zone_SetAAEXPModifierByCharacterID); package.add("SetBucket", (void(*)(Zone*, const std::string, const std::string))&Perl_Zone_SetBucket); @@ -779,6 +790,7 @@ void perl_register_zone() package.add("SetIsHotzone", &Perl_Zone_SetIsHotzone); package.add("SetTimer", &Perl_Zone_SetTimer); package.add("SetVariable", &Perl_Zone_SetVariable); + package.add("Signal", &Perl_Zone_Signal); package.add("StopTimer", &Perl_Zone_StopTimer); package.add("StopAllTimers", &Perl_Zone_StopAllTimers); package.add("ShowZoneGlobalLoot", &Perl_Zone_ShowZoneGlobalLoot); diff --git a/zone/zone.cpp b/zone/zone.cpp index ade8b7fb4..b3654fa0c 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1703,6 +1703,15 @@ bool Zone::Process() { } } + if (!m_zone_signals.empty()) { + int signal_id = m_zone_signals.front(); + m_zone_signals.pop_front(); + + if (parse->ZoneHasQuestSub(EVENT_SIGNAL)) { + parse->EventZone(EVENT_SIGNAL, this, std::to_string(signal_id), 0); + } + } + mMovementManager->Process(); return true; @@ -3520,4 +3529,18 @@ void Zone::StopAllTimers() } } +void Zone::Signal(int signal_id) +{ + m_zone_signals.push_back(signal_id); +} + +void Zone::SendPayload(int payload_id, std::string payload_value) +{ + if (parse->ZoneHasQuestSub(EVENT_PAYLOAD)) { + const auto& export_string = fmt::format("{} {}", payload_id, payload_value); + + parse->EventZone(EVENT_PAYLOAD, this, export_string, 0); + } +} + #include "zone_loot.cpp" diff --git a/zone/zone.h b/zone/zone.h index 693d96359..60c291abf 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -486,6 +486,9 @@ public: static void ClearZoneState(uint32 zone_id, uint32 instance_id); void ReloadMaps(); + void Signal(int signal_id); + void SendPayload(int payload_id, std::string payload_value); + struct PausedZoneTimer { std::string name; uint32 remaining_time; @@ -578,6 +581,7 @@ private: std::vector zone_timers; std::vector paused_zone_timers; + std::deque m_zone_signals; }; #endif