From 24cbf0af8a0b070a6c2a8931fca72dd4f4df9bf3 Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Wed, 18 Mar 2026 23:56:46 +0100 Subject: [PATCH 01/12] Multistate shoehorn --- conf/mod_ale.conf.dist | 10 + src/ALE_SC.cpp | 343 ++++++++++++---------- src/LuaEngine/ALEConfig.cpp | 1 + src/LuaEngine/ALEConfig.h | 2 + src/LuaEngine/ALECreatureAI.h | 4 +- src/LuaEngine/ALEEventMgr.cpp | 4 +- src/LuaEngine/ALEInstanceAI.cpp | 7 + src/LuaEngine/ALEInstanceAI.h | 14 +- src/LuaEngine/ALETemplate.h | 4 +- src/LuaEngine/HttpManager.cpp | 12 +- src/LuaEngine/HttpManager.h | 8 +- src/LuaEngine/LuaEngine.cpp | 75 ++++- src/LuaEngine/LuaEngine.h | 55 +++- src/LuaEngine/hooks/AllCreatureHooks.cpp | 4 +- src/LuaEngine/hooks/BattleGroundHooks.cpp | 2 +- src/LuaEngine/hooks/CreatureHooks.cpp | 4 +- src/LuaEngine/hooks/GameObjectHooks.cpp | 4 +- src/LuaEngine/hooks/GossipHooks.cpp | 4 +- src/LuaEngine/hooks/InstanceHooks.cpp | 4 +- src/LuaEngine/hooks/ItemHooks.cpp | 4 +- src/LuaEngine/hooks/PlayerHooks.cpp | 162 +++++----- src/LuaEngine/hooks/ServerHooks.cpp | 84 ++++-- src/LuaEngine/hooks/SpellHooks.cpp | 4 +- src/LuaEngine/hooks/VehicleHooks.cpp | 2 +- src/LuaEngine/methods/GlobalMethods.h | 30 +- 25 files changed, 539 insertions(+), 308 deletions(-) diff --git a/conf/mod_ale.conf.dist b/conf/mod_ale.conf.dist index 3eca4cc50d..6a45a537eb 100644 --- a/conf/mod_ale.conf.dist +++ b/conf/mod_ale.conf.dist @@ -59,6 +59,15 @@ # Cache is cleared only when files are modified or server restarts. # Default: true - (enabled) # false - (disabled) +# +# ALE.Multistate +# Description: Enable or disable per-map Lua state isolation. +# When enabled, each map runs its own Lua state concurrently on its map thread, +# allowing true parallel execution across maps. Scripts can use GetStateMapId() +# to self-select which map state they load into. +# When disabled, all maps share the global Lua state (original behavior). +# Default: false - (disabled, single global state) +# true - (enabled, per-map states) ALE.Enabled = true ALE.TraceBack = false @@ -69,6 +78,7 @@ ALE.RequireCPaths = "" ALE.AutoReload = false ALE.AutoReloadInterval = 1 ALE.BytecodeCache = true +ALE.Multistate = false ################################################################################################### # LOGGING SYSTEM SETTINGS diff --git a/src/ALE_SC.cpp b/src/ALE_SC.cpp index 60fe1013c3..57a4e7474d 100644 --- a/src/ALE_SC.cpp +++ b/src/ALE_SC.cpp @@ -21,6 +21,7 @@ #include "LuaEngine.h" #include "Pet.h" #include "Player.h" +#include "Vehicle.h" #include "ScriptMgr.h" #include "ScriptedGossip.h" @@ -32,7 +33,7 @@ class ALE_AllCreatureScript : public AllCreatureScript // Creature bool CanCreatureGossipHello(Player* player, Creature* creature) override { - if (sALE->OnGossipHello(player, creature)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId())->OnGossipHello(player, creature)) return true; return false; @@ -40,7 +41,7 @@ class ALE_AllCreatureScript : public AllCreatureScript bool CanCreatureGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) override { - if (sALE->OnGossipSelect(player, creature, sender, action)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId())->OnGossipSelect(player, creature, sender, action)) return true; return false; @@ -48,7 +49,7 @@ class ALE_AllCreatureScript : public AllCreatureScript bool CanCreatureGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code) override { - if (sALE->OnGossipSelectCode(player, creature, sender, action, code)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId())->OnGossipSelectCode(player, creature, sender, action, code)) return true; return false; @@ -56,6 +57,7 @@ class ALE_AllCreatureScript : public AllCreatureScript void OnCreatureAddWorld(Creature* creature) override { + ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId()); sALE->OnAddToWorld(creature); sALE->OnAllCreatureAddToWorld(creature); @@ -65,12 +67,14 @@ class ALE_AllCreatureScript : public AllCreatureScript void OnCreatureRemoveWorld(Creature* creature) override { + ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId()); sALE->OnRemoveFromWorld(creature); sALE->OnAllCreatureRemoveFromWorld(creature); } bool CanCreatureQuestAccept(Player* player, Creature* creature, Quest const* quest) override { + ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId()); sALE->OnPlayerQuestAccept(player, quest); sALE->OnQuestAccept(player, creature, quest); return false; @@ -78,7 +82,7 @@ class ALE_AllCreatureScript : public AllCreatureScript bool CanCreatureQuestReward(Player* player, Creature* creature, Quest const* quest, uint32 opt) override { - if (sALE->OnQuestReward(player, creature, quest, opt)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId())->OnQuestReward(player, creature, quest, opt)) { ClearGossipMenuFor(player); return true; @@ -89,7 +93,7 @@ class ALE_AllCreatureScript : public AllCreatureScript CreatureAI* GetCreatureAI(Creature* creature) const override { - if (CreatureAI* luaAI = sALE->GetAI(creature)) + if (CreatureAI* luaAI = ALE::GetMapStateOrGlobal(creature->GetMapId())->GetAI(creature)) return luaAI; return nullptr; @@ -97,12 +101,12 @@ class ALE_AllCreatureScript : public AllCreatureScript void OnCreatureSelectLevel(const CreatureTemplate* cinfo, Creature* creature) override { - sALE->OnAllCreatureSelectLevel(cinfo, creature); + ALE::GetMapStateOrGlobal(creature->GetMapId())->OnAllCreatureSelectLevel(cinfo, creature); } void OnBeforeCreatureSelectLevel(const CreatureTemplate* cinfo, Creature* creature, uint8& level) override { - sALE->OnAllCreatureBeforeSelectLevel(cinfo, creature, level); + ALE::GetMapStateOrGlobal(creature->GetMapId())->OnAllCreatureBeforeSelectLevel(cinfo, creature, level); } }; @@ -113,21 +117,22 @@ class ALE_AllGameObjectScript : public AllGameObjectScript void OnGameObjectAddWorld(GameObject* go) override { - sALE->OnAddToWorld(go); + ALE::GetMapStateOrGlobal(go->GetMapId())->OnAddToWorld(go); } void OnGameObjectRemoveWorld(GameObject* go) override { - sALE->OnRemoveFromWorld(go); + ALE::GetMapStateOrGlobal(go->GetMapId())->OnRemoveFromWorld(go); } void OnGameObjectUpdate(GameObject* go, uint32 diff) override { - sALE->UpdateAI(go, diff); + ALE::GetMapStateOrGlobal(go->GetMapId())->UpdateAI(go, diff); } bool CanGameObjectGossipHello(Player* player, GameObject* go) override { + ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId()); if (sALE->OnGossipHello(player, go)) return true; @@ -139,26 +144,27 @@ class ALE_AllGameObjectScript : public AllGameObjectScript void OnGameObjectDamaged(GameObject* go, Player* player) override { - sALE->OnDamaged(go, player); + ALE::GetMapStateOrGlobal(go->GetMapId())->OnDamaged(go, player); } void OnGameObjectDestroyed(GameObject* go, Player* player) override { - sALE->OnDestroyed(go, player); + ALE::GetMapStateOrGlobal(go->GetMapId())->OnDestroyed(go, player); } void OnGameObjectLootStateChanged(GameObject* go, uint32 state, Unit* /*unit*/) override { - sALE->OnLootStateChanged(go, state); + ALE::GetMapStateOrGlobal(go->GetMapId())->OnLootStateChanged(go, state); } void OnGameObjectStateChanged(GameObject* go, uint32 state) override { - sALE->OnGameObjectStateChanged(go, state); + ALE::GetMapStateOrGlobal(go->GetMapId())->OnGameObjectStateChanged(go, state); } bool CanGameObjectQuestAccept(Player* player, GameObject* go, Quest const* quest) override { + ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId()); sALE->OnPlayerQuestAccept(player, quest); sALE->OnQuestAccept(player, go, quest); return false; @@ -166,7 +172,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript bool CanGameObjectGossipSelect(Player* player, GameObject* go, uint32 sender, uint32 action) override { - if (sALE->OnGossipSelect(player, go, sender, action)) + if (ALE::GetMapStateOrGlobal(go->GetMapId())->OnGossipSelect(player, go, sender, action)) return true; return false; @@ -174,7 +180,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript bool CanGameObjectGossipSelectCode(Player* player, GameObject* go, uint32 sender, uint32 action, const char* code) override { - if (sALE->OnGossipSelectCode(player, go, sender, action, code)) + if (ALE::GetMapStateOrGlobal(go->GetMapId())->OnGossipSelectCode(player, go, sender, action, code)) return true; return false; @@ -182,6 +188,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript bool CanGameObjectQuestReward(Player* player, GameObject* go, Quest const* quest, uint32 opt) override { + ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId()); if (sALE->OnQuestAccept(player, go, quest)) { sALE->OnPlayerQuestAccept(player, quest); @@ -196,7 +203,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript GameObjectAI* GetGameObjectAI(GameObject* go) const override { - sALE->OnSpawn(go); + ALE::GetMapStateOrGlobal(go->GetMapId())->OnSpawn(go); return nullptr; } }; @@ -208,6 +215,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemQuestAccept(Player* player, Item* item, Quest const* quest) override { + ALE* sALE = ALE::GetMapStateOrGlobal(player->GetMapId()); if (sALE->OnQuestAccept(player, item, quest)) { sALE->OnPlayerQuestAccept(player, quest); @@ -219,7 +227,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemUse(Player* player, Item* item, SpellCastTargets const& targets) override { - if (!sALE->OnUse(player, item, targets)) + if (!ALE::GetMapStateOrGlobal(player->GetMapId())->OnUse(player, item, targets)) return true; return false; @@ -227,7 +235,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemExpire(Player* player, ItemTemplate const* proto) override { - if (sALE->OnExpire(player, proto)) + if (ALE::GetMapStateOrGlobal(player->GetMapId())->OnExpire(player, proto)) return false; return true; @@ -235,7 +243,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemRemove(Player* player, Item* item) override { - if (sALE->OnRemove(player, item)) + if (ALE::GetMapStateOrGlobal(player->GetMapId())->OnRemove(player, item)) return false; return true; @@ -243,12 +251,12 @@ class ALE_AllItemScript : public AllItemScript void OnItemGossipSelect(Player* player, Item* item, uint32 sender, uint32 action) override { - sALE->HandleGossipSelectOption(player, item, sender, action, ""); + ALE::GetMapStateOrGlobal(player->GetMapId())->HandleGossipSelectOption(player, item, sender, action, ""); } void OnItemGossipSelectCode(Player* player, Item* item, uint32 sender, uint32 action, const char* code) override { - sALE->HandleGossipSelectOption(player, item, sender, action, code); + ALE::GetMapStateOrGlobal(player->GetMapId())->HandleGossipSelectOption(player, item, sender, action, code); } }; @@ -268,37 +276,44 @@ class ALE_AllMapScript : public AllMapScript void OnBeforeCreateInstanceScript(InstanceMap* instanceMap, InstanceScript** instanceData, bool /*load*/, std::string /*data*/, uint32 /*completedEncounterMask*/) override { if (instanceData) - *instanceData = sALE->GetInstanceData(instanceMap); + *instanceData = ALE::GetMapStateOrGlobal(instanceMap->GetId())->GetInstanceData(instanceMap); } void OnDestroyInstance(MapInstanced* /*mapInstanced*/, Map* map) override { - sALE->FreeInstanceId(map->GetInstanceId()); + ALE::GetMapStateOrGlobal(map->GetId())->FreeInstanceId(map->GetInstanceId()); } void OnCreateMap(Map* map) override { - sALE->OnCreate(map); + if (ALEConfig::GetInstance().IsMultistateEnabled()) + { + if (!ALE::GetMapState(map->GetId())) + ALE::CreateMapState(map->GetId()); + } + ALE::GetMapStateOrGlobal(map->GetId())->OnCreate(map); } void OnDestroyMap(Map* map) override { - sALE->OnDestroy(map); + ALE::GetMapStateOrGlobal(map->GetId())->OnDestroy(map); + if (ALEConfig::GetInstance().IsMultistateEnabled() && !map->Instanceable()) + ALE::DestroyMapState(map->GetId()); } void OnPlayerEnterAll(Map* map, Player* player) override { - sALE->OnPlayerEnter(map, player); + ALE::GetMapStateOrGlobal(map->GetId())->OnPlayerEnter(map, player); } void OnPlayerLeaveAll(Map* map, Player* player) override { - sALE->OnPlayerLeave(map, player); + ALE::GetMapStateOrGlobal(map->GetId())->OnPlayerLeave(map, player); } void OnMapUpdate(Map* map, uint32 diff) override { - sALE->OnUpdate(map, diff); + ALE::GetMapStateOrGlobal(map->GetId())->OnUpdate(map, diff); } }; @@ -314,22 +329,22 @@ class ALE_AuctionHouseScript : public AuctionHouseScript void OnAuctionAdd(AuctionHouseObject* ah, AuctionEntry* entry) override { - sALE->OnAdd(ah, entry); + gALE->OnAdd(ah, entry); } void OnAuctionRemove(AuctionHouseObject* ah, AuctionEntry* entry) override { - sALE->OnRemove(ah, entry); + gALE->OnRemove(ah, entry); } void OnAuctionSuccessful(AuctionHouseObject* ah, AuctionEntry* entry) override { - sALE->OnSuccessful(ah, entry); + gALE->OnSuccessful(ah, entry); } void OnAuctionExpire(AuctionHouseObject* ah, AuctionEntry* entry) override { - sALE->OnExpire(ah, entry); + gALE->OnExpire(ah, entry); } }; @@ -345,22 +360,22 @@ class ALE_BGScript : public BGScript void OnBattlegroundStart(Battleground* bg) override { - sALE->OnBGStart(bg, bg->GetBgTypeID(), bg->GetInstanceID()); + ALE::GetMapStateOrGlobal(bg->GetMapId())->OnBGStart(bg, bg->GetBgTypeID(), bg->GetInstanceID()); } void OnBattlegroundEnd(Battleground* bg, TeamId winnerTeam) override { - sALE->OnBGEnd(bg, bg->GetBgTypeID(), bg->GetInstanceID(), winnerTeam); + ALE::GetMapStateOrGlobal(bg->GetMapId())->OnBGEnd(bg, bg->GetBgTypeID(), bg->GetInstanceID(), winnerTeam); } void OnBattlegroundDestroy(Battleground* bg) override { - sALE->OnBGDestroy(bg, bg->GetBgTypeID(), bg->GetInstanceID()); + ALE::GetMapStateOrGlobal(bg->GetMapId())->OnBGDestroy(bg, bg->GetBgTypeID(), bg->GetInstanceID()); } void OnBattlegroundCreate(Battleground* bg) override { - sALE->OnBGCreate(bg, bg->GetBgTypeID(), bg->GetInstanceID()); + ALE::GetMapStateOrGlobal(bg->GetMapId())->OnBGCreate(bg, bg->GetBgTypeID(), bg->GetInstanceID()); } }; @@ -373,7 +388,7 @@ class ALE_CommandSC : public CommandSC bool OnTryExecuteCommand(ChatHandler& handler, std::string_view cmdStr) override { - if (!sALE->OnCommand(handler, std::string(cmdStr).c_str())) + if (!gALE->OnCommand(handler, std::string(cmdStr).c_str())) { return false; } @@ -390,13 +405,13 @@ class ALE_ALEScript : public ALEScript // Weather void OnWeatherChange(Weather* weather, WeatherState state, float grade) override { - sALE->OnChange(weather, weather->GetZone(), state, grade); + gALE->OnChange(weather, weather->GetZone(), state, grade); } // AreaTriger bool CanAreaTrigger(Player* player, AreaTrigger const* trigger) override { - if (sALE->OnAreaTrigger(player, trigger)) + if (ALE::GetMapStateOrGlobal(player->GetMapId())->OnAreaTrigger(player, trigger)) return true; return false; @@ -413,12 +428,12 @@ class ALE_GameEventScript : public GameEventScript void OnStart(uint16 eventID) override { - sALE->OnGameEventStart(eventID); + gALE->OnGameEventStart(eventID); } void OnStop(uint16 eventID) override { - sALE->OnGameEventStop(eventID); + gALE->OnGameEventStop(eventID); } }; @@ -436,32 +451,32 @@ class ALE_GroupScript : public GroupScript void OnAddMember(Group* group, ObjectGuid guid) override { - sALE->OnAddMember(group, guid); + gALE->OnAddMember(group, guid); } void OnInviteMember(Group* group, ObjectGuid guid) override { - sALE->OnInviteMember(group, guid); + gALE->OnInviteMember(group, guid); } void OnRemoveMember(Group* group, ObjectGuid guid, RemoveMethod method, ObjectGuid /* kicker */, const char* /* reason */) override { - sALE->OnRemoveMember(group, guid, method); + gALE->OnRemoveMember(group, guid, method); } void OnChangeLeader(Group* group, ObjectGuid newLeaderGuid, ObjectGuid oldLeaderGuid) override { - sALE->OnChangeLeader(group, newLeaderGuid, oldLeaderGuid); + gALE->OnChangeLeader(group, newLeaderGuid, oldLeaderGuid); } void OnDisband(Group* group) override { - sALE->OnDisband(group); + gALE->OnDisband(group); } void OnCreate(Group* group, Player* leader) override { - sALE->OnCreate(group, leader->GetGUID(), group->GetGroupType()); + gALE->OnCreate(group, leader->GetGUID(), group->GetGroupType()); } }; @@ -484,58 +499,58 @@ class ALE_GuildScript : public GuildScript void OnAddMember(Guild* guild, Player* player, uint8& plRank) override { - sALE->OnAddMember(guild, player, plRank); + gALE->OnAddMember(guild, player, plRank); } void OnRemoveMember(Guild* guild, Player* player, bool isDisbanding, bool /*isKicked*/) override { - sALE->OnRemoveMember(guild, player, isDisbanding); + gALE->OnRemoveMember(guild, player, isDisbanding); } void OnMOTDChanged(Guild* guild, const std::string& newMotd) override { - sALE->OnMOTDChanged(guild, newMotd); + gALE->OnMOTDChanged(guild, newMotd); } void OnInfoChanged(Guild* guild, const std::string& newInfo) override { - sALE->OnInfoChanged(guild, newInfo); + gALE->OnInfoChanged(guild, newInfo); } void OnCreate(Guild* guild, Player* leader, const std::string& name) override { - sALE->OnCreate(guild, leader, name); + gALE->OnCreate(guild, leader, name); } void OnDisband(Guild* guild) override { - sALE->OnDisband(guild); + gALE->OnDisband(guild); } void OnMemberWitdrawMoney(Guild* guild, Player* player, uint32& amount, bool isRepair) override { - sALE->OnMemberWitdrawMoney(guild, player, amount, isRepair); + gALE->OnMemberWitdrawMoney(guild, player, amount, isRepair); } void OnMemberDepositMoney(Guild* guild, Player* player, uint32& amount) override { - sALE->OnMemberDepositMoney(guild, player, amount); + gALE->OnMemberDepositMoney(guild, player, amount); } void OnItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId, bool isDestBank, uint8 destContainer, uint8 destSlotId) override { - sALE->OnItemMove(guild, player, pItem, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId); + gALE->OnItemMove(guild, player, pItem, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId); } void OnEvent(Guild* guild, uint8 eventType, ObjectGuid::LowType playerGuid1, ObjectGuid::LowType playerGuid2, uint8 newRank) override { - sALE->OnEvent(guild, eventType, playerGuid1, playerGuid2, newRank); + gALE->OnEvent(guild, eventType, playerGuid1, playerGuid2, newRank); } void OnBankEvent(Guild* guild, uint8 eventType, uint8 tabId, ObjectGuid::LowType playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) override { - sALE->OnBankEvent(guild, eventType, tabId, playerGuid, itemOrMoney, itemStackCount, destTabId); + gALE->OnBankEvent(guild, eventType, tabId, playerGuid, itemOrMoney, itemStackCount, destTabId); } }; @@ -548,7 +563,7 @@ class ALE_LootScript : public LootScript void OnLootMoney(Player* player, uint32 gold) override { - sALE->OnLootMoney(player, gold); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnLootMoney(player, gold); } }; @@ -561,6 +576,7 @@ class ALE_MiscScript : public MiscScript void GetDialogStatus(Player* player, Object* questgiver) override { + ALE* sALE = ALE::GetMapStateOrGlobal(player->GetMapId()); if (questgiver->GetTypeId() == TYPEID_GAMEOBJECT) sALE->GetDialogStatus(player, questgiver->ToGameObject()); else if (questgiver->GetTypeId() == TYPEID_UNIT) @@ -577,7 +593,7 @@ class ALE_PetScript : public PetScript void OnPetAddToWorld(Pet* pet) override { - sALE->OnPetAddedToWorld(pet->GetOwner(), pet); + ALE::GetMapStateOrGlobal(pet->GetMapId())->OnPetAddedToWorld(pet->GetOwner(), pet); } }; @@ -649,7 +665,7 @@ class ALE_PlayerScript : public PlayerScript void OnPlayerResurrect(Player* player, float /*restore_percent*/, bool /*applySickness*/) override { - sALE->OnResurrect(player); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnResurrect(player); } bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg) override @@ -657,7 +673,7 @@ class ALE_PlayerScript : public PlayerScript if (type != CHAT_MSG_SAY && type != CHAT_MSG_YELL && type != CHAT_MSG_EMOTE) return true; - if (!sALE->OnChat(player, type, lang, msg)) + if (!gALE->OnChat(player, type, lang, msg)) return false; return true; @@ -665,7 +681,7 @@ class ALE_PlayerScript : public PlayerScript bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg, Player* target) override { - if (!sALE->OnChat(player, type, lang, msg, target)) + if (!gALE->OnChat(player, type, lang, msg, target)) return false; return true; @@ -673,7 +689,7 @@ class ALE_PlayerScript : public PlayerScript bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg, Group* group) override { - if (!sALE->OnChat(player, type, lang, msg, group)) + if (!gALE->OnChat(player, type, lang, msg, group)) return false; return true; @@ -681,7 +697,7 @@ class ALE_PlayerScript : public PlayerScript bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg, Guild* guild) override { - if (!sALE->OnChat(player, type, lang, msg, guild)) + if (!gALE->OnChat(player, type, lang, msg, guild)) return false; return true; @@ -689,7 +705,7 @@ class ALE_PlayerScript : public PlayerScript bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg, Channel* channel) override { - if (!sALE->OnChat(player, type, lang, msg, channel)) + if (!gALE->OnChat(player, type, lang, msg, channel)) return false; return true; @@ -697,274 +713,274 @@ class ALE_PlayerScript : public PlayerScript void OnPlayerLootItem(Player* player, Item* item, uint32 count, ObjectGuid lootguid) override { - sALE->OnLootItem(player, item, count, lootguid); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnLootItem(player, item, count, lootguid); } void OnPlayerLearnTalents(Player* player, uint32 talentId, uint32 talentRank, uint32 spellid) override { - sALE->OnLearnTalents(player, talentId, talentRank, spellid); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnLearnTalents(player, talentId, talentRank, spellid); } bool OnPlayerCanUseItem(Player* player, ItemTemplate const* proto, InventoryResult& result) override { - result = sALE->OnCanUseItem(player, proto->ItemId); + result = ALE::GetMapStateOrGlobal(player->GetMapId())->OnCanUseItem(player, proto->ItemId); return result != EQUIP_ERR_OK ? false : true; } void OnPlayerEquip(Player* player, Item* it, uint8 bag, uint8 slot, bool /*update*/) override { - sALE->OnEquip(player, it, bag, slot); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnEquip(player, it, bag, slot); } void OnPlayerEnterCombat(Player* player, Unit* enemy) override { - sALE->OnPlayerEnterCombat(player, enemy); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerEnterCombat(player, enemy); } void OnPlayerLeaveCombat(Player* player) override { - sALE->OnPlayerLeaveCombat(player); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerLeaveCombat(player); } bool OnPlayerCanRepopAtGraveyard(Player* player) override { - sALE->OnRepop(player); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnRepop(player); return true; } void OnPlayerQuestAbandon(Player* player, uint32 questId) override { - sALE->OnQuestAbandon(player, questId); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnQuestAbandon(player, questId); } void OnPlayerMapChanged(Player* player) override { - sALE->OnMapChanged(player); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnMapChanged(player); } void OnPlayerGossipSelect(Player* player, uint32 menu_id, uint32 sender, uint32 action) override { - sALE->HandleGossipSelectOption(player, menu_id, sender, action, ""); + ALE::GetMapStateOrGlobal(player->GetMapId())->HandleGossipSelectOption(player, menu_id, sender, action, ""); } void OnPlayerGossipSelectCode(Player* player, uint32 menu_id, uint32 sender, uint32 action, const char* code) override { - sALE->HandleGossipSelectOption(player, menu_id, sender, action, code); + ALE::GetMapStateOrGlobal(player->GetMapId())->HandleGossipSelectOption(player, menu_id, sender, action, code); } void OnPlayerPVPKill(Player* killer, Player* killed) override { - sALE->OnPVPKill(killer, killed); + ALE::GetMapStateOrGlobal(killer->GetMapId())->OnPVPKill(killer, killed); } void OnPlayerCreatureKill(Player* killer, Creature* killed) override { - sALE->OnCreatureKill(killer, killed); + ALE::GetMapStateOrGlobal(killer->GetMapId())->OnCreatureKill(killer, killed); } void OnPlayerKilledByCreature(Creature* killer, Player* killed) override { - sALE->OnPlayerKilledByCreature(killer, killed); + ALE::GetMapStateOrGlobal(killer->GetMapId())->OnPlayerKilledByCreature(killer, killed); } void OnPlayerLevelChanged(Player* player, uint8 oldLevel) override { - sALE->OnLevelChanged(player, oldLevel); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnLevelChanged(player, oldLevel); } void OnPlayerFreeTalentPointsChanged(Player* player, uint32 points) override { - sALE->OnFreeTalentPointsChanged(player, points); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnFreeTalentPointsChanged(player, points); } void OnPlayerTalentsReset(Player* player, bool noCost) override { - sALE->OnTalentsReset(player, noCost); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnTalentsReset(player, noCost); } void OnPlayerMoneyChanged(Player* player, int32& amount) override { - sALE->OnMoneyChanged(player, amount); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnMoneyChanged(player, amount); } void OnPlayerGiveXP(Player* player, uint32& amount, Unit* victim, uint8 xpSource) override { - sALE->OnGiveXP(player, amount, victim, xpSource); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnGiveXP(player, amount, victim, xpSource); } bool OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental) override { - return sALE->OnReputationChange(player, factionID, standing, incremental); + return ALE::GetMapStateOrGlobal(player->GetMapId())->OnReputationChange(player, factionID, standing, incremental); } void OnPlayerDuelRequest(Player* target, Player* challenger) override { - sALE->OnDuelRequest(target, challenger); + ALE::GetMapStateOrGlobal(challenger->GetMapId())->OnDuelRequest(target, challenger); } void OnPlayerDuelStart(Player* player1, Player* player2) override { - sALE->OnDuelStart(player1, player2); + ALE::GetMapStateOrGlobal(player1->GetMapId())->OnDuelStart(player1, player2); } void OnPlayerDuelEnd(Player* winner, Player* loser, DuelCompleteType type) override { - sALE->OnDuelEnd(winner, loser, type); + ALE::GetMapStateOrGlobal(winner->GetMapId())->OnDuelEnd(winner, loser, type); } void OnPlayerEmote(Player* player, uint32 emote) override { - sALE->OnEmote(player, emote); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnEmote(player, emote); } void OnPlayerTextEmote(Player* player, uint32 textEmote, uint32 emoteNum, ObjectGuid guid) override { - sALE->OnTextEmote(player, textEmote, emoteNum, guid); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnTextEmote(player, textEmote, emoteNum, guid); } void OnPlayerSpellCast(Player* player, Spell* spell, bool skipCheck) override { - sALE->OnPlayerSpellCast(player, spell, skipCheck); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerSpellCast(player, spell, skipCheck); } void OnPlayerLogin(Player* player) override { - sALE->OnLogin(player); + gALE->OnLogin(player); } void OnPlayerLogout(Player* player) override { - sALE->OnLogout(player); + gALE->OnLogout(player); } void OnPlayerCreate(Player* player) override { - sALE->OnCreate(player); + gALE->OnCreate(player); } void OnPlayerSave(Player* player) override { - sALE->OnSave(player); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnSave(player); } void OnPlayerDelete(ObjectGuid guid, uint32 /*accountId*/) override { - sALE->OnDelete(guid.GetCounter()); + gALE->OnDelete(guid.GetCounter()); } void OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent) override { - sALE->OnBindToInstance(player, difficulty, mapid, permanent); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnBindToInstance(player, difficulty, mapid, permanent); } void OnPlayerUpdateArea(Player* player, uint32 oldArea, uint32 newArea) override { - sALE->OnUpdateArea(player, oldArea, newArea); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnUpdateArea(player, oldArea, newArea); } void OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea) override { - sALE->OnUpdateZone(player, newZone, newArea); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnUpdateZone(player, newZone, newArea); } void OnPlayerFirstLogin(Player* player) override { - sALE->OnFirstLogin(player); + gALE->OnFirstLogin(player); } void OnPlayerLearnSpell(Player* player, uint32 spellId) override { - sALE->OnLearnSpell(player, spellId); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnLearnSpell(player, spellId); } void OnPlayerAchievementComplete(Player* player, AchievementEntry const* achievement) override { - sALE->OnAchiComplete(player, achievement); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnAchiComplete(player, achievement); } void OnPlayerFfaPvpStateUpdate(Player* player, bool IsFlaggedForFfaPvp) override { - sALE->OnFfaPvpStateUpdate(player, IsFlaggedForFfaPvp); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnFfaPvpStateUpdate(player, IsFlaggedForFfaPvp); } bool OnPlayerCanInitTrade(Player* player, Player* target) override { - return sALE->OnCanInitTrade(player, target); + return ALE::GetMapStateOrGlobal(player->GetMapId())->OnCanInitTrade(player, target); } bool OnPlayerCanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 cod, Item* item) override { - return sALE->OnCanSendMail(player, receiverGuid, mailbox, subject, body, money, cod, item); + return ALE::GetMapStateOrGlobal(player->GetMapId())->OnCanSendMail(player, receiverGuid, mailbox, subject, body, money, cod, item); } bool OnPlayerCanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment) override { - return sALE->OnCanJoinLfg(player, roles, dungeons, comment); + return ALE::GetMapStateOrGlobal(player->GetMapId())->OnCanJoinLfg(player, roles, dungeons, comment); } void OnPlayerQuestRewardItem(Player* player, Item* item, uint32 count) override { - sALE->OnQuestRewardItem(player, item, count); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnQuestRewardItem(player, item, count); } void OnPlayerGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll) override { - sALE->OnGroupRollRewardItem(player, item, count, voteType, roll); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnGroupRollRewardItem(player, item, count, voteType, roll); } void OnPlayerCreateItem(Player* player, Item* item, uint32 count) override { - sALE->OnCreateItem(player, item, count); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnCreateItem(player, item, count); } void OnPlayerStoreNewItem(Player* player, Item* item, uint32 count) override { - sALE->OnStoreNewItem(player, item, count); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnStoreNewItem(player, item, count); } void OnPlayerCompleteQuest(Player* player, Quest const* quest) override { - sALE->OnPlayerCompleteQuest(player, quest); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerCompleteQuest(player, quest); } bool OnPlayerCanGroupInvite(Player* player, std::string& memberName) override { - return sALE->OnCanGroupInvite(player, memberName); + return ALE::GetMapStateOrGlobal(player->GetMapId())->OnCanGroupInvite(player, memberName); } void OnPlayerBattlegroundDesertion(Player* player, const BattlegroundDesertionType type) override { - sALE->OnBattlegroundDesertion(player, type); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnBattlegroundDesertion(player, type); } void OnPlayerCreatureKilledByPet(Player* player, Creature* killed) override { - sALE->OnCreatureKilledByPet(player, killed); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnCreatureKilledByPet(player, killed); } bool OnPlayerCanUpdateSkill(Player* player, uint32 skill_id) override { - return sALE->OnPlayerCanUpdateSkill(player, skill_id); + return ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerCanUpdateSkill(player, skill_id); } void OnPlayerBeforeUpdateSkill(Player* player, uint32 skill_id, uint32& value, uint32 max, uint32 step) override { - sALE->OnPlayerBeforeUpdateSkill(player, skill_id, value, max, step); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerBeforeUpdateSkill(player, skill_id, value, max, step); } void OnPlayerUpdateSkill(Player* player, uint32 skill_id, uint32 value, uint32 max, uint32 step, uint32 new_value) override { - sALE->OnPlayerUpdateSkill(player, skill_id, value, max, step, new_value); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerUpdateSkill(player, skill_id, value, max, step, new_value); } bool OnPlayerCanResurrect(Player* player) override { - return sALE->CanPlayerResurrect(player); + return ALE::GetMapStateOrGlobal(player->GetMapId())->CanPlayerResurrect(player); } void OnPlayerReleasedGhost(Player* player) override { - sALE->OnPlayerReleasedGhost(player); + ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerReleasedGhost(player); } }; @@ -978,7 +994,7 @@ class ALE_ServerScript : public ServerScript bool CanPacketSend(WorldSession* session, WorldPacket const& packet) override { - if (!sALE->OnPacketSend(session, packet)) + if (!gALE->OnPacketSend(session, packet)) return false; return true; @@ -986,7 +1002,7 @@ class ALE_ServerScript : public ServerScript bool CanPacketReceive(WorldSession* session, WorldPacket const& packet) override { - if (!sALE->OnPacketReceive(session, packet)) + if (!gALE->OnPacketReceive(session, packet)) return false; return true; @@ -1007,32 +1023,32 @@ class ALE_SpellSC : public SpellSC void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, GameObject* gameObjTarget) override { - sALE->OnDummyEffect(caster, spellID, effIndex, gameObjTarget); + ALE::GetMapStateOrGlobal(caster->GetMapId())->OnDummyEffect(caster, spellID, effIndex, gameObjTarget); } void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Creature* creatureTarget) override { - sALE->OnDummyEffect(caster, spellID, effIndex, creatureTarget); + ALE::GetMapStateOrGlobal(caster->GetMapId())->OnDummyEffect(caster, spellID, effIndex, creatureTarget); } void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Item* itemTarget) override { - sALE->OnDummyEffect(caster, spellID, effIndex, itemTarget); + ALE::GetMapStateOrGlobal(caster->GetMapId())->OnDummyEffect(caster, spellID, effIndex, itemTarget); } void OnSpellCastCancel(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool bySelf) override { - sALE->OnSpellCastCancel(caster, spell, spellInfo, bySelf); + ALE::GetMapStateOrGlobal(caster->GetMapId())->OnSpellCastCancel(caster, spell, spellInfo, bySelf); } void OnSpellCast(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool skipCheck) override { - sALE->OnSpellCast(caster, spell, spellInfo, skipCheck); + ALE::GetMapStateOrGlobal(caster->GetMapId())->OnSpellCast(caster, spell, spellInfo, skipCheck); } void OnSpellPrepare(Spell* spell, Unit* caster, SpellInfo const* spellInfo) override { - sALE->OnSpellPrepare(caster, spell, spellInfo); + ALE::GetMapStateOrGlobal(caster->GetMapId())->OnSpellPrepare(caster, spell, spellInfo); } }; @@ -1043,27 +1059,27 @@ class ALE_VehicleScript : public VehicleScript void OnInstall(Vehicle* veh) override { - sALE->OnInstall(veh); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId())->OnInstall(veh); } void OnUninstall(Vehicle* veh) override { - sALE->OnUninstall(veh); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId())->OnUninstall(veh); } void OnInstallAccessory(Vehicle* veh, Creature* accessory) override { - sALE->OnInstallAccessory(veh, accessory); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId())->OnInstallAccessory(veh, accessory); } void OnAddPassenger(Vehicle* veh, Unit* passenger, int8 seatId) override { - sALE->OnAddPassenger(veh, passenger, seatId); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId())->OnAddPassenger(veh, passenger, seatId); } void OnRemovePassenger(Vehicle* veh, Unit* passenger) override { - sALE->OnRemovePassenger(veh, passenger); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId())->OnRemovePassenger(veh, passenger); } }; @@ -1079,8 +1095,11 @@ class ALE_WorldObjectScript : public WorldObjectScript void OnWorldObjectDestroy(WorldObject* object) override { - delete object->ALEEvents; - object->ALEEvents = nullptr; + if (object->ALEEvents) + { + delete object->ALEEvents; + object->ALEEvents = nullptr; + } } void OnWorldObjectCreate(WorldObject* object) override @@ -1088,10 +1107,20 @@ class ALE_WorldObjectScript : public WorldObjectScript object->ALEEvents = nullptr; } - void OnWorldObjectSetMap(WorldObject* object, Map* /*map*/) override + void OnWorldObjectSetMap(WorldObject* object, Map* map) override { if (!object->ALEEvents) - object->ALEEvents = new ALEEventProcessor(&ALE::GALE, object); + { + if (ALEConfig::GetInstance().IsMultistateEnabled()) + { + ALE** stateSlot = ALE::GetMapStateSlot(map->GetId()); + object->ALEEvents = new ALEEventProcessor(stateSlot, object); + } + else + { + object->ALEEvents = new ALEEventProcessor(&ALE::GALE, object); + } + } } void OnWorldObjectUpdate(WorldObject* object, uint32 diff) override @@ -1118,7 +1147,7 @@ class ALE_WorldScript : public WorldScript void OnOpenStateChange(bool open) override { - sALE->OnOpenStateChange(open); + gALE->OnOpenStateChange(open); } void OnBeforeConfigLoad(bool reload) override @@ -1131,37 +1160,37 @@ class ALE_WorldScript : public WorldScript ALE::Initialize(); } - sALE->OnConfigLoad(reload, true); + gALE->OnConfigLoad(reload, true); } void OnAfterConfigLoad(bool reload) override { - sALE->OnConfigLoad(reload, false); + gALE->OnConfigLoad(reload, false); } void OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask) override { - sALE->OnShutdownInitiate(code, mask); + gALE->OnShutdownInitiate(code, mask); } void OnShutdownCancel() override { - sALE->OnShutdownCancel(); + gALE->OnShutdownCancel(); } void OnUpdate(uint32 diff) override { - sALE->OnWorldUpdate(diff); + gALE->OnWorldUpdate(diff); } void OnStartup() override { - sALE->OnStartup(); + gALE->OnStartup(); } void OnShutdown() override { - sALE->OnShutdown(); + gALE->OnShutdown(); } void OnAfterUnloadAllMaps() override @@ -1173,8 +1202,9 @@ class ALE_WorldScript : public WorldScript { ///- Run ALE scripts. // in multithread foreach: run scripts - sALE->RunScripts(); - sALE->OnConfigLoad(false, false); // Must be done after ALE is initialized and scripts have run. + gALE->RunScripts(); + ALE::RunScriptsOnAllMapStates(); + gALE->OnConfigLoad(false, false); // Must be done after ALE is initialized and scripts have run. } }; @@ -1190,22 +1220,22 @@ class ALE_TicketScript : public TicketScript void OnTicketCreate(GmTicket* ticket) override { - sALE->OnTicketCreate(ticket); + gALE->OnTicketCreate(ticket); } void OnTicketUpdateLastChange(GmTicket* ticket) override { - sALE->OnTicketUpdateLastChange(ticket); + gALE->OnTicketUpdateLastChange(ticket); } void OnTicketClose(GmTicket* ticket) override { - sALE->OnTicketClose(ticket); + gALE->OnTicketClose(ticket); } void OnTicketResolve(GmTicket* ticket) override { - sALE->OnTicketResolve(ticket); + gALE->OnTicketResolve(ticket); } }; @@ -1217,6 +1247,7 @@ class ALE_UnitScript : public UnitScript void OnAuraApply(Unit* unit, Aura* aura) override { if (!unit || !aura) return; + ALE* sALE = ALE::GetMapStateOrGlobal(unit->GetMapId()); if (unit->IsPlayer()) sALE->OnPlayerAuraApply(unit->ToPlayer(), aura); @@ -1231,6 +1262,7 @@ class ALE_UnitScript : public UnitScript void OnAuraRemove(Unit* unit, AuraApplication* aurApp, AuraRemoveMode mode) override { if (!unit || !aurApp->GetBase()) return; + ALE* sALE = ALE::GetMapStateOrGlobal(unit->GetMapId()); if (unit->IsPlayer()) sALE->OnPlayerAuraRemove(unit->ToPlayer(), aurApp->GetBase(), mode); @@ -1245,6 +1277,7 @@ class ALE_UnitScript : public UnitScript void OnHeal(Unit* healer, Unit* receiver, uint32& gain) override { if (!receiver || !healer) return; + ALE* sALE = ALE::GetMapStateOrGlobal(healer->GetMapId()); if (healer->IsPlayer()) sALE->OnPlayerHeal(healer->ToPlayer(), receiver, gain); @@ -1259,6 +1292,7 @@ class ALE_UnitScript : public UnitScript void OnDamage(Unit* attacker, Unit* receiver, uint32& damage) override { if (!attacker || !receiver) return; + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId()); if (attacker->IsPlayer()) sALE->OnPlayerDamage(attacker->ToPlayer(), receiver, damage); @@ -1273,6 +1307,7 @@ class ALE_UnitScript : public UnitScript void ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage, SpellInfo const* spellInfo) override { if (!target || !attacker) return; + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId()); if (attacker->IsPlayer()) sALE->OnPlayerModifyPeriodicDamageAurasTick(attacker->ToPlayer(), target, damage, spellInfo); @@ -1287,6 +1322,7 @@ class ALE_UnitScript : public UnitScript void ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage) override { if (!target || !attacker) return; + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId()); if (attacker->IsPlayer()) sALE->OnPlayerModifyMeleeDamage(attacker->ToPlayer(), target, damage); @@ -1301,6 +1337,7 @@ class ALE_UnitScript : public UnitScript void ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage, SpellInfo const* spellInfo) override { if (!target || !attacker) return; + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId()); if (attacker->IsPlayer()) sALE->OnPlayerModifySpellDamageTaken(attacker->ToPlayer(), target, damage, spellInfo); @@ -1315,6 +1352,7 @@ class ALE_UnitScript : public UnitScript void ModifyHealReceived(Unit* target, Unit* healer, uint32& heal, SpellInfo const* spellInfo) override { if (!target || !healer) return; + ALE* sALE = ALE::GetMapStateOrGlobal(healer->GetMapId()); if (healer->IsPlayer()) sALE->OnPlayerModifyHealReceived(healer->ToPlayer(), target, heal, spellInfo); @@ -1329,6 +1367,7 @@ class ALE_UnitScript : public UnitScript uint32 DealDamage(Unit* AttackerUnit, Unit* pVictim, uint32 damage, DamageEffectType damagetype) override { if (!AttackerUnit || !pVictim) return damage; + ALE* sALE = ALE::GetMapStateOrGlobal(AttackerUnit->GetMapId()); if (AttackerUnit->IsPlayer()) return sALE->OnPlayerDealDamage(AttackerUnit->ToPlayer(), pVictim, damage, damagetype); diff --git a/src/LuaEngine/ALEConfig.cpp b/src/LuaEngine/ALEConfig.cpp index e3eca213bd..efd32fcb57 100644 --- a/src/LuaEngine/ALEConfig.cpp +++ b/src/LuaEngine/ALEConfig.cpp @@ -21,6 +21,7 @@ void ALEConfig::BuildConfigCache() SetConfigValue(ALEConfigValues::TRACEBACK_ENABLED, "ALE.TraceBack", "false"); SetConfigValue(ALEConfigValues::AUTORELOAD_ENABLED, "ALE.AutoReload", "false"); SetConfigValue(ALEConfigValues::BYTECODE_CACHE_ENABLED, "ALE.BytecodeCache", "false"); + SetConfigValue(ALEConfigValues::MULTISTATE_ENABLED, "ALE.Multistate", "false"); SetConfigValue(ALEConfigValues::SCRIPT_PATH, "ALE.ScriptPath", "lua_scripts"); SetConfigValue(ALEConfigValues::REQUIRE_PATH, "ALE.RequirePaths", ""); diff --git a/src/LuaEngine/ALEConfig.h b/src/LuaEngine/ALEConfig.h index b413b4a451..3495ac85fd 100644 --- a/src/LuaEngine/ALEConfig.h +++ b/src/LuaEngine/ALEConfig.h @@ -10,6 +10,7 @@ enum class ALEConfigValues : uint32 TRACEBACK_ENABLED, AUTORELOAD_ENABLED, BYTECODE_CACHE_ENABLED, + MULTISTATE_ENABLED, // String SCRIPT_PATH, @@ -33,6 +34,7 @@ class ALEConfig final : public ConfigValueCache bool IsTraceBackEnabled() const { return GetConfigValue(ALEConfigValues::TRACEBACK_ENABLED); } bool IsAutoReloadEnabled() const { return GetConfigValue(ALEConfigValues::AUTORELOAD_ENABLED); } bool IsByteCodeCacheEnabled() const { return GetConfigValue(ALEConfigValues::BYTECODE_CACHE_ENABLED); } + bool IsMultistateEnabled() const { return GetConfigValue(ALEConfigValues::MULTISTATE_ENABLED); } std::string_view GetScriptPath() const { return GetConfigValue(ALEConfigValues::SCRIPT_PATH); } std::string_view GetRequirePath() const { return GetConfigValue(ALEConfigValues::REQUIRE_PATH); } diff --git a/src/LuaEngine/ALECreatureAI.h b/src/LuaEngine/ALECreatureAI.h index cb9ccdae7c..3b584d0d07 100644 --- a/src/LuaEngine/ALECreatureAI.h +++ b/src/LuaEngine/ALECreatureAI.h @@ -17,8 +17,10 @@ struct ALECreatureAI : ScriptedAI bool justSpawned; // used to delay movementinform hook (WP hook) std::vector< std::pair > movepoints; + ALE* sALE; - ALECreatureAI(Creature* creature) : ScriptedAI(creature), justSpawned(true) + ALECreatureAI(Creature* creature) : ScriptedAI(creature), justSpawned(true), + sALE(ALE::GetMapStateOrGlobal(creature->GetMapId())) { } ~ALECreatureAI() { } diff --git a/src/LuaEngine/ALEEventMgr.cpp b/src/LuaEngine/ALEEventMgr.cpp index f90cee3167..498aad77b9 100644 --- a/src/LuaEngine/ALEEventMgr.cpp +++ b/src/LuaEngine/ALEEventMgr.cpp @@ -28,11 +28,11 @@ ALEEventProcessor::~ALEEventProcessor() { // can be called from multiple threads { - LOCK_ALE; + ALE::Guard guard((*E)->GetStateLock()); RemoveEvents_internal(); } - if (obj && ALE::IsInitialized()) + if (obj && ALE::IsInitialized() && *E && (*E)->eventMgr) { EventMgr::Guard guard((*E)->eventMgr->GetLock()); (*E)->eventMgr->processors.erase(this); diff --git a/src/LuaEngine/ALEInstanceAI.cpp b/src/LuaEngine/ALEInstanceAI.cpp index ea32f2feaa..252f8d5037 100644 --- a/src/LuaEngine/ALEInstanceAI.cpp +++ b/src/LuaEngine/ALEInstanceAI.cpp @@ -12,6 +12,7 @@ void ALEInstanceAI::Initialize() { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); ASSERT(!sALE->HasInstanceData(instance)); @@ -26,6 +27,7 @@ void ALEInstanceAI::Initialize() void ALEInstanceAI::Load(const char* data) { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); // If we get passed NULL (i.e. `Reload` was called) then use // the last known save data (or maybe just an empty string). @@ -108,6 +110,7 @@ void ALEInstanceAI::Load(const char* data) const char* ALEInstanceAI::Save() const { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); lua_State* L = sALE->L; // Stack: (empty) @@ -146,6 +149,7 @@ const char* ALEInstanceAI::Save() const uint32 ALEInstanceAI::GetData(uint32 key) const { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); lua_State* L = sALE->L; // Stack: (empty) @@ -168,6 +172,7 @@ uint32 ALEInstanceAI::GetData(uint32 key) const void ALEInstanceAI::SetData(uint32 key, uint32 value) { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); lua_State* L = sALE->L; // Stack: (empty) @@ -188,6 +193,7 @@ void ALEInstanceAI::SetData(uint32 key, uint32 value) uint64 ALEInstanceAI::GetData64(uint32 key) const { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); lua_State* L = sALE->L; // Stack: (empty) @@ -210,6 +216,7 @@ uint64 ALEInstanceAI::GetData64(uint32 key) const void ALEInstanceAI::SetData64(uint32 key, uint64 value) { LOCK_ALE; + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); lua_State* L = sALE->L; // Stack: (empty) diff --git a/src/LuaEngine/ALEInstanceAI.h b/src/LuaEngine/ALEInstanceAI.h index ebc5037db0..6ee03baa5c 100644 --- a/src/LuaEngine/ALEInstanceAI.h +++ b/src/LuaEngine/ALEInstanceAI.h @@ -53,7 +53,7 @@ class ALEInstanceAI : public InstanceData private: // The last save data to pass through this class, // either through `Load` or `Save`. - std::string lastSaveData; + mutable std::string lastSaveData; public: ALEInstanceAI(Map* map) : InstanceData(map) @@ -72,8 +72,8 @@ class ALEInstanceAI : public InstanceData { return Save(); } - const char* Save() const; + const char* Save() const; /* * Calls `Load` with the last save data that was passed to @@ -100,6 +100,8 @@ class ALEInstanceAI : public InstanceData */ void Update(uint32 diff) override { + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); + // If ALE is reloaded, it will be missing our instance data. // Reload here instead of waiting for the next hook call (possibly never). // This avoids having to have an empty Update hook handler just to trigger the reload. @@ -111,22 +113,22 @@ class ALEInstanceAI : public InstanceData bool IsEncounterInProgress() const override { - return sALE->OnCheckEncounterInProgress(const_cast(this)); + return ALE::GetMapStateOrGlobal(instance->GetId())->OnCheckEncounterInProgress(const_cast(this)); } void OnPlayerEnter(Player* player) override { - sALE->OnPlayerEnterInstance(this, player); + ALE::GetMapStateOrGlobal(instance->GetId())->OnPlayerEnterInstance(this, player); } void OnGameObjectCreate(GameObject* gameobject) override { - sALE->OnGameObjectCreate(this, gameobject); + ALE::GetMapStateOrGlobal(instance->GetId())->OnGameObjectCreate(this, gameobject); } void OnCreatureCreate(Creature* creature) override { - sALE->OnCreatureCreate(this, creature); + ALE::GetMapStateOrGlobal(instance->GetId())->OnCreatureCreate(this, creature); } }; diff --git a/src/LuaEngine/ALETemplate.h b/src/LuaEngine/ALETemplate.h index a8d6fc497a..de0d89bcaa 100644 --- a/src/LuaEngine/ALETemplate.h +++ b/src/LuaEngine/ALETemplate.h @@ -68,7 +68,7 @@ class ALEObject // Get wrapped object pointer void* GetObj() const { return object; } // Returns whether the object is valid or not - bool IsValid() const { return !callstackid || callstackid == sALE->GetCallstackId(); } + bool IsValid() const { return !callstackid || callstackid == ALE::GALE->GetCallstackId(); } // Returns whether the object can be invalidated or not bool CanInvalidate() const { return _invalidate; } // Returns pointer to the wrapped object's type name @@ -87,7 +87,7 @@ class ALEObject ASSERT(!valid || (valid && object)); if (valid) if (CanInvalidate()) - callstackid = sALE->GetCallstackId(); + callstackid = ALE::GALE->GetCallstackId(); else callstackid = 0; else diff --git a/src/LuaEngine/HttpManager.cpp b/src/LuaEngine/HttpManager.cpp index f7079cf3c9..af3024bdb9 100644 --- a/src/LuaEngine/HttpManager.cpp +++ b/src/LuaEngine/HttpManager.cpp @@ -11,8 +11,9 @@ extern "C" #include "HttpManager.h" #include "LuaEngine.h" -HttpWorkItem::HttpWorkItem(int funcRef, const std::string& httpVerb, const std::string& url, const std::string& body, const std::string& contentType, const httplib::Headers& headers) +HttpWorkItem::HttpWorkItem(int funcRef, ALE* state, const std::string& httpVerb, const std::string& url, const std::string& body, const std::string& contentType, const httplib::Headers& headers) : funcRef(funcRef), + state(state), httpVerb(httpVerb), url(url), body(body), @@ -20,8 +21,9 @@ HttpWorkItem::HttpWorkItem(int funcRef, const std::string& httpVerb, const std:: headers(headers) { } -HttpResponse::HttpResponse(int funcRef, int statusCode, const std::string& body, const httplib::Headers& headers) +HttpResponse::HttpResponse(int funcRef, ALE* state, int statusCode, const std::string& body, const httplib::Headers& headers) : funcRef(funcRef), + state(state), statusCode(statusCode), body(body), headers(headers) @@ -166,7 +168,7 @@ void HttpManager::HttpWorkerThread() res = DoRequest(cli2, req, path); } - responseQueue.push(new HttpResponse(req->funcRef, res->status, res->body, res->headers)); + responseQueue.push(new HttpResponse(req->funcRef, req->state, res->status, res->body, res->headers)); } catch (const std::exception& ex) { @@ -250,7 +252,7 @@ void HttpManager::HandleHttpResponses() LOCK_ALE; - lua_State* L = ALE::GALE->L; + lua_State* L = res->state->L; // Get function lua_rawgeti(L, LUA_REGISTRYINDEX, res->funcRef); @@ -266,7 +268,7 @@ void HttpManager::HandleHttpResponses() } // Call function - ALE::GALE->ExecuteCall(3, 0); + res->state->ExecuteCall(3, 0); luaL_unref(L, LUA_REGISTRYINDEX, res->funcRef); diff --git a/src/LuaEngine/HttpManager.h b/src/LuaEngine/HttpManager.h index cab17a4466..412739fe22 100644 --- a/src/LuaEngine/HttpManager.h +++ b/src/LuaEngine/HttpManager.h @@ -6,12 +6,15 @@ #include "libs/httplib.h" #include "libs/rigtorp/SPSCQueue.h" +class ALE; + struct HttpWorkItem { public: - HttpWorkItem(int funcRef, const std::string& httpVerb, const std::string& url, const std::string& body, const std::string &contentType, const httplib::Headers& headers); + HttpWorkItem(int funcRef, ALE* state, const std::string& httpVerb, const std::string& url, const std::string& body, const std::string &contentType, const httplib::Headers& headers); int funcRef; + ALE* state; std::string httpVerb; std::string url; std::string body; @@ -22,9 +25,10 @@ struct HttpWorkItem struct HttpResponse { public: - HttpResponse(int funcRef, int statusCode, const std::string& body, const httplib::Headers& headers); + HttpResponse(int funcRef, ALE* state, int statusCode, const std::string& body, const httplib::Headers& headers); int funcRef; + ALE* state; int statusCode; std::string body; httplib::Headers headers; diff --git a/src/LuaEngine/LuaEngine.cpp b/src/LuaEngine/LuaEngine.cpp index c647d689a5..be7345a17a 100644 --- a/src/LuaEngine/LuaEngine.cpp +++ b/src/LuaEngine/LuaEngine.cpp @@ -52,6 +52,10 @@ bool ALE::initialized = false; ALE::LockType ALE::lock; std::unique_ptr ALE::fileWatcher; +// Multistate handling +std::map ALE::g_states; +std::shared_mutex ALE::g_states_mutex; + // Global bytecode cache that survives ALE reloads static std::unordered_map globalBytecodeCache; static std::unordered_map timestampCache; @@ -75,7 +79,7 @@ void ALE::Initialize() initialized = true; // Create global ALE - GALE = new ALE(); + GALE = new ALE(nullptr, ALE_GLOBAL_STATE); // Start file watcher if enabled if (ALEConfig::GetInstance().IsAutoReloadEnabled()) @@ -98,6 +102,15 @@ void ALE::Uninitialize() fileWatcher.reset(); } + { + std::unique_lock lock(g_states_mutex); + for (auto& [mapId, state] : g_states) + { + delete state; + } + g_states.clear(); + } + delete GALE; GALE = NULL; @@ -110,6 +123,33 @@ void ALE::Uninitialize() initialized = false; } +ALE** ALE::CreateMapState(uint32 mapId) +{ + ALE** slotPtr; + { + std::unique_lock lock(g_states_mutex); + ASSERT(g_states.find(mapId) == g_states.end()); + auto& slot = g_states[mapId]; + slot = nullptr; + slotPtr = &slot; + slot = new ALE(slotPtr, mapId); + } + + (*slotPtr)->RunScripts(); + return slotPtr; +} + +void ALE::DestroyMapState(uint32 mapId) +{ + std::unique_lock lock(g_states_mutex); + auto it = g_states.find(mapId); + if (it != g_states.end()) + { + delete it->second; + g_states.erase(it); + } +} + void ALE::LoadScriptPaths() { uint32 oldMSTime = ALEUtil::GetCurrTime(); @@ -162,24 +202,35 @@ void ALE::_ReloadALE() ChatHandler(nullptr).SendGMText(SERVER_MSG_STRING, "Reloading ALE..."); // Remove all timed events - sALE->eventMgr->SetStates(LUAEVENT_STATE_ERASE); + ALE::GALE->eventMgr->SetStates(LUAEVENT_STATE_ERASE); // Close lua - sALE->CloseLua(); + ALE::GALE->CloseLua(); // Reload script paths LoadScriptPaths(); // Open new lua and libaraies - sALE->OpenLua(); + ALE::GALE->OpenLua(); // Run scripts from laoded paths - sALE->RunScripts(); + ALE::GALE->RunScripts(); + { + std::shared_lock lock(g_states_mutex); + for (auto& [mapId, state] : g_states) + { + state->eventMgr->SetStates(LUAEVENT_STATE_ERASE); + state->CloseLua(); + state->OpenLua(); + state->RunScripts(); + } + } + reload = false; } -ALE::ALE() : +ALE::ALE(ALE** _selfPtr, uint32 mapId) : event_level(0), push_counter(0), @@ -188,6 +239,9 @@ eventMgr(NULL), httpManager(), queryProcessor(), +selfPtr(_selfPtr), +stateMapId(mapId), + ServerEventBindings(NULL), PlayerEventBindings(NULL), GuildEventBindings(NULL), @@ -215,11 +269,8 @@ CreatureUniqueBindings(NULL) OpenLua(); - // Replace this with map insert if making multithread version - - // Set event manager. Must be after setting sALE - // on multithread have a map of state pointers and here insert this pointer to the map and then save a pointer of that pointer to the EventMgr - eventMgr = new EventMgr(&ALE::GALE); + ALE** evtPtr = selfPtr ? selfPtr : &ALE::GALE; + eventMgr = new EventMgr(evtPtr); } ALE::~ALE() @@ -837,7 +888,7 @@ int ALE::StackTrace(lua_State *_L) // dirty stack? // Stack: errmsg, debug, tracemsg - sALE->OnError(std::string(lua_tostring(_L, -1))); + ALE::GALE->OnError(std::string(lua_tostring(_L, -1))); return 1; } diff --git a/src/LuaEngine/LuaEngine.h b/src/LuaEngine/LuaEngine.h index a21640d0e4..f57f9e3bb5 100644 --- a/src/LuaEngine/LuaEngine.h +++ b/src/LuaEngine/LuaEngine.h @@ -28,6 +28,8 @@ #include "ALEConfig.h" #include #include +#include +#include #include #include #include @@ -104,6 +106,8 @@ struct LuaScript #define ALE_STATE_PTR "ALE State Ptr" #define LOCK_ALE ALE::Guard __guard(ALE::GetLock()) +#define LOCK_ALE_STATE ALE::Guard __guard(this->GetStateLock()) +#define ALE_GLOBAL_STATE (uint32)(-1) #define ALE_GAME_API AC_GAME_API @@ -118,7 +122,21 @@ class ALE_GAME_API ALE const std::string& GetRequirePath() const { return lua_requirepath; } const std::string& GetRequireCPath() const { return lua_requirecpath; } + LockType& GetStateLock() { return stateLock; } + uint32 GetStateMapId() const { return stateMapId; } + ALE** GetSelfPtr() { return selfPtr ? selfPtr : &ALE::GALE; } + + static void RunScriptsOnAllMapStates() + { + std::shared_lock lock(g_states_mutex); + for (auto& [mapId, state] : g_states) + state->RunScripts(); + } + private: + LockType stateLock; + uint32 stateMapId; + static bool reload; static bool initialized; static LockType lock; @@ -134,6 +152,10 @@ class ALE_GAME_API ALE static std::string lua_requirepath; static std::string lua_requirecpath; + // Per-map states. std::map used for pointer stability on insert/erase. + static std::map g_states; + static std::shared_mutex g_states_mutex; + // A counter for lua event stacks that occur (see event_level). // This is used to determine whether an object belongs to the current call stack or not. // 0 is reserved for always belonging to the call stack @@ -152,7 +174,9 @@ class ALE_GAME_API ALE // Map from map ID -> Lua table ref std::unordered_map continentDataRefs; - ALE(); + ALE** selfPtr; + + ALE(ALE** selfPtr = nullptr, uint32 mapId = ALE_GLOBAL_STATE); ~ALE(); // Prevent copy @@ -268,6 +292,33 @@ class ALE_GAME_API ALE static void ReloadALE() { LOCK_ALE; reload = true; } static LockType& GetLock() { return lock; }; static bool IsInitialized() { return initialized; } + + static ALE* GetMapState(uint32 mapId) + { + std::shared_lock lock(g_states_mutex); + auto it = g_states.find(mapId); + return it != g_states.end() ? it->second : nullptr; + } + + static ALE* GetMapStateOrGlobal(uint32 mapId) + { + std::shared_lock lock(g_states_mutex); + auto it = g_states.find(mapId); + return it != g_states.end() ? it->second : GALE; + } + + static ALE** CreateMapState(uint32 mapId); + static void DestroyMapState(uint32 mapId); + + // Returns a stable pointer-to-pointer for the map state slot, for use by ALEEventProcessor. + static ALE** GetMapStateSlot(uint32 mapId) + { + std::shared_lock lock(g_states_mutex); + auto it = g_states.find(mapId); + ASSERT(it != g_states.end()); + return &it->second; + } + // Never returns nullptr static ALE* GetALE(lua_State* L) { @@ -623,5 +674,5 @@ template<> Object* ALE::CHECKOBJ(lua_State* L, int narg, bool error); template<> WorldObject* ALE::CHECKOBJ(lua_State* L, int narg, bool error); template<> ALEObject* ALE::CHECKOBJ(lua_State* L, int narg, bool error); -#define sALE ALE::GALE +#define gALE ALE::GALE #endif diff --git a/src/LuaEngine/hooks/AllCreatureHooks.cpp b/src/LuaEngine/hooks/AllCreatureHooks.cpp index f32fe110e1..bb3f85dfe8 100644 --- a/src/LuaEngine/hooks/AllCreatureHooks.cpp +++ b/src/LuaEngine/hooks/AllCreatureHooks.cpp @@ -19,7 +19,7 @@ using namespace Hooks; auto key = EventKey(EVENT);\ if (!AllCreatureEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(EVENT, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -27,7 +27,7 @@ using namespace Hooks; auto key = EventKey(EVENT);\ if (!AllCreatureEventBindings->HasBindingsFor(key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnAllCreatureAddToWorld(Creature* creature) { diff --git a/src/LuaEngine/hooks/BattleGroundHooks.cpp b/src/LuaEngine/hooks/BattleGroundHooks.cpp index ec70cf5a15..5d3ee57a6a 100644 --- a/src/LuaEngine/hooks/BattleGroundHooks.cpp +++ b/src/LuaEngine/hooks/BattleGroundHooks.cpp @@ -18,7 +18,7 @@ using namespace Hooks; auto key = EventKey(EVENT);\ if (!BGEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnBGStart(BattleGround* bg, BattleGroundTypeId bgId, uint32 instanceId) { diff --git a/src/LuaEngine/hooks/CreatureHooks.cpp b/src/LuaEngine/hooks/CreatureHooks.cpp index 9fca834e48..3cf92a9373 100644 --- a/src/LuaEngine/hooks/CreatureHooks.cpp +++ b/src/LuaEngine/hooks/CreatureHooks.cpp @@ -21,7 +21,7 @@ using namespace Hooks; if (!CreatureEventBindings->HasBindingsFor(entry_key))\ if (!CreatureUniqueBindings->HasBindingsFor(unique_key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(EVENT, CREATURE, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -31,7 +31,7 @@ using namespace Hooks; if (!CreatureEventBindings->HasBindingsFor(entry_key))\ if (!CreatureUniqueBindings->HasBindingsFor(unique_key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnDummyEffect(WorldObject* pCaster, uint32 spellId, SpellEffIndex effIndex, Creature* pTarget) { diff --git a/src/LuaEngine/hooks/GameObjectHooks.cpp b/src/LuaEngine/hooks/GameObjectHooks.cpp index 7dd8508f4f..b25f300ee5 100644 --- a/src/LuaEngine/hooks/GameObjectHooks.cpp +++ b/src/LuaEngine/hooks/GameObjectHooks.cpp @@ -20,7 +20,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!GameObjectEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(EVENT, ENTRY, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -28,7 +28,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!GameObjectEventBindings->HasBindingsFor(key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnDummyEffect(WorldObject* pCaster, uint32 spellId, SpellEffIndex effIndex, GameObject* pTarget) { diff --git a/src/LuaEngine/hooks/GossipHooks.cpp b/src/LuaEngine/hooks/GossipHooks.cpp index 5fa324516f..aa0fad089a 100644 --- a/src/LuaEngine/hooks/GossipHooks.cpp +++ b/src/LuaEngine/hooks/GossipHooks.cpp @@ -19,7 +19,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!BINDINGS->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(BINDINGS, EVENT, ENTRY, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -27,7 +27,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!BINDINGS->HasBindingsFor(key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE bool ALE::OnGossipHello(Player* pPlayer, GameObject* pGameObject) { diff --git a/src/LuaEngine/hooks/InstanceHooks.cpp b/src/LuaEngine/hooks/InstanceHooks.cpp index 113ca2b348..56137b2c59 100644 --- a/src/LuaEngine/hooks/InstanceHooks.cpp +++ b/src/LuaEngine/hooks/InstanceHooks.cpp @@ -21,7 +21,7 @@ using namespace Hooks; auto instanceKey = EntryKey(EVENT, AI->instance->GetInstanceId());\ if (!MapEventBindings->HasBindingsFor(mapKey) && !InstanceEventBindings->HasBindingsFor(instanceKey))\ return;\ - LOCK_ALE;\ + LOCK_ALE_STATE;\ PushInstanceData(L, AI);\ Push(AI->instance) @@ -32,7 +32,7 @@ using namespace Hooks; auto instanceKey = EntryKey(EVENT, AI->instance->GetInstanceId());\ if (!MapEventBindings->HasBindingsFor(mapKey) && !InstanceEventBindings->HasBindingsFor(instanceKey))\ return RETVAL;\ - LOCK_ALE;\ + LOCK_ALE_STATE;\ PushInstanceData(L, AI);\ Push(AI->instance) diff --git a/src/LuaEngine/hooks/ItemHooks.cpp b/src/LuaEngine/hooks/ItemHooks.cpp index 9bc347480c..93afe065e9 100644 --- a/src/LuaEngine/hooks/ItemHooks.cpp +++ b/src/LuaEngine/hooks/ItemHooks.cpp @@ -19,7 +19,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!ItemEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(EVENT, ENTRY, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -27,7 +27,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!ItemEventBindings->HasBindingsFor(key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnDummyEffect(WorldObject* pCaster, uint32 spellId, SpellEffIndex effIndex, Item* pTarget) { diff --git a/src/LuaEngine/hooks/PlayerHooks.cpp b/src/LuaEngine/hooks/PlayerHooks.cpp index 7649274840..abd7f1995d 100644 --- a/src/LuaEngine/hooks/PlayerHooks.cpp +++ b/src/LuaEngine/hooks/PlayerHooks.cpp @@ -13,7 +13,7 @@ using namespace Hooks; -#define START_HOOK(EVENT) \ +#define START_HOOK_WORLD(EVENT) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ return;\ auto key = EventKey(EVENT);\ @@ -21,17 +21,33 @@ using namespace Hooks; return;\ LOCK_ALE -#define START_HOOK_WITH_RETVAL(EVENT, RETVAL) \ +#define START_HOOK_WORLD_WITH_RETVAL(EVENT, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ return RETVAL;\ auto key = EventKey(EVENT);\ if (!PlayerEventBindings->HasBindingsFor(key))\ return RETVAL;\ LOCK_ALE + +#define START_HOOK_MAP(EVENT) \ + if (!ALEConfig::GetInstance().IsALEEnabled())\ + return;\ + auto key = EventKey(EVENT);\ + if (!PlayerEventBindings->HasBindingsFor(key))\ + return;\ + LOCK_ALE_STATE + +#define START_HOOK_MAP_WITH_RETVAL(EVENT, RETVAL) \ + if (!ALEConfig::GetInstance().IsALEEnabled())\ + return RETVAL;\ + auto key = EventKey(EVENT);\ + if (!PlayerEventBindings->HasBindingsFor(key))\ + return RETVAL;\ + LOCK_ALE_STATE void ALE::OnLearnTalents(Player* pPlayer, uint32 talentId, uint32 talentRank, uint32 spellid) { - START_HOOK(PLAYER_EVENT_ON_LEARN_TALENTS); + START_HOOK_MAP(PLAYER_EVENT_ON_LEARN_TALENTS); Push(pPlayer); Push(talentId); Push(talentRank); @@ -54,7 +70,7 @@ bool ALE::OnCommand(ChatHandler& handler, const char* text) } } - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_COMMAND, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_COMMAND, true); Push(player); Push(text); Push(&handler); @@ -63,7 +79,7 @@ bool ALE::OnCommand(ChatHandler& handler, const char* text) void ALE::OnLootItem(Player* pPlayer, Item* pItem, uint32 count, ObjectGuid guid) { - START_HOOK(PLAYER_EVENT_ON_LOOT_ITEM); + START_HOOK_MAP(PLAYER_EVENT_ON_LOOT_ITEM); Push(pPlayer); Push(pItem); Push(count); @@ -73,7 +89,7 @@ void ALE::OnLootItem(Player* pPlayer, Item* pItem, uint32 count, ObjectGuid guid void ALE::OnLootMoney(Player* pPlayer, uint32 amount) { - START_HOOK(PLAYER_EVENT_ON_LOOT_MONEY); + START_HOOK_MAP(PLAYER_EVENT_ON_LOOT_MONEY); Push(pPlayer); Push(amount); CallAllFunctions(PlayerEventBindings, key); @@ -81,28 +97,28 @@ void ALE::OnLootMoney(Player* pPlayer, uint32 amount) void ALE::OnFirstLogin(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_FIRST_LOGIN); + START_HOOK_WORLD(PLAYER_EVENT_ON_FIRST_LOGIN); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnRepop(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_REPOP); + START_HOOK_MAP(PLAYER_EVENT_ON_REPOP); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnResurrect(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_RESURRECT); + START_HOOK_MAP(PLAYER_EVENT_ON_RESURRECT); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnQuestAbandon(Player* pPlayer, uint32 questId) { - START_HOOK(PLAYER_EVENT_ON_QUEST_ABANDON); + START_HOOK_MAP(PLAYER_EVENT_ON_QUEST_ABANDON); Push(pPlayer); Push(questId); CallAllFunctions(PlayerEventBindings, key); @@ -110,7 +126,7 @@ void ALE::OnQuestAbandon(Player* pPlayer, uint32 questId) void ALE::OnEquip(Player* pPlayer, Item* pItem, uint8 bag, uint8 slot) { - START_HOOK(PLAYER_EVENT_ON_EQUIP); + START_HOOK_MAP(PLAYER_EVENT_ON_EQUIP); Push(pPlayer); Push(pItem); Push(bag); @@ -120,7 +136,7 @@ void ALE::OnEquip(Player* pPlayer, Item* pItem, uint8 bag, uint8 slot) InventoryResult ALE::OnCanUseItem(const Player* pPlayer, uint32 itemEntry) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_USE_ITEM, EQUIP_ERR_OK); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_USE_ITEM, EQUIP_ERR_OK); InventoryResult result = EQUIP_ERR_OK; Push(pPlayer); Push(itemEntry); @@ -141,7 +157,7 @@ InventoryResult ALE::OnCanUseItem(const Player* pPlayer, uint32 itemEntry) } void ALE::OnPlayerEnterCombat(Player* pPlayer, Unit* pEnemy) { - START_HOOK(PLAYER_EVENT_ON_ENTER_COMBAT); + START_HOOK_MAP(PLAYER_EVENT_ON_ENTER_COMBAT); Push(pPlayer); Push(pEnemy); CallAllFunctions(PlayerEventBindings, key); @@ -149,14 +165,14 @@ void ALE::OnPlayerEnterCombat(Player* pPlayer, Unit* pEnemy) void ALE::OnPlayerLeaveCombat(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_LEAVE_COMBAT); + START_HOOK_MAP(PLAYER_EVENT_ON_LEAVE_COMBAT); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnPVPKill(Player* pKiller, Player* pKilled) { - START_HOOK(PLAYER_EVENT_ON_KILL_PLAYER); + START_HOOK_MAP(PLAYER_EVENT_ON_KILL_PLAYER); Push(pKiller); Push(pKilled); CallAllFunctions(PlayerEventBindings, key); @@ -164,7 +180,7 @@ void ALE::OnPVPKill(Player* pKiller, Player* pKilled) void ALE::OnCreatureKill(Player* pKiller, Creature* pKilled) { - START_HOOK(PLAYER_EVENT_ON_KILL_CREATURE); + START_HOOK_MAP(PLAYER_EVENT_ON_KILL_CREATURE); Push(pKiller); Push(pKilled); CallAllFunctions(PlayerEventBindings, key); @@ -172,7 +188,7 @@ void ALE::OnCreatureKill(Player* pKiller, Creature* pKilled) void ALE::OnPlayerKilledByCreature(Creature* pKiller, Player* pKilled) { - START_HOOK(PLAYER_EVENT_ON_KILLED_BY_CREATURE); + START_HOOK_MAP(PLAYER_EVENT_ON_KILLED_BY_CREATURE); Push(pKiller); Push(pKilled); CallAllFunctions(PlayerEventBindings, key); @@ -180,7 +196,7 @@ void ALE::OnPlayerKilledByCreature(Creature* pKiller, Player* pKilled) void ALE::OnLevelChanged(Player* pPlayer, uint8 oldLevel) { - START_HOOK(PLAYER_EVENT_ON_LEVEL_CHANGE); + START_HOOK_MAP(PLAYER_EVENT_ON_LEVEL_CHANGE); Push(pPlayer); Push(oldLevel); CallAllFunctions(PlayerEventBindings, key); @@ -188,7 +204,7 @@ void ALE::OnLevelChanged(Player* pPlayer, uint8 oldLevel) void ALE::OnFreeTalentPointsChanged(Player* pPlayer, uint32 newPoints) { - START_HOOK(PLAYER_EVENT_ON_TALENTS_CHANGE); + START_HOOK_MAP(PLAYER_EVENT_ON_TALENTS_CHANGE); Push(pPlayer); Push(newPoints); CallAllFunctions(PlayerEventBindings, key); @@ -196,7 +212,7 @@ void ALE::OnFreeTalentPointsChanged(Player* pPlayer, uint32 newPoints) void ALE::OnTalentsReset(Player* pPlayer, bool noCost) { - START_HOOK(PLAYER_EVENT_ON_TALENTS_RESET); + START_HOOK_MAP(PLAYER_EVENT_ON_TALENTS_RESET); Push(pPlayer); Push(noCost); CallAllFunctions(PlayerEventBindings, key); @@ -204,7 +220,7 @@ void ALE::OnTalentsReset(Player* pPlayer, bool noCost) void ALE::OnMoneyChanged(Player* pPlayer, int32& amount) { - START_HOOK(PLAYER_EVENT_ON_MONEY_CHANGE); + START_HOOK_MAP(PLAYER_EVENT_ON_MONEY_CHANGE); Push(pPlayer); Push(amount); int amountIndex = lua_gettop(L); @@ -229,7 +245,7 @@ void ALE::OnMoneyChanged(Player* pPlayer, int32& amount) void ALE::OnGiveXP(Player* pPlayer, uint32& amount, Unit* pVictim, uint8 xpSource) { - START_HOOK(PLAYER_EVENT_ON_GIVE_XP); + START_HOOK_MAP(PLAYER_EVENT_ON_GIVE_XP); Push(pPlayer); Push(amount); Push(pVictim); @@ -256,7 +272,7 @@ void ALE::OnGiveXP(Player* pPlayer, uint32& amount, Unit* pVictim, uint8 xpSourc bool ALE::OnReputationChange(Player* pPlayer, uint32 factionID, int32& standing, bool incremental) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_REPUTATION_CHANGE, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_REPUTATION_CHANGE, true); bool result = true; Push(pPlayer); Push(factionID); @@ -287,7 +303,7 @@ bool ALE::OnReputationChange(Player* pPlayer, uint32 factionID, int32& standing, void ALE::OnDuelRequest(Player* pTarget, Player* pChallenger) { - START_HOOK(PLAYER_EVENT_ON_DUEL_REQUEST); + START_HOOK_MAP(PLAYER_EVENT_ON_DUEL_REQUEST); Push(pTarget); Push(pChallenger); CallAllFunctions(PlayerEventBindings, key); @@ -295,7 +311,7 @@ void ALE::OnDuelRequest(Player* pTarget, Player* pChallenger) void ALE::OnDuelStart(Player* pStarter, Player* pChallenger) { - START_HOOK(PLAYER_EVENT_ON_DUEL_START); + START_HOOK_MAP(PLAYER_EVENT_ON_DUEL_START); Push(pStarter); Push(pChallenger); CallAllFunctions(PlayerEventBindings, key); @@ -303,7 +319,7 @@ void ALE::OnDuelStart(Player* pStarter, Player* pChallenger) void ALE::OnDuelEnd(Player* pWinner, Player* pLoser, DuelCompleteType type) { - START_HOOK(PLAYER_EVENT_ON_DUEL_END); + START_HOOK_MAP(PLAYER_EVENT_ON_DUEL_END); Push(pWinner); Push(pLoser); Push(type); @@ -312,7 +328,7 @@ void ALE::OnDuelEnd(Player* pWinner, Player* pLoser, DuelCompleteType type) void ALE::OnEmote(Player* pPlayer, uint32 emote) { - START_HOOK(PLAYER_EVENT_ON_EMOTE); + START_HOOK_MAP(PLAYER_EVENT_ON_EMOTE); Push(pPlayer); Push(emote); CallAllFunctions(PlayerEventBindings, key); @@ -320,7 +336,7 @@ void ALE::OnEmote(Player* pPlayer, uint32 emote) void ALE::OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, ObjectGuid guid) { - START_HOOK(PLAYER_EVENT_ON_TEXT_EMOTE); + START_HOOK_MAP(PLAYER_EVENT_ON_TEXT_EMOTE); Push(pPlayer); Push(textEmote); Push(emoteNum); @@ -330,7 +346,7 @@ void ALE::OnTextEmote(Player* pPlayer, uint32 textEmote, uint32 emoteNum, Object void ALE::OnPlayerSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck) { - START_HOOK(PLAYER_EVENT_ON_SPELL_CAST); + START_HOOK_MAP(PLAYER_EVENT_ON_SPELL_CAST); Push(pPlayer); Push(pSpell); Push(skipCheck); @@ -339,42 +355,42 @@ void ALE::OnPlayerSpellCast(Player* pPlayer, Spell* pSpell, bool skipCheck) void ALE::OnLogin(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_LOGIN); + START_HOOK_WORLD(PLAYER_EVENT_ON_LOGIN); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnLogout(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_LOGOUT); + START_HOOK_WORLD(PLAYER_EVENT_ON_LOGOUT); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnCreate(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_CHARACTER_CREATE); + START_HOOK_WORLD(PLAYER_EVENT_ON_CHARACTER_CREATE); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnDelete(uint32 guidlow) { - START_HOOK(PLAYER_EVENT_ON_CHARACTER_DELETE); + START_HOOK_WORLD(PLAYER_EVENT_ON_CHARACTER_DELETE); Push(guidlow); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnSave(Player* pPlayer) { - START_HOOK(PLAYER_EVENT_ON_SAVE); + START_HOOK_MAP(PLAYER_EVENT_ON_SAVE); Push(pPlayer); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnBindToInstance(Player* pPlayer, Difficulty difficulty, uint32 mapid, bool permanent) { - START_HOOK(PLAYER_EVENT_ON_BIND_TO_INSTANCE); + START_HOOK_MAP(PLAYER_EVENT_ON_BIND_TO_INSTANCE); Push(pPlayer); Push(difficulty); Push(mapid); @@ -384,7 +400,7 @@ void ALE::OnBindToInstance(Player* pPlayer, Difficulty difficulty, uint32 mapid, void ALE::OnUpdateArea(Player* pPlayer, uint32 oldArea, uint32 newArea) { - START_HOOK(PLAYER_EVENT_ON_UPDATE_AREA); + START_HOOK_MAP(PLAYER_EVENT_ON_UPDATE_AREA); Push(pPlayer); Push(oldArea); Push(newArea); @@ -393,7 +409,7 @@ void ALE::OnUpdateArea(Player* pPlayer, uint32 oldArea, uint32 newArea) void ALE::OnUpdateZone(Player* pPlayer, uint32 newZone, uint32 newArea) { - START_HOOK(PLAYER_EVENT_ON_UPDATE_ZONE); + START_HOOK_MAP(PLAYER_EVENT_ON_UPDATE_ZONE); Push(pPlayer); Push(newZone); Push(newArea); @@ -402,7 +418,7 @@ void ALE::OnUpdateZone(Player* pPlayer, uint32 newZone, uint32 newArea) void ALE::OnMapChanged(Player* player) { - START_HOOK(PLAYER_EVENT_ON_MAP_CHANGE); + START_HOOK_MAP(PLAYER_EVENT_ON_MAP_CHANGE); Push(player); CallAllFunctions(PlayerEventBindings, key); } @@ -412,7 +428,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg) if (lang == LANG_ADDON) return OnAddonMessage(pPlayer, type, msg, NULL, NULL, NULL, NULL); - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CHAT, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_CHAT, true); bool result = true; Push(pPlayer); Push(msg); @@ -442,7 +458,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Gr if (lang == LANG_ADDON) return OnAddonMessage(pPlayer, type, msg, NULL, NULL, pGroup, NULL); - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_GROUP_CHAT, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_GROUP_CHAT, true); bool result = true; Push(pPlayer); Push(msg); @@ -473,7 +489,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Gu if (lang == LANG_ADDON) return OnAddonMessage(pPlayer, type, msg, NULL, pGuild, NULL, NULL); - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_GUILD_CHAT, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_GUILD_CHAT, true); bool result = true; Push(pPlayer); Push(msg); @@ -504,7 +520,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Ch if (lang == LANG_ADDON) return OnAddonMessage(pPlayer, type, msg, NULL, NULL, NULL, pChannel); - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CHANNEL_CHAT, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_CHANNEL_CHAT, true); bool result = true; Push(pPlayer); Push(msg); @@ -535,7 +551,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Pl if (lang == LANG_ADDON) return OnAddonMessage(pPlayer, type, msg, pReceiver, NULL, NULL, NULL); - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_WHISPER, true); + START_HOOK_WORLD_WITH_RETVAL(PLAYER_EVENT_ON_WHISPER, true); bool result = true; Push(pPlayer); Push(msg); @@ -563,7 +579,7 @@ bool ALE::OnChat(Player* pPlayer, uint32 type, uint32 lang, std::string& msg, Pl void ALE::OnPetAddedToWorld(Player* player, Creature* pet) { - START_HOOK(PLAYER_EVENT_ON_PET_ADDED_TO_WORLD); + START_HOOK_MAP(PLAYER_EVENT_ON_PET_ADDED_TO_WORLD); Push(player); Push(pet); CallAllFunctions(PlayerEventBindings, key); @@ -571,7 +587,7 @@ void ALE::OnPetAddedToWorld(Player* player, Creature* pet) void ALE::OnLearnSpell(Player* player, uint32 spellId) { - START_HOOK(PLAYER_EVENT_ON_LEARN_SPELL); + START_HOOK_MAP(PLAYER_EVENT_ON_LEARN_SPELL); Push(player); Push(spellId); CallAllFunctions(PlayerEventBindings, key); @@ -579,7 +595,7 @@ void ALE::OnLearnSpell(Player* player, uint32 spellId) void ALE::OnAchiComplete(Player* player, AchievementEntry const* achievement) { - START_HOOK(PLAYER_EVENT_ON_ACHIEVEMENT_COMPLETE); + START_HOOK_MAP(PLAYER_EVENT_ON_ACHIEVEMENT_COMPLETE); Push(player); Push(achievement); CallAllFunctions(PlayerEventBindings, key); @@ -587,7 +603,7 @@ void ALE::OnAchiComplete(Player* player, AchievementEntry const* achievement) void ALE::OnFfaPvpStateUpdate(Player* player, bool hasFfaPvp) { - START_HOOK(PLAYER_EVENT_ON_FFAPVP_CHANGE); + START_HOOK_MAP(PLAYER_EVENT_ON_FFAPVP_CHANGE); Push(player); Push(hasFfaPvp); CallAllFunctions(PlayerEventBindings, key); @@ -595,7 +611,7 @@ void ALE::OnFfaPvpStateUpdate(Player* player, bool hasFfaPvp) bool ALE::OnCanInitTrade(Player* player, Player* target) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_INIT_TRADE, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_INIT_TRADE, true); Push(player); Push(target); return CallAllFunctionsBool(PlayerEventBindings, key); @@ -603,7 +619,7 @@ bool ALE::OnCanInitTrade(Player* player, Player* target) bool ALE::OnCanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 cod, Item* item) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_SEND_MAIL, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_SEND_MAIL, true); Push(player); Push(receiverGuid); Push(mailbox); @@ -617,7 +633,7 @@ bool ALE::OnCanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mail bool ALE::OnCanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_JOIN_LFG, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_JOIN_LFG, true); Push(player); Push(roles); @@ -639,7 +655,7 @@ bool ALE::OnCanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons void ALE::OnQuestRewardItem(Player* player, Item* item, uint32 count) { - START_HOOK(PLAYER_EVENT_ON_QUEST_REWARD_ITEM); + START_HOOK_MAP(PLAYER_EVENT_ON_QUEST_REWARD_ITEM); Push(player); Push(item); Push(count); @@ -648,7 +664,7 @@ void ALE::OnQuestRewardItem(Player* player, Item* item, uint32 count) void ALE::OnCreateItem(Player* player, Item* item, uint32 count) { - START_HOOK(PLAYER_EVENT_ON_CREATE_ITEM); + START_HOOK_MAP(PLAYER_EVENT_ON_CREATE_ITEM); Push(player); Push(item); Push(count); @@ -657,7 +673,7 @@ void ALE::OnCreateItem(Player* player, Item* item, uint32 count) void ALE::OnStoreNewItem(Player* player, Item* item, uint32 count) { - START_HOOK(PLAYER_EVENT_ON_STORE_NEW_ITEM); + START_HOOK_MAP(PLAYER_EVENT_ON_STORE_NEW_ITEM); Push(player); Push(item); Push(count); @@ -666,7 +682,7 @@ void ALE::OnStoreNewItem(Player* player, Item* item, uint32 count) void ALE::OnPlayerCompleteQuest(Player* player, Quest const* quest) { - START_HOOK(PLAYER_EVENT_ON_COMPLETE_QUEST); + START_HOOK_MAP(PLAYER_EVENT_ON_COMPLETE_QUEST); Push(player); Push(quest); CallAllFunctions(PlayerEventBindings, key); @@ -674,7 +690,7 @@ void ALE::OnPlayerCompleteQuest(Player* player, Quest const* quest) bool ALE::OnCanGroupInvite(Player* player, std::string& memberName) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_GROUP_INVITE, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_GROUP_INVITE, true); Push(player); Push(memberName); return CallAllFunctionsBool(PlayerEventBindings, key); @@ -682,7 +698,7 @@ bool ALE::OnCanGroupInvite(Player* player, std::string& memberName) void ALE::OnGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll) { - START_HOOK(PLAYER_EVENT_ON_GROUP_ROLL_REWARD_ITEM); + START_HOOK_MAP(PLAYER_EVENT_ON_GROUP_ROLL_REWARD_ITEM); Push(player); Push(item); Push(count); @@ -693,7 +709,7 @@ void ALE::OnGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVo void ALE::OnBattlegroundDesertion(Player* player, const BattlegroundDesertionType type) { - START_HOOK(PLAYER_EVENT_ON_BG_DESERTION); + START_HOOK_MAP(PLAYER_EVENT_ON_BG_DESERTION); Push(player); Push(type); CallAllFunctions(PlayerEventBindings, key); @@ -701,7 +717,7 @@ void ALE::OnBattlegroundDesertion(Player* player, const BattlegroundDesertionTyp void ALE::OnCreatureKilledByPet(Player* player, Creature* killed) { - START_HOOK(PLAYER_EVENT_ON_PET_KILL); + START_HOOK_MAP(PLAYER_EVENT_ON_PET_KILL); Push(player); Push(killed); CallAllFunctions(PlayerEventBindings, key); @@ -709,7 +725,7 @@ void ALE::OnCreatureKilledByPet(Player* player, Creature* killed) bool ALE::OnPlayerCanUpdateSkill(Player* player, uint32 skill_id) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_UPDATE_SKILL, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_UPDATE_SKILL, true); Push(player); Push(skill_id); return CallAllFunctionsBool(PlayerEventBindings, key); @@ -717,7 +733,7 @@ bool ALE::OnPlayerCanUpdateSkill(Player* player, uint32 skill_id) void ALE::OnPlayerBeforeUpdateSkill(Player* player, uint32 skill_id, uint32& value, uint32 max, uint32 step) { - START_HOOK(PLAYER_EVENT_ON_BEFORE_UPDATE_SKILL); + START_HOOK_MAP(PLAYER_EVENT_ON_BEFORE_UPDATE_SKILL); Push(player); Push(skill_id); Push(value); @@ -744,7 +760,7 @@ void ALE::OnPlayerBeforeUpdateSkill(Player* player, uint32 skill_id, uint32& val void ALE::OnPlayerUpdateSkill(Player* player, uint32 skill_id, uint32 value, uint32 max, uint32 step, uint32 new_value) { - START_HOOK(PLAYER_EVENT_ON_UPDATE_SKILL); + START_HOOK_MAP(PLAYER_EVENT_ON_UPDATE_SKILL); Push(player); Push(skill_id); Push(value); @@ -756,21 +772,21 @@ void ALE::OnPlayerUpdateSkill(Player* player, uint32 skill_id, uint32 value, uin bool ALE::CanPlayerResurrect(Player* player) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_CAN_RESURRECT, true); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_CAN_RESURRECT, true); Push(player); return CallAllFunctionsBool(PlayerEventBindings, key); } void ALE::OnPlayerReleasedGhost(Player* player) { - START_HOOK(PLAYER_EVENT_ON_RELEASED_GHOST); + START_HOOK_MAP(PLAYER_EVENT_ON_RELEASED_GHOST); Push(player); CallAllFunctions(PlayerEventBindings, key); } void ALE::OnPlayerQuestAccept(Player* player, Quest const* quest) { - START_HOOK(PLAYER_EVENT_ON_QUEST_ACCEPT); + START_HOOK_MAP(PLAYER_EVENT_ON_QUEST_ACCEPT); Push(player); Push(quest); CallAllFunctions(PlayerEventBindings, key); @@ -778,7 +794,7 @@ void ALE::OnPlayerQuestAccept(Player* player, Quest const* quest) void ALE::OnPlayerAuraApply(Player* player, Aura* aura) { - START_HOOK(PLAYER_EVENT_ON_AURA_APPLY); + START_HOOK_MAP(PLAYER_EVENT_ON_AURA_APPLY); Push(player); Push(aura); CallAllFunctions(PlayerEventBindings, key); @@ -786,7 +802,7 @@ void ALE::OnPlayerAuraApply(Player* player, Aura* aura) void ALE::OnPlayerHeal(Player* player, Unit* target, uint32& gain) { - START_HOOK(PLAYER_EVENT_ON_HEAL); + START_HOOK_MAP(PLAYER_EVENT_ON_HEAL); Push(player); Push(target); Push(gain); @@ -811,7 +827,7 @@ void ALE::OnPlayerHeal(Player* player, Unit* target, uint32& gain) void ALE::OnPlayerDamage(Player* player, Unit* target, uint32& damage) { - START_HOOK(PLAYER_EVENT_ON_DAMAGE); + START_HOOK_MAP(PLAYER_EVENT_ON_DAMAGE); Push(player); Push(target); Push(damage); @@ -836,7 +852,7 @@ void ALE::OnPlayerDamage(Player* player, Unit* target, uint32& damage) void ALE::OnPlayerAuraRemove(Player* player, Aura* aura, AuraRemoveMode mode) { - START_HOOK(PLAYER_EVENT_ON_AURA_REMOVE); + START_HOOK_MAP(PLAYER_EVENT_ON_AURA_REMOVE); Push(player); Push(aura); Push(mode); @@ -845,7 +861,7 @@ void ALE::OnPlayerAuraRemove(Player* player, Aura* aura, AuraRemoveMode mode) void ALE::OnPlayerModifyPeriodicDamageAurasTick(Player* player, Unit* target, uint32& damage, SpellInfo const* spellInfo) { - START_HOOK(PLAYER_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK); + START_HOOK_MAP(PLAYER_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK); Push(player); Push(target); Push(damage); @@ -871,7 +887,7 @@ void ALE::OnPlayerModifyPeriodicDamageAurasTick(Player* player, Unit* target, ui void ALE::OnPlayerModifyMeleeDamage(Player* player, Unit* target, uint32& damage) { - START_HOOK(PLAYER_EVENT_ON_MODIFY_MELEE_DAMAGE); + START_HOOK_MAP(PLAYER_EVENT_ON_MODIFY_MELEE_DAMAGE); Push(player); Push(target); Push(damage); @@ -896,7 +912,7 @@ void ALE::OnPlayerModifyMeleeDamage(Player* player, Unit* target, uint32& damage void ALE::OnPlayerModifySpellDamageTaken(Player* player, Unit* target, int32& damage, SpellInfo const* spellInfo) { - START_HOOK(PLAYER_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN); + START_HOOK_MAP(PLAYER_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN); Push(player); Push(target); Push(damage); @@ -922,7 +938,7 @@ void ALE::OnPlayerModifySpellDamageTaken(Player* player, Unit* target, int32& da void ALE::OnPlayerModifyHealReceived(Player* player, Unit* target, uint32& heal, SpellInfo const* spellInfo) { - START_HOOK(PLAYER_EVENT_ON_MODIFY_HEAL_RECEIVED); + START_HOOK_MAP(PLAYER_EVENT_ON_MODIFY_HEAL_RECEIVED); Push(player); Push(target); Push(heal); @@ -948,7 +964,7 @@ void ALE::OnPlayerModifyHealReceived(Player* player, Unit* target, uint32& heal, uint32 ALE::OnPlayerDealDamage(Player* player, Unit* target, uint32 damage, DamageEffectType damagetype) { - START_HOOK_WITH_RETVAL(PLAYER_EVENT_ON_DEAL_DAMAGE, damage); + START_HOOK_MAP_WITH_RETVAL(PLAYER_EVENT_ON_DEAL_DAMAGE, damage); Push(player); Push(target); Push(damage); diff --git a/src/LuaEngine/hooks/ServerHooks.cpp b/src/LuaEngine/hooks/ServerHooks.cpp index f305c97b7e..0534cb0c95 100644 --- a/src/LuaEngine/hooks/ServerHooks.cpp +++ b/src/LuaEngine/hooks/ServerHooks.cpp @@ -14,7 +14,7 @@ using namespace Hooks; -#define START_HOOK(EVENT) \ +#define START_HOOK_WORLD(EVENT) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ return;\ auto key = EventKey(EVENT);\ @@ -22,7 +22,7 @@ using namespace Hooks; return;\ LOCK_ALE -#define START_HOOK_WITH_RETVAL(EVENT, RETVAL) \ +#define START_HOOK_WORLD_WITH_RETVAL(EVENT, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ return RETVAL;\ auto key = EventKey(EVENT);\ @@ -30,9 +30,25 @@ using namespace Hooks; return RETVAL;\ LOCK_ALE +#define START_HOOK_MAP(EVENT) \ + if (!ALEConfig::GetInstance().IsALEEnabled())\ + return;\ + auto key = EventKey(EVENT);\ + if (!ServerEventBindings->HasBindingsFor(key))\ + return;\ + LOCK_ALE_STATE + +#define START_HOOK_MAP_WITH_RETVAL(EVENT, RETVAL) \ + if (!ALEConfig::GetInstance().IsALEEnabled())\ + return RETVAL;\ + auto key = EventKey(EVENT);\ + if (!ServerEventBindings->HasBindingsFor(key))\ + return RETVAL;\ + LOCK_ALE_STATE + bool ALE::OnAddonMessage(Player* sender, uint32 type, std::string& msg, Player* receiver, Guild* guild, Group* group, Channel* channel) { - START_HOOK_WITH_RETVAL(ADDON_EVENT_ON_MESSAGE, true); + START_HOOK_WORLD_WITH_RETVAL(ADDON_EVENT_ON_MESSAGE, true); Push(sender); Push(type); @@ -66,7 +82,7 @@ bool ALE::OnAddonMessage(Player* sender, uint32 type, std::string& msg, Player* void ALE::OnTimedEvent(int funcRef, uint32 delay, uint32 calls, WorldObject* obj) { - LOCK_ALE; + LOCK_ALE_STATE; ASSERT(!event_level); // Get function @@ -87,34 +103,34 @@ void ALE::OnTimedEvent(int funcRef, uint32 delay, uint32 calls, WorldObject* obj void ALE::OnGameEventStart(uint32 eventid) { - START_HOOK(GAME_EVENT_START); + START_HOOK_WORLD(GAME_EVENT_START); Push(eventid); CallAllFunctions(ServerEventBindings, key); } void ALE::OnGameEventStop(uint32 eventid) { - START_HOOK(GAME_EVENT_STOP); + START_HOOK_WORLD(GAME_EVENT_STOP); Push(eventid); CallAllFunctions(ServerEventBindings, key); } void ALE::OnLuaStateClose() { - START_HOOK(ALE_EVENT_ON_LUA_STATE_CLOSE); + START_HOOK_MAP(ALE_EVENT_ON_LUA_STATE_CLOSE); // Uses map since each state, including world (-1), calls this on close CallAllFunctions(ServerEventBindings, key); } void ALE::OnLuaStateOpen() { - START_HOOK(ALE_EVENT_ON_LUA_STATE_OPEN); + START_HOOK_MAP(ALE_EVENT_ON_LUA_STATE_OPEN); // Uses map since each state, including world (-1), calls this on open CallAllFunctions(ServerEventBindings, key); } // AreaTrigger bool ALE::OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* pTrigger) { - START_HOOK_WITH_RETVAL(TRIGGER_EVENT_ON_TRIGGER, false); + START_HOOK_MAP_WITH_RETVAL(TRIGGER_EVENT_ON_TRIGGER, false); Push(pPlayer); Push(pTrigger->entry); @@ -124,7 +140,7 @@ bool ALE::OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* pTrigger) // Weather void ALE::OnChange(Weather* /*weather*/, uint32 zone, WeatherState state, float grade) { - START_HOOK(WEATHER_EVENT_ON_CHANGE); + START_HOOK_WORLD(WEATHER_EVENT_ON_CHANGE); Push(zone); Push(state); Push(grade); @@ -142,7 +158,7 @@ void ALE::OnAdd(AuctionHouseObject* /*ah*/, AuctionEntry* entry) if (!owner || !item) return; - START_HOOK(AUCTION_EVENT_ON_ADD); + START_HOOK_WORLD(AUCTION_EVENT_ON_ADD); Push(entry->Id); Push(owner); Push(item); @@ -164,7 +180,7 @@ void ALE::OnRemove(AuctionHouseObject* /*ah*/, AuctionEntry* entry) if (!owner || !item) return; - START_HOOK(AUCTION_EVENT_ON_REMOVE); + START_HOOK_WORLD(AUCTION_EVENT_ON_REMOVE); Push(entry->Id); Push(owner); Push(item); @@ -186,7 +202,7 @@ void ALE::OnSuccessful(AuctionHouseObject* /*ah*/, AuctionEntry* entry) if (!owner || !item) return; - START_HOOK(AUCTION_EVENT_ON_SUCCESSFUL); + START_HOOK_WORLD(AUCTION_EVENT_ON_SUCCESSFUL); Push(entry->Id); Push(owner); Push(item); @@ -208,7 +224,7 @@ void ALE::OnExpire(AuctionHouseObject* /*ah*/, AuctionEntry* entry) if (!owner || !item) return; - START_HOOK(AUCTION_EVENT_ON_EXPIRE); + START_HOOK_WORLD(AUCTION_EVENT_ON_EXPIRE); Push(entry->Id); Push(owner); Push(item); @@ -222,14 +238,14 @@ void ALE::OnExpire(AuctionHouseObject* /*ah*/, AuctionEntry* entry) void ALE::OnOpenStateChange(bool open) { - START_HOOK(WORLD_EVENT_ON_OPEN_STATE_CHANGE); + START_HOOK_WORLD(WORLD_EVENT_ON_OPEN_STATE_CHANGE); Push(open); CallAllFunctions(ServerEventBindings, key); } void ALE::OnConfigLoad(bool reload, bool isBefore) { - START_HOOK(WORLD_EVENT_ON_CONFIG_LOAD); + START_HOOK_WORLD(WORLD_EVENT_ON_CONFIG_LOAD); Push(reload); Push(isBefore); CallAllFunctions(ServerEventBindings, key); @@ -237,7 +253,7 @@ void ALE::OnConfigLoad(bool reload, bool isBefore) void ALE::OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask) { - START_HOOK(WORLD_EVENT_ON_SHUTDOWN_INIT); + START_HOOK_WORLD(WORLD_EVENT_ON_SHUTDOWN_INIT); Push(code); Push(mask); CallAllFunctions(ServerEventBindings, key); @@ -245,7 +261,7 @@ void ALE::OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask) void ALE::OnShutdownCancel() { - START_HOOK(WORLD_EVENT_ON_SHUTDOWN_CANCEL); + START_HOOK_WORLD(WORLD_EVENT_ON_SHUTDOWN_CANCEL); CallAllFunctions(ServerEventBindings, key); } @@ -261,41 +277,53 @@ void ALE::OnWorldUpdate(uint32 diff) httpManager.HandleHttpResponses(); queryProcessor.ProcessReadyCallbacks(); - START_HOOK(WORLD_EVENT_ON_UPDATE); + { + std::shared_lock lock(g_states_mutex); + for (auto& [mapId, state] : g_states) + { + if (state) + { + state->httpManager.HandleHttpResponses(); + state->queryProcessor.ProcessReadyCallbacks(); + } + } + } + + START_HOOK_WORLD(WORLD_EVENT_ON_UPDATE); Push(diff); CallAllFunctions(ServerEventBindings, key); } void ALE::OnStartup() { - START_HOOK(WORLD_EVENT_ON_STARTUP); + START_HOOK_WORLD(WORLD_EVENT_ON_STARTUP); CallAllFunctions(ServerEventBindings, key); } void ALE::OnShutdown() { - START_HOOK(WORLD_EVENT_ON_SHUTDOWN); + START_HOOK_WORLD(WORLD_EVENT_ON_SHUTDOWN); CallAllFunctions(ServerEventBindings, key); } /* Map */ void ALE::OnCreate(Map* map) { - START_HOOK(MAP_EVENT_ON_CREATE); + START_HOOK_MAP(MAP_EVENT_ON_CREATE); Push(map); CallAllFunctions(ServerEventBindings, key); } void ALE::OnDestroy(Map* map) { - START_HOOK(MAP_EVENT_ON_DESTROY); + START_HOOK_MAP(MAP_EVENT_ON_DESTROY); Push(map); CallAllFunctions(ServerEventBindings, key); } void ALE::OnPlayerEnter(Map* map, Player* player) { - START_HOOK(MAP_EVENT_ON_PLAYER_ENTER); + START_HOOK_MAP(MAP_EVENT_ON_PLAYER_ENTER); Push(map); Push(player); CallAllFunctions(ServerEventBindings, key); @@ -303,7 +331,7 @@ void ALE::OnPlayerEnter(Map* map, Player* player) void ALE::OnPlayerLeave(Map* map, Player* player) { - START_HOOK(MAP_EVENT_ON_PLAYER_LEAVE); + START_HOOK_MAP(MAP_EVENT_ON_PLAYER_LEAVE); Push(map); Push(player); CallAllFunctions(ServerEventBindings, key); @@ -311,7 +339,7 @@ void ALE::OnPlayerLeave(Map* map, Player* player) void ALE::OnUpdate(Map* map, uint32 diff) { - START_HOOK(MAP_EVENT_ON_UPDATE); + START_HOOK_MAP(MAP_EVENT_ON_UPDATE); // enable this for multithread // eventMgr->globalProcessor->Update(diff); Push(map); @@ -321,14 +349,14 @@ void ALE::OnUpdate(Map* map, uint32 diff) void ALE::OnRemove(GameObject* gameobject) { - START_HOOK(WORLD_EVENT_ON_DELETE_GAMEOBJECT); + START_HOOK_MAP(WORLD_EVENT_ON_DELETE_GAMEOBJECT); Push(gameobject); CallAllFunctions(ServerEventBindings, key); } void ALE::OnRemove(Creature* creature) { - START_HOOK(WORLD_EVENT_ON_DELETE_CREATURE); + START_HOOK_MAP(WORLD_EVENT_ON_DELETE_CREATURE); Push(creature); CallAllFunctions(ServerEventBindings, key); } diff --git a/src/LuaEngine/hooks/SpellHooks.cpp b/src/LuaEngine/hooks/SpellHooks.cpp index 8c0801893e..0016757bba 100644 --- a/src/LuaEngine/hooks/SpellHooks.cpp +++ b/src/LuaEngine/hooks/SpellHooks.cpp @@ -19,7 +19,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!SpellEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE #define START_HOOK_WITH_RETVAL(EVENT, ENTRY, RETVAL) \ if (!ALEConfig::GetInstance().IsALEEnabled())\ @@ -27,7 +27,7 @@ using namespace Hooks; auto key = EntryKey(EVENT, ENTRY);\ if (!SpellEventBindings->HasBindingsFor(key))\ return RETVAL;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnSpellCastCancel(Unit* caster, Spell* spell, SpellInfo const* spellInfo, bool bySelf) { diff --git a/src/LuaEngine/hooks/VehicleHooks.cpp b/src/LuaEngine/hooks/VehicleHooks.cpp index f03a9657f9..b1319d27bf 100644 --- a/src/LuaEngine/hooks/VehicleHooks.cpp +++ b/src/LuaEngine/hooks/VehicleHooks.cpp @@ -18,7 +18,7 @@ using namespace Hooks; auto key = EventKey(EVENT);\ if (!VehicleEventBindings->HasBindingsFor(key))\ return;\ - LOCK_ALE + LOCK_ALE_STATE void ALE::OnInstall(Vehicle* vehicle) { diff --git a/src/LuaEngine/methods/GlobalMethods.h b/src/LuaEngine/methods/GlobalMethods.h index cebb7bc6d6..2102036e0f 100644 --- a/src/LuaEngine/methods/GlobalMethods.h +++ b/src/LuaEngine/methods/GlobalMethods.h @@ -146,8 +146,16 @@ namespace LuaGlobalFunctions */ int GetStateMap(lua_State* L) { - // Until AC supports multistate, this will always return nil - ALE::Push(L); + ALE* E = ALE::GetALE(L); + if (E->GetStateMapId() == ALE_GLOBAL_STATE) + { + ALE::Push(L); + return 1; + } + + // Get the map object and push it + Map* map = sMapMgr->FindMap(E->GetStateMapId(), 0); + ALE::Push(L, map); return 1; } @@ -158,8 +166,13 @@ namespace LuaGlobalFunctions */ int GetStateMapId(lua_State* L) { - // Until AC supports multistate, this will always return -1 - ALE::Push(L, -1); + ALE* E = ALE::GetALE(L); + if (E->GetStateMapId() == ALE_GLOBAL_STATE) + { + ALE::Push(L, -1); + return 1; + } + ALE::Push(L, (int32)E->GetStateMapId()); return 1; } @@ -1445,7 +1458,9 @@ namespace LuaGlobalFunctions return 0; } - ALE::GALE->queryProcessor.AddCallback(db.AsyncQuery(query).WithCallback([L, funcRef](QueryResult result) + ALE* sALE = ALE::GetALE(L); + + sALE->queryProcessor.AddCallback(db.AsyncQuery(query).WithCallback([L, funcRef, sALE](QueryResult result) { ALEQuery* eq = result ? new ALEQuery(result) : nullptr; @@ -1458,7 +1473,7 @@ namespace LuaGlobalFunctions ALE::Push(L, eq); // Call function - ALE::GALE->ExecuteCall(1, 0); + sALE->ExecuteCall(1, 0); luaL_unref(L, LUA_REGISTRYINDEX, funcRef); })); @@ -2699,7 +2714,8 @@ namespace LuaGlobalFunctions int funcRef = luaL_ref(L, LUA_REGISTRYINDEX); if (funcRef >= 0) { - ALE::GALE->httpManager.PushRequest(new HttpWorkItem(funcRef, httpVerb, url, body, bodyContentType, headers)); + ALE* sALE = ALE::GetALE(L); + sALE->httpManager.PushRequest(new HttpWorkItem(funcRef, sALE, httpVerb, url, body, bodyContentType, headers)); } else { From e03ee54ec78e119157e1c17913fc59dfed0c4921 Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Thu, 19 Mar 2026 04:17:37 +0100 Subject: [PATCH 02/12] Add instance state separation --- src/ALE_SC.cpp | 10 +++++----- src/LuaEngine/ALEInstanceAI.cpp | 14 +++++++------- src/LuaEngine/LuaEngine.cpp | 19 +++++++++++-------- src/LuaEngine/LuaEngine.h | 25 +++++++++++++++---------- src/LuaEngine/methods/GlobalMethods.h | 4 ++-- 5 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/ALE_SC.cpp b/src/ALE_SC.cpp index 57a4e7474d..c34f630518 100644 --- a/src/ALE_SC.cpp +++ b/src/ALE_SC.cpp @@ -288,8 +288,8 @@ class ALE_AllMapScript : public AllMapScript { if (ALEConfig::GetInstance().IsMultistateEnabled()) { - if (!ALE::GetMapState(map->GetId())) - ALE::CreateMapState(map->GetId()); + if (!ALE::GetMapState(map->GetId(), map->GetInstanceId())) + ALE::CreateMapState(map->GetId(), map->GetInstanceId()); } ALE::GetMapStateOrGlobal(map->GetId())->OnCreate(map); } @@ -297,8 +297,8 @@ class ALE_AllMapScript : public AllMapScript void OnDestroyMap(Map* map) override { ALE::GetMapStateOrGlobal(map->GetId())->OnDestroy(map); - if (ALEConfig::GetInstance().IsMultistateEnabled() && !map->Instanceable()) - ALE::DestroyMapState(map->GetId()); + if (ALEConfig::GetInstance().IsMultistateEnabled()) + ALE::DestroyMapState(map->GetId(), map->GetInstanceId()); } void OnPlayerEnterAll(Map* map, Player* player) override @@ -1113,7 +1113,7 @@ class ALE_WorldObjectScript : public WorldObjectScript { if (ALEConfig::GetInstance().IsMultistateEnabled()) { - ALE** stateSlot = ALE::GetMapStateSlot(map->GetId()); + ALE** stateSlot = ALE::GetMapStateSlot(map->GetId(), map->GetInstanceId()); object->ALEEvents = new ALEEventProcessor(stateSlot, object); } else diff --git a/src/LuaEngine/ALEInstanceAI.cpp b/src/LuaEngine/ALEInstanceAI.cpp index 252f8d5037..93a206a1ea 100644 --- a/src/LuaEngine/ALEInstanceAI.cpp +++ b/src/LuaEngine/ALEInstanceAI.cpp @@ -12,7 +12,7 @@ void ALEInstanceAI::Initialize() { LOCK_ALE; - ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); ASSERT(!sALE->HasInstanceData(instance)); @@ -27,7 +27,7 @@ void ALEInstanceAI::Initialize() void ALEInstanceAI::Load(const char* data) { LOCK_ALE; - ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); // If we get passed NULL (i.e. `Reload` was called) then use // the last known save data (or maybe just an empty string). @@ -110,7 +110,7 @@ void ALEInstanceAI::Load(const char* data) const char* ALEInstanceAI::Save() const { LOCK_ALE; - ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); lua_State* L = sALE->L; // Stack: (empty) @@ -149,7 +149,7 @@ const char* ALEInstanceAI::Save() const uint32 ALEInstanceAI::GetData(uint32 key) const { LOCK_ALE; - ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); lua_State* L = sALE->L; // Stack: (empty) @@ -172,7 +172,7 @@ uint32 ALEInstanceAI::GetData(uint32 key) const void ALEInstanceAI::SetData(uint32 key, uint32 value) { LOCK_ALE; - ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); lua_State* L = sALE->L; // Stack: (empty) @@ -193,7 +193,7 @@ void ALEInstanceAI::SetData(uint32 key, uint32 value) uint64 ALEInstanceAI::GetData64(uint32 key) const { LOCK_ALE; - ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); lua_State* L = sALE->L; // Stack: (empty) @@ -216,7 +216,7 @@ uint64 ALEInstanceAI::GetData64(uint32 key) const void ALEInstanceAI::SetData64(uint32 key, uint64 value) { LOCK_ALE; - ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId()); + ALE* sALE = ALE::GetMapStateOrGlobal(instance->GetId(), instance->GetInstanceId()); lua_State* L = sALE->L; // Stack: (empty) diff --git a/src/LuaEngine/LuaEngine.cpp b/src/LuaEngine/LuaEngine.cpp index be7345a17a..ba5d960b8c 100644 --- a/src/LuaEngine/LuaEngine.cpp +++ b/src/LuaEngine/LuaEngine.cpp @@ -53,7 +53,7 @@ ALE::LockType ALE::lock; std::unique_ptr ALE::fileWatcher; // Multistate handling -std::map ALE::g_states; +std::map ALE::g_states; std::shared_mutex ALE::g_states_mutex; // Global bytecode cache that survives ALE reloads @@ -123,26 +123,28 @@ void ALE::Uninitialize() initialized = false; } -ALE** ALE::CreateMapState(uint32 mapId) +ALE** ALE::CreateMapState(uint32 mapId, uint32 instanceId) { ALE** slotPtr; + uint64 key = ((uint64)mapId << 32) | instanceId; { std::unique_lock lock(g_states_mutex); - ASSERT(g_states.find(mapId) == g_states.end()); - auto& slot = g_states[mapId]; + ASSERT(g_states.find(key) == g_states.end()); + auto& slot = g_states[key]; slot = nullptr; slotPtr = &slot; - slot = new ALE(slotPtr, mapId); + slot = new ALE(slotPtr, mapId, instanceId); } (*slotPtr)->RunScripts(); return slotPtr; } -void ALE::DestroyMapState(uint32 mapId) +void ALE::DestroyMapState(uint32 mapId, uint32 instanceId) { std::unique_lock lock(g_states_mutex); - auto it = g_states.find(mapId); + uint64 key = ((uint64)mapId << 32) | instanceId; + auto it = g_states.find(key); if (it != g_states.end()) { delete it->second; @@ -230,7 +232,7 @@ void ALE::_ReloadALE() reload = false; } -ALE::ALE(ALE** _selfPtr, uint32 mapId) : +ALE::ALE(ALE** _selfPtr, uint32 mapId, uint32 instanceId) : event_level(0), push_counter(0), @@ -241,6 +243,7 @@ queryProcessor(), selfPtr(_selfPtr), stateMapId(mapId), +stateInstanceId(instanceId), ServerEventBindings(NULL), PlayerEventBindings(NULL), diff --git a/src/LuaEngine/LuaEngine.h b/src/LuaEngine/LuaEngine.h index f57f9e3bb5..ea8839a37e 100644 --- a/src/LuaEngine/LuaEngine.h +++ b/src/LuaEngine/LuaEngine.h @@ -124,6 +124,7 @@ class ALE_GAME_API ALE LockType& GetStateLock() { return stateLock; } uint32 GetStateMapId() const { return stateMapId; } + uint32 GetStateInstanceId() const { return stateInstanceId; } ALE** GetSelfPtr() { return selfPtr ? selfPtr : &ALE::GALE; } static void RunScriptsOnAllMapStates() @@ -136,6 +137,7 @@ class ALE_GAME_API ALE private: LockType stateLock; uint32 stateMapId; + uint32 stateInstanceId; static bool reload; static bool initialized; @@ -153,7 +155,7 @@ class ALE_GAME_API ALE static std::string lua_requirecpath; // Per-map states. std::map used for pointer stability on insert/erase. - static std::map g_states; + static std::map g_states; static std::shared_mutex g_states_mutex; // A counter for lua event stacks that occur (see event_level). @@ -176,7 +178,7 @@ class ALE_GAME_API ALE ALE** selfPtr; - ALE(ALE** selfPtr = nullptr, uint32 mapId = ALE_GLOBAL_STATE); + ALE(ALE** selfPtr = nullptr, uint32 mapId = ALE_GLOBAL_STATE, uint32 instanceId = 0); ~ALE(); // Prevent copy @@ -293,28 +295,31 @@ class ALE_GAME_API ALE static LockType& GetLock() { return lock; }; static bool IsInitialized() { return initialized; } - static ALE* GetMapState(uint32 mapId) + static ALE* GetMapState(uint32 mapId, uint32 instanceId = 0) { std::shared_lock lock(g_states_mutex); - auto it = g_states.find(mapId); + uint64 key = ((uint64)mapId << 32) | instanceId; + auto it = g_states.find(key); return it != g_states.end() ? it->second : nullptr; } - static ALE* GetMapStateOrGlobal(uint32 mapId) + static ALE* GetMapStateOrGlobal(uint32 mapId, uint32 instanceId = 0) { std::shared_lock lock(g_states_mutex); - auto it = g_states.find(mapId); + uint64 key = ((uint64)mapId << 32) | instanceId; + auto it = g_states.find(key); return it != g_states.end() ? it->second : GALE; } - static ALE** CreateMapState(uint32 mapId); - static void DestroyMapState(uint32 mapId); + static ALE** CreateMapState(uint32 mapId, uint32 instanceId = 0); + static void DestroyMapState(uint32 mapId, uint32 instanceId = 0); // Returns a stable pointer-to-pointer for the map state slot, for use by ALEEventProcessor. - static ALE** GetMapStateSlot(uint32 mapId) + static ALE** GetMapStateSlot(uint32 mapId, uint32 instanceId = 0) { std::shared_lock lock(g_states_mutex); - auto it = g_states.find(mapId); + uint64 key = ((uint64)mapId << 32) | instanceId; + auto it = g_states.find(key); ASSERT(it != g_states.end()); return &it->second; } diff --git a/src/LuaEngine/methods/GlobalMethods.h b/src/LuaEngine/methods/GlobalMethods.h index 2102036e0f..7c382bc646 100644 --- a/src/LuaEngine/methods/GlobalMethods.h +++ b/src/LuaEngine/methods/GlobalMethods.h @@ -183,8 +183,8 @@ namespace LuaGlobalFunctions */ int GetStateInstanceId(lua_State* L) { - // Until AC supports multistate, this will always return 0 - ALE::Push(L, 0); + ALE* E = ALE::GetALE(L); + ALE::Push(L, E->GetStateInstanceId()); return 1; } From 5160252036de615ea9315ecc4a71fdfa3306b7f8 Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Thu, 19 Mar 2026 05:57:09 +0100 Subject: [PATCH 03/12] Fix state-wise timed events --- src/LuaEngine/ALEEventMgr.cpp | 29 +++++++++++----------- src/LuaEngine/ALEEventMgr.h | 7 +++--- src/LuaEngine/hooks/ServerHooks.cpp | 4 +-- src/LuaEngine/methods/GlobalMethods.h | 3 ++- src/LuaEngine/methods/WorldObjectMethods.h | 4 ++- 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/LuaEngine/ALEEventMgr.cpp b/src/LuaEngine/ALEEventMgr.cpp index 498aad77b9..d9d3ffd5f8 100644 --- a/src/LuaEngine/ALEEventMgr.cpp +++ b/src/LuaEngine/ALEEventMgr.cpp @@ -27,10 +27,15 @@ ALEEventProcessor::ALEEventProcessor(ALE** _E, WorldObject* _obj) : m_time(0), o ALEEventProcessor::~ALEEventProcessor() { // can be called from multiple threads + if (*E) { ALE::Guard guard((*E)->GetStateLock()); RemoveEvents_internal(); } + else + { + RemoveEvents_internal(); + } if (obj && ALE::IsInitialized() && *E && (*E)->eventMgr) { @@ -57,8 +62,10 @@ void ALEEventProcessor::Update(uint32 diff) if (!remove) AddEvent(luaEvent); // Reschedule before calling incase RemoveEvents used - // Call the timed event - (*E)->OnTimedEvent(luaEvent->funcRef, delay, luaEvent->repeats ? luaEvent->repeats-- : luaEvent->repeats, obj); + // Call the timed event using the event's own state slot + ALE** slot = luaEvent->stateSlot; + if (slot && *slot && (*slot)->HasLuaState()) + (*slot)->OnTimedEvent(luaEvent->funcRef, delay, luaEvent->repeats ? luaEvent->repeats-- : luaEvent->repeats, obj); if (!remove) continue; @@ -79,13 +86,6 @@ void ALEEventProcessor::SetStates(LuaEventState state) void ALEEventProcessor::RemoveEvents_internal() { - //if (!final) - //{ - // for (EventList::iterator it = eventList.begin(); it != eventList.end(); ++it) - // it->second->to_Abort = true; - // return; - //} - for (EventList::iterator it = eventList.begin(); it != eventList.end(); ++it) RemoveEvent(it->second); @@ -108,18 +108,19 @@ void ALEEventProcessor::AddEvent(LuaEvent* luaEvent) eventMap[luaEvent->funcRef] = luaEvent; } -void ALEEventProcessor::AddEvent(int funcRef, uint32 min, uint32 max, uint32 repeats) +void ALEEventProcessor::AddEvent(int funcRef, uint32 min, uint32 max, uint32 repeats, ALE** stateSlot) { - AddEvent(new LuaEvent(funcRef, min, max, repeats)); + AddEvent(new LuaEvent(funcRef, min, max, repeats, stateSlot)); } void ALEEventProcessor::RemoveEvent(LuaEvent* luaEvent) { - // Unreference if should and if ALE was not yet uninitialized and if the lua state still exists - if (luaEvent->state != LUAEVENT_STATE_ERASE && ALE::IsInitialized() && (*E)->HasLuaState()) + // Unreference using the event's own state slot + ALE** slot = luaEvent->stateSlot; + if (luaEvent->state != LUAEVENT_STATE_ERASE && ALE::IsInitialized() && slot && *slot && (*slot)->HasLuaState()) { // Free lua function ref - luaL_unref((*E)->L, LUA_REGISTRYINDEX, luaEvent->funcRef); + luaL_unref((*slot)->L, LUA_REGISTRYINDEX, luaEvent->funcRef); } delete luaEvent; } diff --git a/src/LuaEngine/ALEEventMgr.h b/src/LuaEngine/ALEEventMgr.h index 5302ecead2..a4e2c73638 100644 --- a/src/LuaEngine/ALEEventMgr.h +++ b/src/LuaEngine/ALEEventMgr.h @@ -28,8 +28,8 @@ enum LuaEventState struct LuaEvent { - LuaEvent(int _funcRef, uint32 _min, uint32 _max, uint32 _repeats) : - min(_min), max(_max), delay(0), repeats(_repeats), funcRef(_funcRef), state(LUAEVENT_STATE_RUN) + LuaEvent(int _funcRef, uint32 _min, uint32 _max, uint32 _repeats, ALE** _stateSlot) : + min(_min), max(_max), delay(0), repeats(_repeats), funcRef(_funcRef), state(LUAEVENT_STATE_RUN), stateSlot(_stateSlot) { } @@ -50,6 +50,7 @@ struct LuaEvent uint32 repeats; // Amount of repeats to make, 0 for infinite int funcRef; // Lua function reference ID, also used as event ID LuaEventState state; // State for next call + ALE** stateSlot; }; class ALEEventProcessor @@ -68,7 +69,7 @@ class ALEEventProcessor void SetStates(LuaEventState state); // set the event to be removed when executing void SetState(int eventId, LuaEventState state); - void AddEvent(int funcRef, uint32 min, uint32 max, uint32 repeats); + void AddEvent(int funcRef, uint32 min, uint32 max, uint32 repeats, ALE** stateSlot); EventMap eventMap; private: diff --git a/src/LuaEngine/hooks/ServerHooks.cpp b/src/LuaEngine/hooks/ServerHooks.cpp index 0534cb0c95..2dd7f4daf0 100644 --- a/src/LuaEngine/hooks/ServerHooks.cpp +++ b/src/LuaEngine/hooks/ServerHooks.cpp @@ -339,9 +339,9 @@ void ALE::OnPlayerLeave(Map* map, Player* player) void ALE::OnUpdate(Map* map, uint32 diff) { + eventMgr->globalProcessor->Update(diff); + START_HOOK_MAP(MAP_EVENT_ON_UPDATE); - // enable this for multithread - // eventMgr->globalProcessor->Update(diff); Push(map); Push(diff); CallAllFunctions(ServerEventBindings, key); diff --git a/src/LuaEngine/methods/GlobalMethods.h b/src/LuaEngine/methods/GlobalMethods.h index 7c382bc646..f92ee700aa 100644 --- a/src/LuaEngine/methods/GlobalMethods.h +++ b/src/LuaEngine/methods/GlobalMethods.h @@ -1747,7 +1747,8 @@ namespace LuaGlobalFunctions int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) { - ALE::GetALE(L)->eventMgr->globalProcessor->AddEvent(functionRef, min, max, repeats); + ALE* callingE = ALE::GetALE(L); + callingE->eventMgr->globalProcessor->AddEvent(functionRef, min, max, repeats, callingE->GetSelfPtr()); ALE::Push(L, functionRef); } return 1; diff --git a/src/LuaEngine/methods/WorldObjectMethods.h b/src/LuaEngine/methods/WorldObjectMethods.h index a92a435b01..7595c62bad 100644 --- a/src/LuaEngine/methods/WorldObjectMethods.h +++ b/src/LuaEngine/methods/WorldObjectMethods.h @@ -780,7 +780,9 @@ namespace LuaWorldObject int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) { - obj->ALEEvents->AddEvent(functionRef, min, max, repeats); + ALE* callingE = ALE::GetALE(L); + ALE** stateSlot = callingE->GetSelfPtr(); + obj->ALEEvents->AddEvent(functionRef, min, max, repeats, stateSlot); ALE::Push(L, functionRef); } return 1; From 3006d5286ea798f6bf4656f6976f47036ada7039 Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Thu, 19 Mar 2026 07:01:27 +0100 Subject: [PATCH 04/12] Satisfy GitHub CI's -Wreorder --- src/LuaEngine/LuaEngine.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/LuaEngine/LuaEngine.cpp b/src/LuaEngine/LuaEngine.cpp index ba5d960b8c..add035618a 100644 --- a/src/LuaEngine/LuaEngine.cpp +++ b/src/LuaEngine/LuaEngine.cpp @@ -233,18 +233,17 @@ void ALE::_ReloadALE() } ALE::ALE(ALE** _selfPtr, uint32 mapId, uint32 instanceId) : +stateMapId(mapId), +stateInstanceId(instanceId), event_level(0), push_counter(0), +selfPtr(_selfPtr), L(NULL), eventMgr(NULL), httpManager(), queryProcessor(), -selfPtr(_selfPtr), -stateMapId(mapId), -stateInstanceId(instanceId), - ServerEventBindings(NULL), PlayerEventBindings(NULL), GuildEventBindings(NULL), From 05d7cf598f133a25d9352f27e631af6a54a5b884 Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Sun, 22 Mar 2026 02:45:22 +0100 Subject: [PATCH 05/12] Refactor config and map loading functionality to more closely match upstream Eluna Based on parts of https://github.com/azerothcore/mod-ale/pull/249 Co-Authored-By: iThorgrim <125808072+iThorgrim@users.noreply.github.com> --- conf/mod_ale.conf.dist | 24 +++++++------ src/ALE_SC.cpp | 6 ++-- src/LuaEngine/ALEConfig.cpp | 67 ++++++++++++++++++++++++++++++++++++- src/LuaEngine/ALEConfig.h | 13 +++++-- src/LuaEngine/LuaEngine.cpp | 17 ++++++++-- src/LuaEngine/LuaEngine.h | 2 +- 6 files changed, 109 insertions(+), 20 deletions(-) diff --git a/conf/mod_ale.conf.dist b/conf/mod_ale.conf.dist index 6a45a537eb..db4c8cbc40 100644 --- a/conf/mod_ale.conf.dist +++ b/conf/mod_ale.conf.dist @@ -8,6 +8,12 @@ # Default: true - (enabled) # false - (disabled) # +# ALE.CompatibilityMode +# Description: Toggles ALE between compatibility mode (single-threaded) or multistate mode. +# Compatibility mode limits the engine to a single global Lua state. +# Default: true - (enabled) +# false - (disabled) +# # ALE.TraceBack # Description: Sets whether to use debug.traceback function on a lua error or not. # Notice that you can redefine the function. @@ -19,6 +25,12 @@ # The path can be relative or absolute. # Default: "lua_scripts" # +# ALE.OnlyOnMaps +# Description: When ALE is enabled, a state will only be created for a list of specified maps. +# This only works in multistate mode. +# Default: "" - (enabled on all maps) +# "0,1,2,..." - (enabled on specific maps only) +# # ALE.PlayerAnnounceReload # Description: Enable or disable whether the reload announcement is sent to players (Lowest security level). # Default: false - (disabled) @@ -59,26 +71,18 @@ # Cache is cleared only when files are modified or server restarts. # Default: true - (enabled) # false - (disabled) -# -# ALE.Multistate -# Description: Enable or disable per-map Lua state isolation. -# When enabled, each map runs its own Lua state concurrently on its map thread, -# allowing true parallel execution across maps. Scripts can use GetStateMapId() -# to self-select which map state they load into. -# When disabled, all maps share the global Lua state (original behavior). -# Default: false - (disabled, single global state) -# true - (enabled, per-map states) ALE.Enabled = true +ALE.CompatibilityMode = true ALE.TraceBack = false ALE.ScriptPath = "lua_scripts" +ALE.OnlyOnMaps = "" ALE.PlayerAnnounceReload = false ALE.RequirePaths = "" ALE.RequireCPaths = "" ALE.AutoReload = false ALE.AutoReloadInterval = 1 ALE.BytecodeCache = true -ALE.Multistate = false ################################################################################################### # LOGGING SYSTEM SETTINGS diff --git a/src/ALE_SC.cpp b/src/ALE_SC.cpp index c34f630518..47471c1673 100644 --- a/src/ALE_SC.cpp +++ b/src/ALE_SC.cpp @@ -286,7 +286,7 @@ class ALE_AllMapScript : public AllMapScript void OnCreateMap(Map* map) override { - if (ALEConfig::GetInstance().IsMultistateEnabled()) + if (!ALEConfig::GetInstance().IsCompatibilityModeEnabled()) { if (!ALE::GetMapState(map->GetId(), map->GetInstanceId())) ALE::CreateMapState(map->GetId(), map->GetInstanceId()); @@ -297,7 +297,7 @@ class ALE_AllMapScript : public AllMapScript void OnDestroyMap(Map* map) override { ALE::GetMapStateOrGlobal(map->GetId())->OnDestroy(map); - if (ALEConfig::GetInstance().IsMultistateEnabled()) + if (!ALEConfig::GetInstance().IsCompatibilityModeEnabled()) ALE::DestroyMapState(map->GetId(), map->GetInstanceId()); } @@ -1111,7 +1111,7 @@ class ALE_WorldObjectScript : public WorldObjectScript { if (!object->ALEEvents) { - if (ALEConfig::GetInstance().IsMultistateEnabled()) + if (!ALEConfig::GetInstance().IsCompatibilityModeEnabled()) { ALE** stateSlot = ALE::GetMapStateSlot(map->GetId(), map->GetInstanceId()); object->ALEEvents = new ALEEventProcessor(stateSlot, object); diff --git a/src/LuaEngine/ALEConfig.cpp b/src/LuaEngine/ALEConfig.cpp index efd32fcb57..d800fcf557 100644 --- a/src/LuaEngine/ALEConfig.cpp +++ b/src/LuaEngine/ALEConfig.cpp @@ -1,4 +1,8 @@ #include "ALEConfig.h" +#include "ALEUtility.h" +#include +#include +#include ALEConfig& ALEConfig::GetInstance() { @@ -13,6 +17,7 @@ ALEConfig::ALEConfig() : ConfigValueCache(ALEConfigValues::CONF void ALEConfig::Initialize(bool reload) { ConfigValueCache::Initialize(reload); + TokenizeAllowedMaps(); } void ALEConfig::BuildConfigCache() @@ -21,11 +26,71 @@ void ALEConfig::BuildConfigCache() SetConfigValue(ALEConfigValues::TRACEBACK_ENABLED, "ALE.TraceBack", "false"); SetConfigValue(ALEConfigValues::AUTORELOAD_ENABLED, "ALE.AutoReload", "false"); SetConfigValue(ALEConfigValues::BYTECODE_CACHE_ENABLED, "ALE.BytecodeCache", "false"); - SetConfigValue(ALEConfigValues::MULTISTATE_ENABLED, "ALE.Multistate", "false"); + SetConfigValue(ALEConfigValues::COMPATIBILITY_MODE, "ALE.CompatibilityMode", "true"); SetConfigValue(ALEConfigValues::SCRIPT_PATH, "ALE.ScriptPath", "lua_scripts"); SetConfigValue(ALEConfigValues::REQUIRE_PATH, "ALE.RequirePaths", ""); SetConfigValue(ALEConfigValues::REQUIRE_CPATH, "ALE.RequireCPaths", ""); + SetConfigValue(ALEConfigValues::ONLY_ON_MAPS, "ALE.OnlyOnMaps", ""); SetConfigValue(ALEConfigValues::AUTORELOAD_INTERVAL, "ALE.AutoReloadInterval", 1); } + +bool ALEConfig::ShouldMapLoadALE(uint32 mapId) const +{ + if (m_allowedMaps.empty()) + return true; + return m_allowedMaps.find(mapId) != m_allowedMaps.end(); +} + +bool ALEConfig::ShouldMapLoadALEByFolderName(const std::string& folderName, uint32 mapId) const +{ + std::string digits; + for (char c : folderName) + { + if (std::isdigit(static_cast(c))) + digits += c; + else + break; + } + + if (digits.empty()) + return true; + + try + { + uint32 folderMapId = std::stoul(digits); + return folderMapId == mapId; + } + catch (std::exception&) + { + return true; + } +} + +void ALEConfig::TokenizeAllowedMaps() +{ + m_allowedMaps.clear(); + + std::istringstream maps(static_cast(GetConfigValue(ALEConfigValues::ONLY_ON_MAPS))); + std::string mapIdStr; + while (std::getline(maps, mapIdStr, ',')) + { + mapIdStr.erase(std::remove_if(mapIdStr.begin(), mapIdStr.end(), [](char c) { + return std::isspace(static_cast(c)); + }), mapIdStr.end()); + + if (mapIdStr.empty()) + continue; + + try + { + uint32 mapId = std::stoul(mapIdStr); + m_allowedMaps.emplace(mapId); + } + catch (std::exception&) + { + ALE_LOG_ERROR("[ALEConfig]: Invalid map ID in ALE.OnlyOnMaps: '{}'", mapIdStr); + } + } +} diff --git a/src/LuaEngine/ALEConfig.h b/src/LuaEngine/ALEConfig.h index 3495ac85fd..11c961355d 100644 --- a/src/LuaEngine/ALEConfig.h +++ b/src/LuaEngine/ALEConfig.h @@ -2,6 +2,7 @@ #define ALE_CONFIG_HPP #include "ConfigValueCache.h" +#include enum class ALEConfigValues : uint32 { @@ -10,12 +11,13 @@ enum class ALEConfigValues : uint32 TRACEBACK_ENABLED, AUTORELOAD_ENABLED, BYTECODE_CACHE_ENABLED, - MULTISTATE_ENABLED, + COMPATIBILITY_MODE, // String SCRIPT_PATH, REQUIRE_PATH, REQUIRE_CPATH, + ONLY_ON_MAPS, // Number AUTORELOAD_INTERVAL, @@ -34,7 +36,7 @@ class ALEConfig final : public ConfigValueCache bool IsTraceBackEnabled() const { return GetConfigValue(ALEConfigValues::TRACEBACK_ENABLED); } bool IsAutoReloadEnabled() const { return GetConfigValue(ALEConfigValues::AUTORELOAD_ENABLED); } bool IsByteCodeCacheEnabled() const { return GetConfigValue(ALEConfigValues::BYTECODE_CACHE_ENABLED); } - bool IsMultistateEnabled() const { return GetConfigValue(ALEConfigValues::MULTISTATE_ENABLED); } + bool IsCompatibilityModeEnabled() const { return GetConfigValue(ALEConfigValues::COMPATIBILITY_MODE); } std::string_view GetScriptPath() const { return GetConfigValue(ALEConfigValues::SCRIPT_PATH); } std::string_view GetRequirePath() const { return GetConfigValue(ALEConfigValues::REQUIRE_PATH); } @@ -42,6 +44,9 @@ class ALEConfig final : public ConfigValueCache uint32 GetAutoReloadInterval() const { return GetConfigValue(ALEConfigValues::AUTORELOAD_INTERVAL); } + bool ShouldMapLoadALE(uint32 mapId) const; + bool ShouldMapLoadALEByFolderName(const std::string& folderName, uint32 mapId) const; + protected: void BuildConfigCache() override; @@ -50,6 +55,10 @@ class ALEConfig final : public ConfigValueCache ~ALEConfig() = default; ALEConfig(const ALEConfig&) = delete; ALEConfig& operator=(const ALEConfig&) = delete; + + void TokenizeAllowedMaps(); + + std::unordered_set m_allowedMaps; }; #endif // ALE_CONFIG_H \ No newline at end of file diff --git a/src/LuaEngine/LuaEngine.cpp b/src/LuaEngine/LuaEngine.cpp index add035618a..96ae136088 100644 --- a/src/LuaEngine/LuaEngine.cpp +++ b/src/LuaEngine/LuaEngine.cpp @@ -125,6 +125,9 @@ void ALE::Uninitialize() ALE** ALE::CreateMapState(uint32 mapId, uint32 instanceId) { + if (!ALEConfig::GetInstance().ShouldMapLoadALE(mapId)) + return nullptr; + ALE** slotPtr; uint64 key = ((uint64)mapId << 32) | instanceId; { @@ -174,7 +177,7 @@ void ALE::LoadScriptPaths() lua_requirepath.clear(); lua_requirecpath.clear(); - GetScripts(lua_folderpath); + GetScripts(lua_folderpath, 0); // append our custom require paths and cpaths if the config variables are not empty if (!lua_path_extra.empty()) @@ -667,7 +670,7 @@ int ALE::LoadCompiledScript(lua_State* L, const std::string& filepath) } // Finds lua script files from given path (including subdirectories) and pushes them to scripts -void ALE::GetScripts(std::string path) +void ALE::GetScripts(std::string path, uint32 mapId) { ALE_LOG_DEBUG("[ALE]: GetScripts from path `{}`", path); @@ -703,7 +706,10 @@ void ALE::GetScripts(std::string path) // load subfolder if (boost::filesystem::is_directory(dir_iter->status())) { - GetScripts(fullpath); + std::string folderName = dir_iter->path().filename().generic_string(); + if (!ALEConfig::GetInstance().ShouldMapLoadALEByFolderName(folderName, mapId)) + continue; + GetScripts(fullpath, mapId); continue; } @@ -753,6 +759,11 @@ void ALE::RunScripts() int modules = lua_gettop(L); for (ScriptList::iterator it = scripts.begin(); it != scripts.end(); ++it) { + // Filter by map-prefixed subdirectory + std::string folderName = boost::filesystem::path(it->modulepath).filename().generic_string(); + if (!ALEConfig::GetInstance().ShouldMapLoadALEByFolderName(folderName, stateMapId)) + continue; + // Check that no duplicate names exist if (loaded.find(it->filename) != loaded.end()) { diff --git a/src/LuaEngine/LuaEngine.h b/src/LuaEngine/LuaEngine.h index ea8839a37e..8729ae3ec9 100644 --- a/src/LuaEngine/LuaEngine.h +++ b/src/LuaEngine/LuaEngine.h @@ -195,7 +195,7 @@ class ALE_GAME_API ALE // This is called on world update to reload ALE static void _ReloadALE(); static void LoadScriptPaths(); - static void GetScripts(std::string path); + static void GetScripts(std::string path, uint32 mapId = 0); static void AddScriptPath(std::string filename, const std::string& fullpath); static int LoadCompiledScript(lua_State* L, const std::string& filepath); static std::time_t GetFileModTime(const std::string& filepath); From 9c4051ac3154a8dd07263ce690070243d264ce7d Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Sun, 22 Mar 2026 03:54:29 +0100 Subject: [PATCH 06/12] Fix missing passing of instance ID to instanced maps --- src/ALE_SC.cpp | 236 +++++++++++++++++++------------------- src/LuaEngine/LuaEngine.h | 11 +- 2 files changed, 128 insertions(+), 119 deletions(-) diff --git a/src/ALE_SC.cpp b/src/ALE_SC.cpp index 47471c1673..b4c6f9e595 100644 --- a/src/ALE_SC.cpp +++ b/src/ALE_SC.cpp @@ -33,7 +33,7 @@ class ALE_AllCreatureScript : public AllCreatureScript // Creature bool CanCreatureGossipHello(Player* player, Creature* creature) override { - if (ALE::GetMapStateOrGlobal(creature->GetMapId())->OnGossipHello(player, creature)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnGossipHello(player, creature)) return true; return false; @@ -41,7 +41,7 @@ class ALE_AllCreatureScript : public AllCreatureScript bool CanCreatureGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) override { - if (ALE::GetMapStateOrGlobal(creature->GetMapId())->OnGossipSelect(player, creature, sender, action)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnGossipSelect(player, creature, sender, action)) return true; return false; @@ -49,7 +49,7 @@ class ALE_AllCreatureScript : public AllCreatureScript bool CanCreatureGossipSelectCode(Player* player, Creature* creature, uint32 sender, uint32 action, const char* code) override { - if (ALE::GetMapStateOrGlobal(creature->GetMapId())->OnGossipSelectCode(player, creature, sender, action, code)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnGossipSelectCode(player, creature, sender, action, code)) return true; return false; @@ -57,7 +57,7 @@ class ALE_AllCreatureScript : public AllCreatureScript void OnCreatureAddWorld(Creature* creature) override { - ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId()); sALE->OnAddToWorld(creature); sALE->OnAllCreatureAddToWorld(creature); @@ -67,14 +67,14 @@ class ALE_AllCreatureScript : public AllCreatureScript void OnCreatureRemoveWorld(Creature* creature) override { - ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId()); sALE->OnRemoveFromWorld(creature); sALE->OnAllCreatureRemoveFromWorld(creature); } bool CanCreatureQuestAccept(Player* player, Creature* creature, Quest const* quest) override { - ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId()); sALE->OnPlayerQuestAccept(player, quest); sALE->OnQuestAccept(player, creature, quest); return false; @@ -82,7 +82,7 @@ class ALE_AllCreatureScript : public AllCreatureScript bool CanCreatureQuestReward(Player* player, Creature* creature, Quest const* quest, uint32 opt) override { - if (ALE::GetMapStateOrGlobal(creature->GetMapId())->OnQuestReward(player, creature, quest, opt)) + if (ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnQuestReward(player, creature, quest, opt)) { ClearGossipMenuFor(player); return true; @@ -93,7 +93,7 @@ class ALE_AllCreatureScript : public AllCreatureScript CreatureAI* GetCreatureAI(Creature* creature) const override { - if (CreatureAI* luaAI = ALE::GetMapStateOrGlobal(creature->GetMapId())->GetAI(creature)) + if (CreatureAI* luaAI = ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->GetAI(creature)) return luaAI; return nullptr; @@ -101,12 +101,12 @@ class ALE_AllCreatureScript : public AllCreatureScript void OnCreatureSelectLevel(const CreatureTemplate* cinfo, Creature* creature) override { - ALE::GetMapStateOrGlobal(creature->GetMapId())->OnAllCreatureSelectLevel(cinfo, creature); + ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnAllCreatureSelectLevel(cinfo, creature); } void OnBeforeCreatureSelectLevel(const CreatureTemplate* cinfo, Creature* creature, uint8& level) override { - ALE::GetMapStateOrGlobal(creature->GetMapId())->OnAllCreatureBeforeSelectLevel(cinfo, creature, level); + ALE::GetMapStateOrGlobal(creature->GetMapId(), creature->GetInstanceId())->OnAllCreatureBeforeSelectLevel(cinfo, creature, level); } }; @@ -117,22 +117,22 @@ class ALE_AllGameObjectScript : public AllGameObjectScript void OnGameObjectAddWorld(GameObject* go) override { - ALE::GetMapStateOrGlobal(go->GetMapId())->OnAddToWorld(go); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnAddToWorld(go); } void OnGameObjectRemoveWorld(GameObject* go) override { - ALE::GetMapStateOrGlobal(go->GetMapId())->OnRemoveFromWorld(go); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnRemoveFromWorld(go); } void OnGameObjectUpdate(GameObject* go, uint32 diff) override { - ALE::GetMapStateOrGlobal(go->GetMapId())->UpdateAI(go, diff); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->UpdateAI(go, diff); } bool CanGameObjectGossipHello(Player* player, GameObject* go) override { - ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId()); if (sALE->OnGossipHello(player, go)) return true; @@ -144,27 +144,27 @@ class ALE_AllGameObjectScript : public AllGameObjectScript void OnGameObjectDamaged(GameObject* go, Player* player) override { - ALE::GetMapStateOrGlobal(go->GetMapId())->OnDamaged(go, player); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnDamaged(go, player); } void OnGameObjectDestroyed(GameObject* go, Player* player) override { - ALE::GetMapStateOrGlobal(go->GetMapId())->OnDestroyed(go, player); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnDestroyed(go, player); } void OnGameObjectLootStateChanged(GameObject* go, uint32 state, Unit* /*unit*/) override { - ALE::GetMapStateOrGlobal(go->GetMapId())->OnLootStateChanged(go, state); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnLootStateChanged(go, state); } void OnGameObjectStateChanged(GameObject* go, uint32 state) override { - ALE::GetMapStateOrGlobal(go->GetMapId())->OnGameObjectStateChanged(go, state); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnGameObjectStateChanged(go, state); } bool CanGameObjectQuestAccept(Player* player, GameObject* go, Quest const* quest) override { - ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId()); sALE->OnPlayerQuestAccept(player, quest); sALE->OnQuestAccept(player, go, quest); return false; @@ -172,7 +172,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript bool CanGameObjectGossipSelect(Player* player, GameObject* go, uint32 sender, uint32 action) override { - if (ALE::GetMapStateOrGlobal(go->GetMapId())->OnGossipSelect(player, go, sender, action)) + if (ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnGossipSelect(player, go, sender, action)) return true; return false; @@ -180,7 +180,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript bool CanGameObjectGossipSelectCode(Player* player, GameObject* go, uint32 sender, uint32 action, const char* code) override { - if (ALE::GetMapStateOrGlobal(go->GetMapId())->OnGossipSelectCode(player, go, sender, action, code)) + if (ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnGossipSelectCode(player, go, sender, action, code)) return true; return false; @@ -188,7 +188,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript bool CanGameObjectQuestReward(Player* player, GameObject* go, Quest const* quest, uint32 opt) override { - ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId()); if (sALE->OnQuestAccept(player, go, quest)) { sALE->OnPlayerQuestAccept(player, quest); @@ -203,7 +203,7 @@ class ALE_AllGameObjectScript : public AllGameObjectScript GameObjectAI* GetGameObjectAI(GameObject* go) const override { - ALE::GetMapStateOrGlobal(go->GetMapId())->OnSpawn(go); + ALE::GetMapStateOrGlobal(go->GetMapId(), go->GetInstanceId())->OnSpawn(go); return nullptr; } }; @@ -215,7 +215,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemQuestAccept(Player* player, Item* item, Quest const* quest) override { - ALE* sALE = ALE::GetMapStateOrGlobal(player->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId()); if (sALE->OnQuestAccept(player, item, quest)) { sALE->OnPlayerQuestAccept(player, quest); @@ -227,7 +227,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemUse(Player* player, Item* item, SpellCastTargets const& targets) override { - if (!ALE::GetMapStateOrGlobal(player->GetMapId())->OnUse(player, item, targets)) + if (!ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnUse(player, item, targets)) return true; return false; @@ -235,7 +235,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemExpire(Player* player, ItemTemplate const* proto) override { - if (ALE::GetMapStateOrGlobal(player->GetMapId())->OnExpire(player, proto)) + if (ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnExpire(player, proto)) return false; return true; @@ -243,7 +243,7 @@ class ALE_AllItemScript : public AllItemScript bool CanItemRemove(Player* player, Item* item) override { - if (ALE::GetMapStateOrGlobal(player->GetMapId())->OnRemove(player, item)) + if (ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnRemove(player, item)) return false; return true; @@ -251,12 +251,12 @@ class ALE_AllItemScript : public AllItemScript void OnItemGossipSelect(Player* player, Item* item, uint32 sender, uint32 action) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->HandleGossipSelectOption(player, item, sender, action, ""); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->HandleGossipSelectOption(player, item, sender, action, ""); } void OnItemGossipSelectCode(Player* player, Item* item, uint32 sender, uint32 action, const char* code) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->HandleGossipSelectOption(player, item, sender, action, code); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->HandleGossipSelectOption(player, item, sender, action, code); } }; @@ -275,13 +275,18 @@ class ALE_AllMapScript : public AllMapScript void OnBeforeCreateInstanceScript(InstanceMap* instanceMap, InstanceScript** instanceData, bool /*load*/, std::string /*data*/, uint32 /*completedEncounterMask*/) override { + if (!ALEConfig::GetInstance().IsCompatibilityModeEnabled()) + { + if (!ALE::GetMapState(instanceMap->GetId(), instanceMap->GetInstanceId())) + ALE::CreateMapState(instanceMap->GetId(), instanceMap->GetInstanceId()); + } if (instanceData) - *instanceData = ALE::GetMapStateOrGlobal(instanceMap->GetId())->GetInstanceData(instanceMap); + *instanceData = ALE::GetMapStateOrGlobal(instanceMap->GetId(), instanceMap->GetInstanceId())->GetInstanceData(instanceMap); } void OnDestroyInstance(MapInstanced* /*mapInstanced*/, Map* map) override { - ALE::GetMapStateOrGlobal(map->GetId())->FreeInstanceId(map->GetInstanceId()); + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->FreeInstanceId(map->GetInstanceId()); } void OnCreateMap(Map* map) override @@ -291,29 +296,29 @@ class ALE_AllMapScript : public AllMapScript if (!ALE::GetMapState(map->GetId(), map->GetInstanceId())) ALE::CreateMapState(map->GetId(), map->GetInstanceId()); } - ALE::GetMapStateOrGlobal(map->GetId())->OnCreate(map); + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->OnCreate(map); } void OnDestroyMap(Map* map) override { - ALE::GetMapStateOrGlobal(map->GetId())->OnDestroy(map); + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->OnDestroy(map); if (!ALEConfig::GetInstance().IsCompatibilityModeEnabled()) ALE::DestroyMapState(map->GetId(), map->GetInstanceId()); } void OnPlayerEnterAll(Map* map, Player* player) override { - ALE::GetMapStateOrGlobal(map->GetId())->OnPlayerEnter(map, player); + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->OnPlayerEnter(map, player); } void OnPlayerLeaveAll(Map* map, Player* player) override { - ALE::GetMapStateOrGlobal(map->GetId())->OnPlayerLeave(map, player); + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->OnPlayerLeave(map, player); } void OnMapUpdate(Map* map, uint32 diff) override { - ALE::GetMapStateOrGlobal(map->GetId())->OnUpdate(map, diff); + ALE::GetMapStateOrGlobal(map->GetId(), map->GetInstanceId())->OnUpdate(map, diff); } }; @@ -360,22 +365,22 @@ class ALE_BGScript : public BGScript void OnBattlegroundStart(Battleground* bg) override { - ALE::GetMapStateOrGlobal(bg->GetMapId())->OnBGStart(bg, bg->GetBgTypeID(), bg->GetInstanceID()); + ALE::GetMapStateOrGlobal(bg->GetMapId(), bg->GetInstanceID())->OnBGStart(bg, bg->GetBgTypeID(), bg->GetInstanceID()); } void OnBattlegroundEnd(Battleground* bg, TeamId winnerTeam) override { - ALE::GetMapStateOrGlobal(bg->GetMapId())->OnBGEnd(bg, bg->GetBgTypeID(), bg->GetInstanceID(), winnerTeam); + ALE::GetMapStateOrGlobal(bg->GetMapId(), bg->GetInstanceID())->OnBGEnd(bg, bg->GetBgTypeID(), bg->GetInstanceID(), winnerTeam); } void OnBattlegroundDestroy(Battleground* bg) override { - ALE::GetMapStateOrGlobal(bg->GetMapId())->OnBGDestroy(bg, bg->GetBgTypeID(), bg->GetInstanceID()); + ALE::GetMapStateOrGlobal(bg->GetMapId(), bg->GetInstanceID())->OnBGDestroy(bg, bg->GetBgTypeID(), bg->GetInstanceID()); } void OnBattlegroundCreate(Battleground* bg) override { - ALE::GetMapStateOrGlobal(bg->GetMapId())->OnBGCreate(bg, bg->GetBgTypeID(), bg->GetInstanceID()); + ALE::GetMapStateOrGlobal(bg->GetMapId(), bg->GetInstanceID())->OnBGCreate(bg, bg->GetBgTypeID(), bg->GetInstanceID()); } }; @@ -411,7 +416,7 @@ class ALE_ALEScript : public ALEScript // AreaTriger bool CanAreaTrigger(Player* player, AreaTrigger const* trigger) override { - if (ALE::GetMapStateOrGlobal(player->GetMapId())->OnAreaTrigger(player, trigger)) + if (ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnAreaTrigger(player, trigger)) return true; return false; @@ -563,7 +568,7 @@ class ALE_LootScript : public LootScript void OnLootMoney(Player* player, uint32 gold) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnLootMoney(player, gold); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnLootMoney(player, gold); } }; @@ -576,7 +581,7 @@ class ALE_MiscScript : public MiscScript void GetDialogStatus(Player* player, Object* questgiver) override { - ALE* sALE = ALE::GetMapStateOrGlobal(player->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId()); if (questgiver->GetTypeId() == TYPEID_GAMEOBJECT) sALE->GetDialogStatus(player, questgiver->ToGameObject()); else if (questgiver->GetTypeId() == TYPEID_UNIT) @@ -593,7 +598,7 @@ class ALE_PetScript : public PetScript void OnPetAddToWorld(Pet* pet) override { - ALE::GetMapStateOrGlobal(pet->GetMapId())->OnPetAddedToWorld(pet->GetOwner(), pet); + ALE::GetMapStateOrGlobal(pet->GetMapId(), pet->GetInstanceId())->OnPetAddedToWorld(pet->GetOwner(), pet); } }; @@ -665,7 +670,7 @@ class ALE_PlayerScript : public PlayerScript void OnPlayerResurrect(Player* player, float /*restore_percent*/, bool /*applySickness*/) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnResurrect(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnResurrect(player); } bool OnPlayerCanUseChat(Player* player, uint32 type, uint32 lang, std::string& msg) override @@ -713,134 +718,134 @@ class ALE_PlayerScript : public PlayerScript void OnPlayerLootItem(Player* player, Item* item, uint32 count, ObjectGuid lootguid) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnLootItem(player, item, count, lootguid); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnLootItem(player, item, count, lootguid); } void OnPlayerLearnTalents(Player* player, uint32 talentId, uint32 talentRank, uint32 spellid) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnLearnTalents(player, talentId, talentRank, spellid); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnLearnTalents(player, talentId, talentRank, spellid); } bool OnPlayerCanUseItem(Player* player, ItemTemplate const* proto, InventoryResult& result) override { - result = ALE::GetMapStateOrGlobal(player->GetMapId())->OnCanUseItem(player, proto->ItemId); + result = ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCanUseItem(player, proto->ItemId); return result != EQUIP_ERR_OK ? false : true; } void OnPlayerEquip(Player* player, Item* it, uint8 bag, uint8 slot, bool /*update*/) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnEquip(player, it, bag, slot); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnEquip(player, it, bag, slot); } void OnPlayerEnterCombat(Player* player, Unit* enemy) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerEnterCombat(player, enemy); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerEnterCombat(player, enemy); } void OnPlayerLeaveCombat(Player* player) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerLeaveCombat(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerLeaveCombat(player); } bool OnPlayerCanRepopAtGraveyard(Player* player) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnRepop(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnRepop(player); return true; } void OnPlayerQuestAbandon(Player* player, uint32 questId) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnQuestAbandon(player, questId); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnQuestAbandon(player, questId); } void OnPlayerMapChanged(Player* player) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnMapChanged(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnMapChanged(player); } void OnPlayerGossipSelect(Player* player, uint32 menu_id, uint32 sender, uint32 action) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->HandleGossipSelectOption(player, menu_id, sender, action, ""); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->HandleGossipSelectOption(player, menu_id, sender, action, ""); } void OnPlayerGossipSelectCode(Player* player, uint32 menu_id, uint32 sender, uint32 action, const char* code) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->HandleGossipSelectOption(player, menu_id, sender, action, code); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->HandleGossipSelectOption(player, menu_id, sender, action, code); } void OnPlayerPVPKill(Player* killer, Player* killed) override { - ALE::GetMapStateOrGlobal(killer->GetMapId())->OnPVPKill(killer, killed); + ALE::GetMapStateOrGlobal(killer->GetMapId(), killer->GetInstanceId())->OnPVPKill(killer, killed); } void OnPlayerCreatureKill(Player* killer, Creature* killed) override { - ALE::GetMapStateOrGlobal(killer->GetMapId())->OnCreatureKill(killer, killed); + ALE::GetMapStateOrGlobal(killer->GetMapId(), killer->GetInstanceId())->OnCreatureKill(killer, killed); } void OnPlayerKilledByCreature(Creature* killer, Player* killed) override { - ALE::GetMapStateOrGlobal(killer->GetMapId())->OnPlayerKilledByCreature(killer, killed); + ALE::GetMapStateOrGlobal(killer->GetMapId(), killer->GetInstanceId())->OnPlayerKilledByCreature(killer, killed); } void OnPlayerLevelChanged(Player* player, uint8 oldLevel) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnLevelChanged(player, oldLevel); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnLevelChanged(player, oldLevel); } void OnPlayerFreeTalentPointsChanged(Player* player, uint32 points) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnFreeTalentPointsChanged(player, points); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnFreeTalentPointsChanged(player, points); } void OnPlayerTalentsReset(Player* player, bool noCost) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnTalentsReset(player, noCost); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnTalentsReset(player, noCost); } void OnPlayerMoneyChanged(Player* player, int32& amount) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnMoneyChanged(player, amount); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnMoneyChanged(player, amount); } void OnPlayerGiveXP(Player* player, uint32& amount, Unit* victim, uint8 xpSource) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnGiveXP(player, amount, victim, xpSource); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnGiveXP(player, amount, victim, xpSource); } bool OnPlayerReputationChange(Player* player, uint32 factionID, int32& standing, bool incremental) override { - return ALE::GetMapStateOrGlobal(player->GetMapId())->OnReputationChange(player, factionID, standing, incremental); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnReputationChange(player, factionID, standing, incremental); } void OnPlayerDuelRequest(Player* target, Player* challenger) override { - ALE::GetMapStateOrGlobal(challenger->GetMapId())->OnDuelRequest(target, challenger); + ALE::GetMapStateOrGlobal(challenger->GetMapId(), challenger->GetInstanceId())->OnDuelRequest(target, challenger); } void OnPlayerDuelStart(Player* player1, Player* player2) override { - ALE::GetMapStateOrGlobal(player1->GetMapId())->OnDuelStart(player1, player2); + ALE::GetMapStateOrGlobal(player1->GetMapId(), player1->GetInstanceId())->OnDuelStart(player1, player2); } void OnPlayerDuelEnd(Player* winner, Player* loser, DuelCompleteType type) override { - ALE::GetMapStateOrGlobal(winner->GetMapId())->OnDuelEnd(winner, loser, type); + ALE::GetMapStateOrGlobal(winner->GetMapId(), winner->GetInstanceId())->OnDuelEnd(winner, loser, type); } void OnPlayerEmote(Player* player, uint32 emote) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnEmote(player, emote); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnEmote(player, emote); } void OnPlayerTextEmote(Player* player, uint32 textEmote, uint32 emoteNum, ObjectGuid guid) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnTextEmote(player, textEmote, emoteNum, guid); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnTextEmote(player, textEmote, emoteNum, guid); } void OnPlayerSpellCast(Player* player, Spell* spell, bool skipCheck) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerSpellCast(player, spell, skipCheck); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerSpellCast(player, spell, skipCheck); } void OnPlayerLogin(Player* player) override @@ -860,7 +865,7 @@ class ALE_PlayerScript : public PlayerScript void OnPlayerSave(Player* player) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnSave(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnSave(player); } void OnPlayerDelete(ObjectGuid guid, uint32 /*accountId*/) override @@ -870,17 +875,17 @@ class ALE_PlayerScript : public PlayerScript void OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnBindToInstance(player, difficulty, mapid, permanent); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnBindToInstance(player, difficulty, mapid, permanent); } void OnPlayerUpdateArea(Player* player, uint32 oldArea, uint32 newArea) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnUpdateArea(player, oldArea, newArea); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnUpdateArea(player, oldArea, newArea); } void OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnUpdateZone(player, newZone, newArea); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnUpdateZone(player, newZone, newArea); } void OnPlayerFirstLogin(Player* player) override @@ -890,97 +895,97 @@ class ALE_PlayerScript : public PlayerScript void OnPlayerLearnSpell(Player* player, uint32 spellId) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnLearnSpell(player, spellId); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnLearnSpell(player, spellId); } void OnPlayerAchievementComplete(Player* player, AchievementEntry const* achievement) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnAchiComplete(player, achievement); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnAchiComplete(player, achievement); } void OnPlayerFfaPvpStateUpdate(Player* player, bool IsFlaggedForFfaPvp) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnFfaPvpStateUpdate(player, IsFlaggedForFfaPvp); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnFfaPvpStateUpdate(player, IsFlaggedForFfaPvp); } bool OnPlayerCanInitTrade(Player* player, Player* target) override { - return ALE::GetMapStateOrGlobal(player->GetMapId())->OnCanInitTrade(player, target); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCanInitTrade(player, target); } bool OnPlayerCanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 cod, Item* item) override { - return ALE::GetMapStateOrGlobal(player->GetMapId())->OnCanSendMail(player, receiverGuid, mailbox, subject, body, money, cod, item); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCanSendMail(player, receiverGuid, mailbox, subject, body, money, cod, item); } bool OnPlayerCanJoinLfg(Player* player, uint8 roles, lfg::LfgDungeonSet& dungeons, const std::string& comment) override { - return ALE::GetMapStateOrGlobal(player->GetMapId())->OnCanJoinLfg(player, roles, dungeons, comment); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCanJoinLfg(player, roles, dungeons, comment); } void OnPlayerQuestRewardItem(Player* player, Item* item, uint32 count) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnQuestRewardItem(player, item, count); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnQuestRewardItem(player, item, count); } void OnPlayerGroupRollRewardItem(Player* player, Item* item, uint32 count, RollVote voteType, Roll* roll) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnGroupRollRewardItem(player, item, count, voteType, roll); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnGroupRollRewardItem(player, item, count, voteType, roll); } void OnPlayerCreateItem(Player* player, Item* item, uint32 count) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnCreateItem(player, item, count); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCreateItem(player, item, count); } void OnPlayerStoreNewItem(Player* player, Item* item, uint32 count) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnStoreNewItem(player, item, count); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnStoreNewItem(player, item, count); } void OnPlayerCompleteQuest(Player* player, Quest const* quest) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerCompleteQuest(player, quest); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerCompleteQuest(player, quest); } bool OnPlayerCanGroupInvite(Player* player, std::string& memberName) override { - return ALE::GetMapStateOrGlobal(player->GetMapId())->OnCanGroupInvite(player, memberName); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCanGroupInvite(player, memberName); } void OnPlayerBattlegroundDesertion(Player* player, const BattlegroundDesertionType type) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnBattlegroundDesertion(player, type); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnBattlegroundDesertion(player, type); } void OnPlayerCreatureKilledByPet(Player* player, Creature* killed) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnCreatureKilledByPet(player, killed); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnCreatureKilledByPet(player, killed); } bool OnPlayerCanUpdateSkill(Player* player, uint32 skill_id) override { - return ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerCanUpdateSkill(player, skill_id); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerCanUpdateSkill(player, skill_id); } void OnPlayerBeforeUpdateSkill(Player* player, uint32 skill_id, uint32& value, uint32 max, uint32 step) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerBeforeUpdateSkill(player, skill_id, value, max, step); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerBeforeUpdateSkill(player, skill_id, value, max, step); } void OnPlayerUpdateSkill(Player* player, uint32 skill_id, uint32 value, uint32 max, uint32 step, uint32 new_value) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerUpdateSkill(player, skill_id, value, max, step, new_value); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerUpdateSkill(player, skill_id, value, max, step, new_value); } bool OnPlayerCanResurrect(Player* player) override { - return ALE::GetMapStateOrGlobal(player->GetMapId())->CanPlayerResurrect(player); + return ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->CanPlayerResurrect(player); } void OnPlayerReleasedGhost(Player* player) override { - ALE::GetMapStateOrGlobal(player->GetMapId())->OnPlayerReleasedGhost(player); + ALE::GetMapStateOrGlobal(player->GetMapId(), player->GetInstanceId())->OnPlayerReleasedGhost(player); } }; @@ -1023,32 +1028,32 @@ class ALE_SpellSC : public SpellSC void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, GameObject* gameObjTarget) override { - ALE::GetMapStateOrGlobal(caster->GetMapId())->OnDummyEffect(caster, spellID, effIndex, gameObjTarget); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnDummyEffect(caster, spellID, effIndex, gameObjTarget); } void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Creature* creatureTarget) override { - ALE::GetMapStateOrGlobal(caster->GetMapId())->OnDummyEffect(caster, spellID, effIndex, creatureTarget); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnDummyEffect(caster, spellID, effIndex, creatureTarget); } void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Item* itemTarget) override { - ALE::GetMapStateOrGlobal(caster->GetMapId())->OnDummyEffect(caster, spellID, effIndex, itemTarget); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnDummyEffect(caster, spellID, effIndex, itemTarget); } void OnSpellCastCancel(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool bySelf) override { - ALE::GetMapStateOrGlobal(caster->GetMapId())->OnSpellCastCancel(caster, spell, spellInfo, bySelf); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnSpellCastCancel(caster, spell, spellInfo, bySelf); } void OnSpellCast(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool skipCheck) override { - ALE::GetMapStateOrGlobal(caster->GetMapId())->OnSpellCast(caster, spell, spellInfo, skipCheck); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnSpellCast(caster, spell, spellInfo, skipCheck); } void OnSpellPrepare(Spell* spell, Unit* caster, SpellInfo const* spellInfo) override { - ALE::GetMapStateOrGlobal(caster->GetMapId())->OnSpellPrepare(caster, spell, spellInfo); + ALE::GetMapStateOrGlobal(caster->GetMapId(), caster->GetInstanceId())->OnSpellPrepare(caster, spell, spellInfo); } }; @@ -1059,27 +1064,27 @@ class ALE_VehicleScript : public VehicleScript void OnInstall(Vehicle* veh) override { - ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId())->OnInstall(veh); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId(), veh->GetBase()->GetInstanceId())->OnInstall(veh); } void OnUninstall(Vehicle* veh) override { - ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId())->OnUninstall(veh); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId(), veh->GetBase()->GetInstanceId())->OnUninstall(veh); } void OnInstallAccessory(Vehicle* veh, Creature* accessory) override { - ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId())->OnInstallAccessory(veh, accessory); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId(), veh->GetBase()->GetInstanceId())->OnInstallAccessory(veh, accessory); } void OnAddPassenger(Vehicle* veh, Unit* passenger, int8 seatId) override { - ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId())->OnAddPassenger(veh, passenger, seatId); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId(), veh->GetBase()->GetInstanceId())->OnAddPassenger(veh, passenger, seatId); } void OnRemovePassenger(Vehicle* veh, Unit* passenger) override { - ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId())->OnRemovePassenger(veh, passenger); + ALE::GetMapStateOrGlobal(veh->GetBase()->GetMapId(), veh->GetBase()->GetInstanceId())->OnRemovePassenger(veh, passenger); } }; @@ -1125,7 +1130,8 @@ class ALE_WorldObjectScript : public WorldObjectScript void OnWorldObjectUpdate(WorldObject* object, uint32 diff) override { - object->ALEEvents->Update(diff); + if (object->ALEEvents) + object->ALEEvents->Update(diff); } }; @@ -1247,7 +1253,7 @@ class ALE_UnitScript : public UnitScript void OnAuraApply(Unit* unit, Aura* aura) override { if (!unit || !aura) return; - ALE* sALE = ALE::GetMapStateOrGlobal(unit->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(unit->GetMapId(), unit->GetInstanceId()); if (unit->IsPlayer()) sALE->OnPlayerAuraApply(unit->ToPlayer(), aura); @@ -1262,7 +1268,7 @@ class ALE_UnitScript : public UnitScript void OnAuraRemove(Unit* unit, AuraApplication* aurApp, AuraRemoveMode mode) override { if (!unit || !aurApp->GetBase()) return; - ALE* sALE = ALE::GetMapStateOrGlobal(unit->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(unit->GetMapId(), unit->GetInstanceId()); if (unit->IsPlayer()) sALE->OnPlayerAuraRemove(unit->ToPlayer(), aurApp->GetBase(), mode); @@ -1277,7 +1283,7 @@ class ALE_UnitScript : public UnitScript void OnHeal(Unit* healer, Unit* receiver, uint32& gain) override { if (!receiver || !healer) return; - ALE* sALE = ALE::GetMapStateOrGlobal(healer->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(healer->GetMapId(), healer->GetInstanceId()); if (healer->IsPlayer()) sALE->OnPlayerHeal(healer->ToPlayer(), receiver, gain); @@ -1292,7 +1298,7 @@ class ALE_UnitScript : public UnitScript void OnDamage(Unit* attacker, Unit* receiver, uint32& damage) override { if (!attacker || !receiver) return; - ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId(), attacker->GetInstanceId()); if (attacker->IsPlayer()) sALE->OnPlayerDamage(attacker->ToPlayer(), receiver, damage); @@ -1307,7 +1313,7 @@ class ALE_UnitScript : public UnitScript void ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage, SpellInfo const* spellInfo) override { if (!target || !attacker) return; - ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId(), attacker->GetInstanceId()); if (attacker->IsPlayer()) sALE->OnPlayerModifyPeriodicDamageAurasTick(attacker->ToPlayer(), target, damage, spellInfo); @@ -1322,7 +1328,7 @@ class ALE_UnitScript : public UnitScript void ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage) override { if (!target || !attacker) return; - ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId(), attacker->GetInstanceId()); if (attacker->IsPlayer()) sALE->OnPlayerModifyMeleeDamage(attacker->ToPlayer(), target, damage); @@ -1337,7 +1343,7 @@ class ALE_UnitScript : public UnitScript void ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage, SpellInfo const* spellInfo) override { if (!target || !attacker) return; - ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(attacker->GetMapId(), attacker->GetInstanceId()); if (attacker->IsPlayer()) sALE->OnPlayerModifySpellDamageTaken(attacker->ToPlayer(), target, damage, spellInfo); @@ -1352,7 +1358,7 @@ class ALE_UnitScript : public UnitScript void ModifyHealReceived(Unit* target, Unit* healer, uint32& heal, SpellInfo const* spellInfo) override { if (!target || !healer) return; - ALE* sALE = ALE::GetMapStateOrGlobal(healer->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(healer->GetMapId(), healer->GetInstanceId()); if (healer->IsPlayer()) sALE->OnPlayerModifyHealReceived(healer->ToPlayer(), target, heal, spellInfo); @@ -1367,7 +1373,7 @@ class ALE_UnitScript : public UnitScript uint32 DealDamage(Unit* AttackerUnit, Unit* pVictim, uint32 damage, DamageEffectType damagetype) override { if (!AttackerUnit || !pVictim) return damage; - ALE* sALE = ALE::GetMapStateOrGlobal(AttackerUnit->GetMapId()); + ALE* sALE = ALE::GetMapStateOrGlobal(AttackerUnit->GetMapId(), AttackerUnit->GetInstanceId()); if (AttackerUnit->IsPlayer()) return sALE->OnPlayerDealDamage(AttackerUnit->ToPlayer(), pVictim, damage, damagetype); diff --git a/src/LuaEngine/LuaEngine.h b/src/LuaEngine/LuaEngine.h index 8729ae3ec9..e738b60202 100644 --- a/src/LuaEngine/LuaEngine.h +++ b/src/LuaEngine/LuaEngine.h @@ -317,11 +317,14 @@ class ALE_GAME_API ALE // Returns a stable pointer-to-pointer for the map state slot, for use by ALEEventProcessor. static ALE** GetMapStateSlot(uint32 mapId, uint32 instanceId = 0) { - std::shared_lock lock(g_states_mutex); uint64 key = ((uint64)mapId << 32) | instanceId; - auto it = g_states.find(key); - ASSERT(it != g_states.end()); - return &it->second; + { + std::shared_lock lock(g_states_mutex); + auto it = g_states.find(key); + if (it != g_states.end()) + return &it->second; + } + return CreateMapState(mapId, instanceId); } // Never returns nullptr From 922302c025e60aece97d5b3beae8d1e8f1fc9073 Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Sun, 29 Mar 2026 01:41:41 +0100 Subject: [PATCH 07/12] Fix concurrent executions on compat mode --- src/LuaEngine/LuaEngine.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/LuaEngine/LuaEngine.h b/src/LuaEngine/LuaEngine.h index e738b60202..0a0d8d390f 100644 --- a/src/LuaEngine/LuaEngine.h +++ b/src/LuaEngine/LuaEngine.h @@ -106,7 +106,9 @@ struct LuaScript #define ALE_STATE_PTR "ALE State Ptr" #define LOCK_ALE ALE::Guard __guard(ALE::GetLock()) -#define LOCK_ALE_STATE ALE::Guard __guard(this->GetStateLock()) +#define LOCK_ALE_STATE \ + ALE::Guard __ale_guard(ALEConfig::GetInstance().IsCompatibilityModeEnabled() ? ALE::GetLock() : ALE::GetNoopLock()); \ + Guard __ale_state_guard(this->GetStateLock()) #define ALE_GLOBAL_STATE (uint32)(-1) #define ALE_GAME_API AC_GAME_API @@ -123,6 +125,7 @@ class ALE_GAME_API ALE const std::string& GetRequireCPath() const { return lua_requirecpath; } LockType& GetStateLock() { return stateLock; } + static LockType& GetNoopLock() { thread_local LockType noop; return noop; } uint32 GetStateMapId() const { return stateMapId; } uint32 GetStateInstanceId() const { return stateInstanceId; } ALE** GetSelfPtr() { return selfPtr ? selfPtr : &ALE::GALE; } From 21cd9be441f0be33208e60e0c648bc5c1941c2fc Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Mon, 30 Mar 2026 23:25:04 +0200 Subject: [PATCH 08/12] Separate methods per state --- src/LuaEngine/ALETemplate.h | 81 ++++++++++++++++++++++++++++++++-- src/LuaEngine/LuaFunctions.cpp | 72 +++++++++++++++--------------- 2 files changed, 113 insertions(+), 40 deletions(-) diff --git a/src/LuaEngine/ALETemplate.h b/src/LuaEngine/ALETemplate.h index de0d89bcaa..dbe2f997f3 100644 --- a/src/LuaEngine/ALETemplate.h +++ b/src/LuaEngine/ALETemplate.h @@ -18,12 +18,32 @@ extern "C" #include "ALEUtility.h" #include "SharedDefines.h" +enum MethodRegisterState +{ + METHOD_REG_MAP = 0, + METHOD_REG_WORLD = 1, + METHOD_REG_ALL = 2 +}; + +struct ALEGlobalRegister +{ + const char* name; + int(*func)(lua_State*); + MethodRegisterState regState; + + ALEGlobalRegister(const char* name, int(*f)(lua_State*), MethodRegisterState state = METHOD_REG_ALL) + : name(name), func(f), regState(state) {} + + ALEGlobalRegister(const char* name, MethodRegisterState state = METHOD_REG_ALL) + : name(name), func(nullptr), regState(state) {} +}; + class ALEGlobal { public: static int thunk(lua_State* L) { - luaL_Reg* l = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + ALEGlobalRegister* l = static_cast(lua_touserdata(L, lua_upvalueindex(1))); int top = lua_gettop(L); int expected = l->func(L); int args = lua_gettop(L) - top; @@ -36,15 +56,38 @@ class ALEGlobal return expected; } - static void SetMethods(ALE* E, luaL_Reg* methodTable) + static int MethodWrongState(lua_State* L) + { + luaL_error(L, "attempt to call method '%s' that is not available in this state", lua_tostring(L, lua_upvalueindex(1))); + return 0; + } + + static void SetMethods(ALE* E, ALEGlobalRegister* methodTable) { ASSERT(E); ASSERT(methodTable); lua_pushglobaltable(E->L); - for (; methodTable && methodTable->name && methodTable->func; ++methodTable) + for (; methodTable && methodTable->name; ++methodTable) { + if (methodTable->regState != METHOD_REG_ALL) + { + bool isMapState = (E->GetStateMapId() != ALE_GLOBAL_STATE); + if ((!isMapState && methodTable->regState == METHOD_REG_MAP) || + (isMapState && methodTable->regState == METHOD_REG_WORLD)) + { + lua_pushstring(E->L, methodTable->name); + lua_pushstring(E->L, methodTable->name); + lua_pushcclosure(E->L, MethodWrongState, 1); + lua_rawset(E->L, -3); + continue; + } + } + + if (!methodTable->func) + continue; + lua_pushstring(E->L, methodTable->name); lua_pushlightuserdata(E->L, (void*)methodTable); lua_pushcclosure(E->L, thunk, 1); @@ -117,6 +160,13 @@ struct ALERegister { const char* name; int(*mfunc)(lua_State*, T*); + MethodRegisterState regState; + + ALERegister(const char* name, int(*func)(lua_State*, T*), MethodRegisterState state = METHOD_REG_ALL) + : name(name), mfunc(func), regState(state) {} + + ALERegister(const char* name, MethodRegisterState state = METHOD_REG_ALL) + : name(name), mfunc(nullptr), regState(state) {} }; template @@ -241,8 +291,25 @@ class ALETemplate lua_rawget(E->L, LUA_REGISTRYINDEX); ASSERT(lua_istable(E->L, -1)); - for (; methodTable && methodTable->name && methodTable->mfunc; ++methodTable) + for (; methodTable && methodTable->name; ++methodTable) { + if (methodTable->regState != METHOD_REG_ALL) + { + bool isMapState = (E->GetStateMapId() != ALE_GLOBAL_STATE); + if ((!isMapState && methodTable->regState == METHOD_REG_MAP) || + (isMapState && methodTable->regState == METHOD_REG_WORLD)) + { + lua_pushstring(E->L, methodTable->name); + lua_pushstring(E->L, methodTable->name); + lua_pushcclosure(E->L, MethodWrongState, 1); + lua_rawset(E->L, -3); + continue; + } + } + + if (!methodTable->mfunc) + continue; + lua_pushstring(E->L, methodTable->name); lua_pushlightuserdata(E->L, (void*)methodTable); lua_pushcclosure(E->L, CallMethod, 1); @@ -322,6 +389,12 @@ class ALETemplate return 0; } + static int MethodWrongState(lua_State* L) + { + luaL_error(L, "attempt to call method '%s' that is not available in this state", lua_tostring(L, lua_upvalueindex(1))); + return 0; + } + static int CallMethod(lua_State* L) { T* obj = ALE::CHECKOBJ(L, 1); // get self diff --git a/src/LuaEngine/LuaFunctions.cpp b/src/LuaEngine/LuaFunctions.cpp index 36cb209938..5e71fff65e 100644 --- a/src/LuaEngine/LuaFunctions.cpp +++ b/src/LuaEngine/LuaFunctions.cpp @@ -50,7 +50,7 @@ extern "C" #include "GemPropertiesEntryMethods.h" #include "SpellEntryMethods.h" -luaL_Reg GlobalMethods[] = +ALEGlobalRegister GlobalMethods[] = { // Hooks { "RegisterPacketEvent", &LuaGlobalFunctions::RegisterPacketEvent }, @@ -101,14 +101,14 @@ luaL_Reg GlobalMethods[] = { "GetRealmID", &LuaGlobalFunctions::GetRealmID }, { "GetCoreVersion", &LuaGlobalFunctions::GetCoreVersion }, { "GetCoreExpansion", &LuaGlobalFunctions::GetCoreExpansion }, - { "GetStateMap", &LuaGlobalFunctions::GetStateMap }, + { "GetStateMap", &LuaGlobalFunctions::GetStateMap, METHOD_REG_MAP }, // Map state method only in multistate { "GetStateMapId", &LuaGlobalFunctions::GetStateMapId }, { "GetStateInstanceId", &LuaGlobalFunctions::GetStateInstanceId }, { "GetQuest", &LuaGlobalFunctions::GetQuest }, - { "GetPlayerByGUID", &LuaGlobalFunctions::GetPlayerByGUID }, - { "GetPlayerByName", &LuaGlobalFunctions::GetPlayerByName }, + { "GetPlayerByGUID", &LuaGlobalFunctions::GetPlayerByGUID, METHOD_REG_WORLD }, // World state method only in multistate + { "GetPlayerByName", &LuaGlobalFunctions::GetPlayerByName, METHOD_REG_WORLD }, // World state method only in multistate { "GetGameTime", &LuaGlobalFunctions::GetGameTime }, - { "GetPlayersInWorld", &LuaGlobalFunctions::GetPlayersInWorld }, + { "GetPlayersInWorld", &LuaGlobalFunctions::GetPlayersInWorld, METHOD_REG_WORLD }, // World state method only in multistate { "GetGuildByName", &LuaGlobalFunctions::GetGuildByName }, { "GetGuildByLeaderGUID", &LuaGlobalFunctions::GetGuildByLeaderGUID }, { "GetPlayerCount", &LuaGlobalFunctions::GetPlayerCount }, @@ -130,7 +130,7 @@ luaL_Reg GlobalMethods[] = { "bit_or", &LuaGlobalFunctions::bit_or }, { "bit_and", &LuaGlobalFunctions::bit_and }, { "GetItemLink", &LuaGlobalFunctions::GetItemLink }, - { "GetMapById", &LuaGlobalFunctions::GetMapById }, + { "GetMapById", &LuaGlobalFunctions::GetMapById, METHOD_REG_WORLD }, // World state method only in multistate { "GetCurrTime", &LuaGlobalFunctions::GetCurrTime }, { "GetTimeDiff", &LuaGlobalFunctions::GetTimeDiff }, { "PrintInfo", &LuaGlobalFunctions::PrintInfo }, @@ -180,7 +180,7 @@ luaL_Reg GlobalMethods[] = { "StartGameEvent", &LuaGlobalFunctions::StartGameEvent }, { "StopGameEvent", &LuaGlobalFunctions::StopGameEvent }, { "HttpRequest", &LuaGlobalFunctions::HttpRequest }, - { "SetOwnerHalaa", &LuaGlobalFunctions::SetOwnerHalaa }, + { "SetOwnerHalaa", &LuaGlobalFunctions::SetOwnerHalaa, METHOD_REG_WORLD }, // World state method only in multistate { "LookupEntry", &LuaGlobalFunctions::LookupEntry }, { NULL, NULL } @@ -278,9 +278,9 @@ ALERegister WorldObjectMethods[] = { "SummonGameObject", &LuaWorldObject::SummonGameObject }, { "SpawnCreature", &LuaWorldObject::SpawnCreature }, { "SendPacket", &LuaWorldObject::SendPacket }, - { "RegisterEvent", &LuaWorldObject::RegisterEvent }, - { "RemoveEventById", &LuaWorldObject::RemoveEventById }, - { "RemoveEvents", &LuaWorldObject::RemoveEvents }, + { "RegisterEvent", &LuaWorldObject::RegisterEvent, METHOD_REG_MAP }, // Map state method only in multistate + { "RemoveEventById", &LuaWorldObject::RemoveEventById, METHOD_REG_MAP }, // Map state method only in multistate + { "RemoveEvents", &LuaWorldObject::RemoveEvents, METHOD_REG_MAP }, // Map state method only in multistate { "PlayMusic", &LuaWorldObject::PlayMusic }, { "PlayDirectSound", &LuaWorldObject::PlayDirectSound }, { "PlayDistanceSound", &LuaWorldObject::PlayDistanceSound }, @@ -813,8 +813,8 @@ ALERegister PlayerMethods[] = { "Mute", &LuaPlayer::Mute }, { "SummonPlayer", &LuaPlayer::SummonPlayer }, { "SaveToDB", &LuaPlayer::SaveToDB }, - { "GroupInvite", &LuaPlayer::GroupInvite }, - { "GroupCreate", &LuaPlayer::GroupCreate }, + { "GroupInvite", &LuaPlayer::GroupInvite, METHOD_REG_WORLD }, // World state method only in multistate + { "GroupCreate", &LuaPlayer::GroupCreate, METHOD_REG_WORLD }, // World state method only in multistate { "SendCinematicStart", &LuaPlayer::SendCinematicStart }, { "SendMovieStart", &LuaPlayer::SendMovieStart }, { "UpdatePlayerSetting", &LuaPlayer::UpdatePlayerSetting }, @@ -1149,7 +1149,7 @@ ALERegister QuestMethods[] = ALERegister GroupMethods[] = { // Getters - { "GetMembers", &LuaGroup::GetMembers }, + { "GetMembers", &LuaGroup::GetMembers, METHOD_REG_WORLD }, // World state method only in multistate { "GetLeaderGUID", &LuaGroup::GetLeaderGUID }, { "GetGUID", &LuaGroup::GetGUID }, { "GetMemberGroup", &LuaGroup::GetMemberGroup }, @@ -1158,16 +1158,16 @@ ALERegister GroupMethods[] = { "GetGroupType", &LuaGroup::GetGroupType }, // Setters - { "SetLeader", &LuaGroup::SetLeader }, - { "SetMembersGroup", &LuaGroup::SetMembersGroup }, - { "SetTargetIcon", &LuaGroup::SetTargetIcon }, - { "SetMemberFlag", &LuaGroup::SetMemberFlag }, + { "SetLeader", &LuaGroup::SetLeader, METHOD_REG_WORLD }, // World state method only in multistate + { "SetMembersGroup", &LuaGroup::SetMembersGroup, METHOD_REG_WORLD }, // World state method only in multistate + { "SetTargetIcon", &LuaGroup::SetTargetIcon, METHOD_REG_WORLD }, // World state method only in multistate + { "SetMemberFlag", &LuaGroup::SetMemberFlag, METHOD_REG_WORLD }, // World state method only in multistate // Boolean { "IsLeader", &LuaGroup::IsLeader }, - { "AddMember", &LuaGroup::AddMember }, - { "RemoveMember", &LuaGroup::RemoveMember }, - { "Disband", &LuaGroup::Disband }, + { "AddMember", &LuaGroup::AddMember, METHOD_REG_WORLD }, // World state method only in multistate + { "RemoveMember", &LuaGroup::RemoveMember, METHOD_REG_WORLD }, // World state method only in multistate + { "Disband", &LuaGroup::Disband, METHOD_REG_WORLD }, // World state method only in multistate { "IsFull", &LuaGroup::IsFull }, { "IsLFGGroup", &LuaGroup::IsLFGGroup }, { "IsRaidGroup", &LuaGroup::IsRaidGroup }, @@ -1181,7 +1181,7 @@ ALERegister GroupMethods[] = // Other { "SendPacket", &LuaGroup::SendPacket }, // {"ConvertToLFG", &LuaGroup::ConvertToLFG}, // :ConvertToLFG() - UNDOCUMENTED - Converts the group to an LFG group - { "ConvertToRaid", &LuaGroup::ConvertToRaid }, + { "ConvertToRaid", &LuaGroup::ConvertToRaid, METHOD_REG_WORLD }, // World state method only in multistate { NULL, NULL } }; @@ -1189,8 +1189,8 @@ ALERegister GroupMethods[] = ALERegister GuildMethods[] = { // Getters - { "GetMembers", &LuaGuild::GetMembers }, - { "GetLeader", &LuaGuild::GetLeader }, + { "GetMembers", &LuaGuild::GetMembers, METHOD_REG_WORLD }, // World state method only in multistate + { "GetLeader", &LuaGuild::GetLeader, METHOD_REG_WORLD }, // World state method only in multistate { "GetLeaderGUID", &LuaGuild::GetLeaderGUID }, { "GetId", &LuaGuild::GetId }, { "GetName", &LuaGuild::GetName }, @@ -1201,24 +1201,24 @@ ALERegister GuildMethods[] = { "GetTotalBankMoney", &LuaGuild::GetTotalBankMoney }, // Setters - { "SetBankTabText", &LuaGuild::SetBankTabText }, - { "SetMemberRank", &LuaGuild::SetMemberRank }, - { "SetLeader", &LuaGuild::SetLeader }, - { "SetName", &LuaGuild::SetName }, + { "SetBankTabText", &LuaGuild::SetBankTabText, METHOD_REG_WORLD }, // World state method only in multistate + { "SetMemberRank", &LuaGuild::SetMemberRank, METHOD_REG_WORLD }, // World state method only in multistate + { "SetLeader", &LuaGuild::SetLeader, METHOD_REG_WORLD }, // World state method only in multistate + { "SetName", &LuaGuild::SetName, METHOD_REG_WORLD }, // World state method only in multistate // Other { "SendPacket", &LuaGuild::SendPacket }, { "SendPacketToRanked", &LuaGuild::SendPacketToRanked }, - { "Disband", &LuaGuild::Disband }, - { "AddMember", &LuaGuild::AddMember }, - { "DeleteMember", &LuaGuild::DeleteMember }, + { "Disband", &LuaGuild::Disband, METHOD_REG_WORLD }, // World state method only in multistate + { "AddMember", &LuaGuild::AddMember, METHOD_REG_WORLD }, // World state method only in multistate + { "DeleteMember", &LuaGuild::DeleteMember, METHOD_REG_WORLD }, // World state method only in multistate { "SendMessage", &LuaGuild::SendMessage }, - { "UpdateMemberData", &LuaGuild::UpdateMemberData }, - { "MassInviteToEvent", &LuaGuild::MassInviteToEvent }, - { "SwapItems", &LuaGuild::SwapItems }, - { "SwapItemsWithInventory", &LuaGuild::SwapItemsWithInventory }, - { "ResetTimes", &LuaGuild::ResetTimes }, - { "ModifyBankMoney", &LuaGuild::ModifyBankMoney }, + { "UpdateMemberData", &LuaGuild::UpdateMemberData, METHOD_REG_WORLD }, // World state method only in multistate + { "MassInviteToEvent", &LuaGuild::MassInviteToEvent, METHOD_REG_WORLD }, // World state method only in multistate + { "SwapItems", &LuaGuild::SwapItems, METHOD_REG_WORLD }, // World state method only in multistate + { "SwapItemsWithInventory", &LuaGuild::SwapItemsWithInventory, METHOD_REG_WORLD }, // World state method only in multistate + { "ResetTimes", &LuaGuild::ResetTimes, METHOD_REG_WORLD }, // World state method only in multistate + { "ModifyBankMoney", &LuaGuild::ModifyBankMoney, METHOD_REG_WORLD }, // World state method only in multistate { NULL, NULL } }; From a00fd94269e1aa27ecbc72360e534a44c3b98523 Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Tue, 31 Mar 2026 02:15:34 +0200 Subject: [PATCH 09/12] fix IsCompatibilityMode() --- src/LuaEngine/methods/GlobalMethods.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/LuaEngine/methods/GlobalMethods.h b/src/LuaEngine/methods/GlobalMethods.h index f92ee700aa..fe0577c381 100644 --- a/src/LuaEngine/methods/GlobalMethods.h +++ b/src/LuaEngine/methods/GlobalMethods.h @@ -2433,8 +2433,7 @@ namespace LuaGlobalFunctions */ int IsCompatibilityMode(lua_State* L) { - // Until AC supports multistate, this will always return true - ALE::Push(L, true); + ALE::Push(L, ALEConfig::GetInstance().IsCompatibilityModeEnabled()); return 1; } From e2d6e185ad57de83105a23a6ef5dddfe42844148 Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Fri, 3 Apr 2026 03:38:06 +0200 Subject: [PATCH 10/12] Revert map registration limit of WorldObj event funcs --- src/LuaEngine/LuaFunctions.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LuaEngine/LuaFunctions.cpp b/src/LuaEngine/LuaFunctions.cpp index 5e71fff65e..ad3fff2837 100644 --- a/src/LuaEngine/LuaFunctions.cpp +++ b/src/LuaEngine/LuaFunctions.cpp @@ -278,9 +278,9 @@ ALERegister WorldObjectMethods[] = { "SummonGameObject", &LuaWorldObject::SummonGameObject }, { "SpawnCreature", &LuaWorldObject::SpawnCreature }, { "SendPacket", &LuaWorldObject::SendPacket }, - { "RegisterEvent", &LuaWorldObject::RegisterEvent, METHOD_REG_MAP }, // Map state method only in multistate - { "RemoveEventById", &LuaWorldObject::RemoveEventById, METHOD_REG_MAP }, // Map state method only in multistate - { "RemoveEvents", &LuaWorldObject::RemoveEvents, METHOD_REG_MAP }, // Map state method only in multistate + { "RegisterEvent", &LuaWorldObject::RegisterEvent }, + { "RemoveEventById", &LuaWorldObject::RemoveEventById }, + { "RemoveEvents", &LuaWorldObject::RemoveEvents }, { "PlayMusic", &LuaWorldObject::PlayMusic }, { "PlayDirectSound", &LuaWorldObject::PlayDirectSound }, { "PlayDistanceSound", &LuaWorldObject::PlayDistanceSound }, From a46552be1e115304e6466cbf4f2af0e8855b6514 Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Fri, 3 Apr 2026 03:47:05 +0200 Subject: [PATCH 11/12] Update documentation to mention state requirement --- src/LuaEngine/methods/GlobalMethods.h | 14 +++++++++++++ src/LuaEngine/methods/GroupMethods.h | 12 +++++++++++ src/LuaEngine/methods/GuildMethods.h | 30 +++++++++++++++++++++++++++ src/LuaEngine/methods/PlayerMethods.h | 4 ++++ 4 files changed, 60 insertions(+) diff --git a/src/LuaEngine/methods/GlobalMethods.h b/src/LuaEngine/methods/GlobalMethods.h index fe0577c381..fb5602dbbb 100644 --- a/src/LuaEngine/methods/GlobalMethods.h +++ b/src/LuaEngine/methods/GlobalMethods.h @@ -142,6 +142,8 @@ namespace LuaGlobalFunctions /** * Returns the [Map] pointer of the Lua state. Returns null for the "World" state. * + * In multistate, this method is only available in the MAP state + * * @return [Map] map */ int GetStateMap(lua_State* L) @@ -205,6 +207,8 @@ namespace LuaGlobalFunctions /** * Finds and Returns [Player] by guid if found * + * In multistate, this method is only available in the WORLD state + * * @param ObjectGuid guid : guid of the [Player], you can get it with [Object:GetGUID] * @return [Player] player */ @@ -218,6 +222,8 @@ namespace LuaGlobalFunctions /** * Finds and Returns [Player] by name if found * + * In multistate, this method is only available in the WORLD state + * * @param string name : name of the [Player] * @return [Player] player */ @@ -251,6 +257,8 @@ namespace LuaGlobalFunctions * TEAM_NEUTRAL = 2 * }; * + * In multistate, this method is only available in the WORLD state + * * @param [TeamId] team = TEAM_NEUTRAL : optional check team of the [Player], Alliance, Horde or Neutral (All) * @param bool onlyGM = false : optional check if GM only * @return table worldPlayers @@ -303,6 +311,8 @@ namespace LuaGlobalFunctions /** * Returns a [Map] by ID. * + * In multistate, this method is only available in the WORLD state + * * @param uint32 mapId : see [Map.dbc](https://github.com/cmangos/issues/wiki/Map.dbc) * @param uint32 instanceId = 0 : required if the map is an instance, otherwise don't pass anything * @return [Map] map : the Map, or `nil` if it doesn't exist @@ -3409,6 +3419,8 @@ namespace LuaGlobalFunctions * 600 = slider max Alliance * -600 = slider max Horde * + * In multistate, this method is only available in the WORLD state + * * @return int16 the ID of the team to own Halaa * @return float the slider position. */ @@ -3427,6 +3439,8 @@ namespace LuaGlobalFunctions * 0 = Alliance * 1 = Horde * + * In multistate, this method is only available in the WORLD state + * * @param uint16 teamId : the ID of the team to own Halaa */ int SetOwnerHalaa(lua_State* L) diff --git a/src/LuaEngine/methods/GroupMethods.h b/src/LuaEngine/methods/GroupMethods.h index 5c0fc37b74..0dee3df875 100644 --- a/src/LuaEngine/methods/GroupMethods.h +++ b/src/LuaEngine/methods/GroupMethods.h @@ -135,6 +135,8 @@ namespace LuaGroup /** * Adds a new member to the [Group] * + * In multistate, this method is only available in the WORLD state + * * @param [Player] player : [Player] to add to the group * @return bool added : true if member was added */ @@ -174,6 +176,8 @@ namespace LuaGroup /** * Returns a table with the [Player]s in this [Group] * + * In multistate, this method is only available in the WORLD state + * * @return table groupPlayers : table of [Player]s */ int GetMembers(lua_State* L, Group* group) @@ -282,6 +286,8 @@ namespace LuaGroup /** * Sets the leader of this [Group] * + * In multistate, this method is only available in the WORLD state + * * @param ObjectGuid guid : guid of the new leader */ int SetLeader(lua_State* L, Group* group) @@ -358,6 +364,8 @@ namespace LuaGroup /** * Sets the member's subGroup * + * In multistate, this method is only available in the WORLD state + * * @param ObjectGuid guid : guid of the player to move * @param uint8 groupID : the subGroup's ID */ @@ -382,6 +390,8 @@ namespace LuaGroup /** * Sets the target icon of an object for the [Group] * + * In multistate, this method is only available in the WORLD state + * * @param uint8 icon : the icon (Skull, Square, etc) * @param ObjectGuid target : GUID of the icon target, 0 is to clear the icon * @param ObjectGuid setter : GUID of the icon setter @@ -410,6 +420,8 @@ namespace LuaGroup * MEMBER_FLAG_MAINASSIST = 0x04, * }; * + * + * In multistate, this method is only available in the WORLD state * * @param ObjectGuid target : GUID of the target * @param bool apply : add the `flag` if `true`, remove the `flag` otherwise diff --git a/src/LuaEngine/methods/GuildMethods.h b/src/LuaEngine/methods/GuildMethods.h index 979f564a9e..6fcf061eff 100644 --- a/src/LuaEngine/methods/GuildMethods.h +++ b/src/LuaEngine/methods/GuildMethods.h @@ -19,6 +19,8 @@ namespace LuaGuild * * Only the players that are online and on some map. * + * In multistate, this method is only available in the WORLD state + * * @return table guildPlayers : table of [Player]s */ int GetMembers(lua_State* L, Guild* guild) @@ -61,6 +63,8 @@ namespace LuaGuild /** * Finds and returns the [Guild] leader by their GUID if logged in * + * In multistate, this method is only available in the WORLD state + * * @return [Player] leader */ int GetLeader(lua_State* L, Guild* guild) @@ -127,6 +131,8 @@ namespace LuaGuild /** * Sets the leader of this [Guild] * + * In multistate, this method is only available in the WORLD state + * * @param [Player] leader : the [Player] leader to change */ int SetLeader(lua_State* L, Guild* guild) @@ -140,6 +146,8 @@ namespace LuaGuild /** * Sets the information of the bank tab specified * + * In multistate, this method is only available in the WORLD state + * * @param uint8 tabId : the ID of the tab specified * @param string info : the information to be set to the bank tab */ @@ -183,6 +191,8 @@ namespace LuaGuild /** * Disbands the [Guild] + * + * In multistate, this method is only available in the WORLD state */ int Disband(lua_State* /*L*/, Guild* guild) { @@ -195,6 +205,8 @@ namespace LuaGuild * * If no rank is specified, defaults to none. * + * In multistate, this method is only available in the WORLD state + * * @param [Player] player : the [Player] to be added to the guild * @param uint8 rankId : the rank ID */ @@ -210,6 +222,8 @@ namespace LuaGuild /** * Removes the specified [Player] from the [Guild]. * + * In multistate, this method is only available in the WORLD state + * * @param [Player] player : the [Player] to be removed from the guild * @param bool isDisbanding : default 'false', should only be set to 'true' if the guild is triggered to disband */ @@ -225,6 +239,8 @@ namespace LuaGuild /** * Promotes/demotes the [Player] to the specified rank. * + * In multistate, this method is only available in the WORLD state + * * @param [Player] player : the [Player] to be promoted/demoted * @param uint8 rankId : the rank ID */ @@ -240,6 +256,8 @@ namespace LuaGuild /** * Sets the new name of the specified [Guild]. * + * In multistate, this method is only available in the WORLD state + * * @param string name : new name of this guild */ int SetName(lua_State* L, Guild* guild) @@ -258,6 +276,8 @@ namespace LuaGuild * GUILD_MEMBER_DATA_ZONEID = 0 * GUILD_MEMBER_DATA_LEVEL = 1 * }; + * + * In multistate, this method is only available in the WORLD state * * @param [Player] player : plkayer you need to update data * @param [GuildMemberData] dataid : data you need to update @@ -294,6 +314,8 @@ namespace LuaGuild /** * Invites [Guild] members to events based on level and rank filters. + * + * In multistate, this method is only available in the WORLD state * * @param [Player] player : who sends the invitation * @param uint32 minLevel : the required min level @@ -313,6 +335,8 @@ namespace LuaGuild /** * Swap item from a specific tab and slot [Guild] bank to another one. + * + * In multistate, this method is only available in the WORLD state * * @param [Player] player : who Swap the item * @param uint8 tabId : source tab id @@ -336,6 +360,8 @@ namespace LuaGuild /** * Swap an item from a specific tab and location in the [guild] bank to the bags and locations in the inventory of a specific [player] and vice versa. + * + * In multistate, this method is only available in the WORLD state * * @param [Player] player : who Swap the item * @param bool toChar : the item goes to the [Player]'s inventory or comes from the [Player]'s inventory @@ -383,6 +409,8 @@ namespace LuaGuild /** * Resets the number of item withdraw in all tab's for all [Guild] members. + * + * In multistate, this method is only available in the WORLD state */ int ResetTimes(lua_State* /*L*/, Guild* guild) { @@ -392,6 +420,8 @@ namespace LuaGuild /** * Modify the [Guild] bank money. You can deposit or withdraw. + * + * In multistate, this method is only available in the WORLD state * * @param uint64 amount : amount to add or remove * @param bool add : true (add money) | false (withdraw money) diff --git a/src/LuaEngine/methods/PlayerMethods.h b/src/LuaEngine/methods/PlayerMethods.h index d0730dd226..38cee8ebbc 100644 --- a/src/LuaEngine/methods/PlayerMethods.h +++ b/src/LuaEngine/methods/PlayerMethods.h @@ -3790,6 +3790,8 @@ namespace LuaPlayer /** * Makes the [Player] invite another player to a group. * + * In multistate, this method is only available in the WORLD state + * * @param [Player] invited : player to invite to group * @return bool success : true if the player was invited to a group */ @@ -3840,6 +3842,8 @@ namespace LuaPlayer /** * Creates a new [Group] with the creator [Player] as leader. * + * In multistate, this method is only available in the WORLD state + * * @param [Player] invited : player to add to group * @return [Group] createdGroup : the created group or nil */ From e70e1eca30e3cedb6806b68731889fee2a7bba7e Mon Sep 17 00:00:00 2001 From: mostlynick3 Date: Mon, 6 Apr 2026 05:40:19 +0200 Subject: [PATCH 12/12] Implement tables in documentation parser Cherry pick from upstream Eluna https://github.com/ElunaLuaEngine/Eluna/commit/71ddf6c8c774f965ecfa83ae63e263c499ef5a7c --- src/LuaEngine/docs/ALEDoc/parser.py | 56 +- src/LuaEngine/docs/ALEDoc/static/main.css | 36 +- .../docs/ALEDoc/templates/method.html | 9 + src/LuaEngine/methods/GlobalMethods.h | 840 +++++++++--------- 4 files changed, 491 insertions(+), 450 deletions(-) diff --git a/src/LuaEngine/docs/ALEDoc/parser.py b/src/LuaEngine/docs/ALEDoc/parser.py index b03c642601..15f313f23f 100644 --- a/src/LuaEngine/docs/ALEDoc/parser.py +++ b/src/LuaEngine/docs/ALEDoc/parser.py @@ -3,7 +3,11 @@ import typing import markdown from typedecorator import params, returns, Nullable +from typing import Any, List, TypedDict +class TableDict(TypedDict): + columns: List[str] + values: List[List[Any]] class ParameterDoc(object): """The documentation data of a parameter or return value for an ALE method.""" @@ -65,13 +69,24 @@ def __init__(self, name, data_type, description, default_value=None): class MethodDoc(object): """The documentation data of an ALE method.""" - @params(self=object, name=str, description=str, prototypes=[str], parameters=[ParameterDoc], returned=[ParameterDoc]) - def __init__(self, name, description, prototypes, parameters, returned): + @params(self=object, name=str, description=str, table=TableDict, prototypes=[str], parameters=[ParameterDoc], returned=[ParameterDoc]) + def __init__(self, name, description, table, prototypes, parameters, returned): self.name = name self.prototypes = prototypes + self.table = table self.parameters = parameters self.returned = returned + if table: + # Generate Markdown Table + md_table = '| ' + ' | '.join(table['columns']) + ' |\n' # Header + md_table += '| ' + ' | '.join(['---'] * len(table['columns'])) + ' |\n' # Separator + + for row in table['values']: + md_table += '| ' + ' | '.join(row) + ' |\n' # Rows + + self.table = markdown.markdown(md_table, extensions=['tables']) + # Parse the description as Markdown. self.description = markdown.markdown(description) # Pull the first paragraph out of the description as the short description. @@ -123,6 +138,11 @@ class ClassParser(object): body_regex = re.compile(r"\s*\s?\*\s?(.*)") # The "body", i.e. a * and optionally some descriptive text. # An extra optional space (\s?) was thrown in to make it different from `class_body_regex`. + # Regular expressions for parsing a table. + table_regex = re.compile(r"\s*\*\s@table") + table_columns_regex = re.compile(r"\s*\*\s@columns\s*\[(.+)\]") + table_values_regex = re.compile(r"\s*\*\s@values\s*\[(.+)\]") + param_regex = re.compile(r"""\s*\*\s@param\s # The @param tag starts with opt. whitespace followed by "* @param ". ([^\s]+)\s(\w+)? # The data type, a space, and the name of the param. (?:\s=\s(\w+))? # The default value: a = surrounded by spaces, followed by text. @@ -163,6 +183,7 @@ def reset(self): self.returned = [] self.method_name = None self.prototypes = [] + self.table = {} def handle_class_body(self, match): text = match.group(1) @@ -171,6 +192,21 @@ def handle_class_body(self, match): def handle_body(self, match): text = match.group(1) self.description += text + '\n' + + def handle_table(self, line): + self.table = { + "columns": [], + "values": [] + } + + def handle_table_columns(self, match): + if self.table: + self.table["columns"] = match.group(1).split(", ") + + def handle_table_values(self, match): + if self.table: + values = re.findall(r'(?:[^,"]|"(?:\\.|[^"])*")+', match.group(1)) + self.table["values"].append([v.strip(' "') for v in values]) def handle_param(self, match): data_type, name, default, description = match.group(1), match.group(2), match.group(3), match.group(4) @@ -247,7 +283,7 @@ def make_prototype(parameters): # Format the method name into each prototype. self.prototypes = [proto.format(self.method_name) for proto in self.prototypes] - self.methods.append(MethodDoc(self.method_name, self.description, self.prototypes, self.params, self.returned)) + self.methods.append(MethodDoc(self.method_name, self.description, self.table, self.prototypes, self.params, self.returned)) # Table of which handler is used to handle each regular expressions. regex_handlers = { @@ -256,6 +292,9 @@ def make_prototype(parameters): class_end_regex: None, start_regex: None, body_regex: handle_body, + table_regex: handle_table, + table_columns_regex: handle_table_columns, + table_values_regex: handle_table_values, param_regex: handle_param, return_regex: handle_return, proto_regex: handle_proto, @@ -270,10 +309,13 @@ def make_prototype(parameters): class_start_regex: [class_end_regex, class_body_regex], class_body_regex: [class_end_regex, class_body_regex], class_end_regex: [], - start_regex: [param_regex, return_regex, proto_regex, comment_end_regex, body_regex], - body_regex: [param_regex, return_regex, proto_regex, comment_end_regex, body_regex], - proto_regex: [param_regex, return_regex, proto_regex, comment_end_regex, body_regex], - param_regex: [param_regex, return_regex, comment_end_regex, body_regex], + start_regex: [table_regex, param_regex, return_regex, proto_regex, comment_end_regex, body_regex], + body_regex: [table_regex, param_regex, return_regex, proto_regex, comment_end_regex, body_regex], + proto_regex: [table_regex, param_regex, return_regex, proto_regex, comment_end_regex, body_regex], + table_regex: [table_regex, table_columns_regex, param_regex, return_regex, comment_end_regex, body_regex], + table_columns_regex: [table_values_regex, param_regex, return_regex, comment_end_regex, body_regex], + table_values_regex: [table_values_regex, param_regex, return_regex, comment_end_regex, body_regex], + param_regex: [table_regex, param_regex, return_regex, comment_end_regex, body_regex], return_regex: [return_regex, comment_end_regex], comment_end_regex: [end_regex], end_regex: [], diff --git a/src/LuaEngine/docs/ALEDoc/static/main.css b/src/LuaEngine/docs/ALEDoc/static/main.css index 4d943cf48d..43ae8db4d5 100644 --- a/src/LuaEngine/docs/ALEDoc/static/main.css +++ b/src/LuaEngine/docs/ALEDoc/static/main.css @@ -155,7 +155,41 @@ nav.sub { min-height: 100%; } -.content, nav { max-width: 960px; } +.content, nav { max-width: 80vw; } + +.docblock .table-container { + width: 100%; + overflow-x: auto; + margin-bottom: 20px; +} + +.docblock table { + max-width: 50vw; + border-collapse: collapse !important; + table-layout: auto; + margin-bottom: 20px; + font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", Inconsolata, monospace; +} + +.docblock th, .docblock td { + padding: 10px; + text-align: left; + border: 1px solid #ddd; + white-space: nowrap; +} + +.docblock th { + background-color: #f5f5f5; + font-weight: bold; +} + +.docblock tr:nth-child(even) { + background-color: #f9f9f9; +} + +.docblock table { + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} /* Everything else */ diff --git a/src/LuaEngine/docs/ALEDoc/templates/method.html b/src/LuaEngine/docs/ALEDoc/templates/method.html index d02dd1f27b..63fe384106 100644 --- a/src/LuaEngine/docs/ALEDoc/templates/method.html +++ b/src/LuaEngine/docs/ALEDoc/templates/method.html @@ -47,6 +47,15 @@

{{ current_class.name }} Methods

For temporary documentation, please check the LuaFunctions source file.

{%- endif %} + + {%- if current_method.table %} +
+

+ {{ current_method.table }} +

+
+ {%- endif %} +

Synopsis

diff --git a/src/LuaEngine/methods/GlobalMethods.h b/src/LuaEngine/methods/GlobalMethods.h index fb5602dbbb..b9521f0813 100644 --- a/src/LuaEngine/methods/GlobalMethods.h +++ b/src/LuaEngine/methods/GlobalMethods.h @@ -664,68 +664,51 @@ namespace LuaGlobalFunctions /** * Registers a server event handler. * - * enum ServerEvents - * { - * // Server - * SERVER_EVENT_ON_NETWORK_START = 1, // Not Implemented - * SERVER_EVENT_ON_NETWORK_STOP = 2, // Not Implemented - * SERVER_EVENT_ON_SOCKET_OPEN = 3, // Not Implemented - * SERVER_EVENT_ON_SOCKET_CLOSE = 4, // Not Implemented - * SERVER_EVENT_ON_PACKET_RECEIVE = 5, // (event, packet, player) - Player only if accessible. Can return false, newPacket - * SERVER_EVENT_ON_PACKET_RECEIVE_UNKNOWN = 6, // Not Implemented - * SERVER_EVENT_ON_PACKET_SEND = 7, // (event, packet, player) - Player only if accessible. Can return false, newPacket - * - * // World - * WORLD_EVENT_ON_OPEN_STATE_CHANGE = 8, // (event, open) - Needs core support on Mangos - * WORLD_EVENT_ON_CONFIG_LOAD = 9, // (event, reload) - * // UNUSED = 10, - * WORLD_EVENT_ON_SHUTDOWN_INIT = 11, // (event, code, mask) - * WORLD_EVENT_ON_SHUTDOWN_CANCEL = 12, // (event) - * WORLD_EVENT_ON_UPDATE = 13, // (event, diff) - * WORLD_EVENT_ON_STARTUP = 14, // (event) - * WORLD_EVENT_ON_SHUTDOWN = 15, // (event) - * - * // ALE - * ALE_EVENT_ON_LUA_STATE_CLOSE = 16, // (event) - triggers just before shutting down ALE (on shutdown and restart) - * - * // Map - * MAP_EVENT_ON_CREATE = 17, // (event, map) - * MAP_EVENT_ON_DESTROY = 18, // (event, map) - * MAP_EVENT_ON_GRID_LOAD = 19, // Not Implemented - * MAP_EVENT_ON_GRID_UNLOAD = 20, // Not Implemented - * MAP_EVENT_ON_PLAYER_ENTER = 21, // (event, map, player) - * MAP_EVENT_ON_PLAYER_LEAVE = 22, // (event, map, player) - * MAP_EVENT_ON_UPDATE = 23, // (event, map, diff) - * - * // Area trigger - * TRIGGER_EVENT_ON_TRIGGER = 24, // (event, player, triggerId) - Can return true - * - * // Weather - * WEATHER_EVENT_ON_CHANGE = 25, // (event, zoneId, state, grade) - * - * // Auction house - * AUCTION_EVENT_ON_ADD = 26, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) - * AUCTION_EVENT_ON_REMOVE = 27, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) - * AUCTION_EVENT_ON_SUCCESSFUL = 28, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) - * AUCTION_EVENT_ON_EXPIRE = 29, // (event, auctionId, owner, item, expireTime, buyout, startBid, currentBid, bidderGUIDLow) - * - * // AddOns - * ADDON_EVENT_ON_MESSAGE = 30, // (event, sender, type, prefix, msg, target) - target can be nil/whisper_target/guild/group/channel. Can return false - * - * WORLD_EVENT_ON_DELETE_CREATURE = 31, // (event, creature) - * WORLD_EVENT_ON_DELETE_GAMEOBJECT = 32, // (event, gameobject) - * - * // ALE - * ALE_EVENT_ON_LUA_STATE_OPEN = 33, // (event) - triggers after all scripts are loaded - * - * GAME_EVENT_START = 34, // (event, gameeventid) - * GAME_EVENT_STOP = 35, // (event, gameeventid) - * }; + * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, SERVER_EVENT_ON_NETWORK_START, "", "", "Not Implemented"] + * @values [2, SERVER_EVENT_ON_NETWORK_STOP, "", "", "Not Implemented"] + * @values [3, SERVER_EVENT_ON_SOCKET_OPEN, "", "", "Not Implemented"] + * @values [4, SERVER_EVENT_ON_SOCKET_CLOSE, "", "", "Not Implemented"] + * @values [5, SERVER_EVENT_ON_PACKET_RECEIVE, "WORLD", , "Player only if accessible. Can return false, newPacket"] + * @values [6, SERVER_EVENT_ON_PACKET_RECEIVE_UNKNOWN, "", "", "Not Implemented"] + * @values [7, SERVER_EVENT_ON_PACKET_SEND, "WORLD", , "Player only if accessible. Can return false, newPacket"] + * @values [8, WORLD_EVENT_ON_OPEN_STATE_CHANGE, "WORLD", , "Needs core support on Mangos"] + * @values [9, WORLD_EVENT_ON_CONFIG_LOAD, "WORLD", , ""] + * @values [11, WORLD_EVENT_ON_SHUTDOWN_INIT, "WORLD", , ""] + * @values [12, WORLD_EVENT_ON_SHUTDOWN_CANCEL, "WORLD", , ""] + * @values [13, WORLD_EVENT_ON_UPDATE, "WORLD", , ""] + * @values [14, WORLD_EVENT_ON_STARTUP, "WORLD", , ""] + * @values [15, WORLD_EVENT_ON_SHUTDOWN, "WORLD", , ""] + * @values [16, ALE_EVENT_ON_LUA_STATE_CLOSE, "ALL", , "Triggers just before shutting down ALE (on shutdown and restart)"] + * @values [17, MAP_EVENT_ON_CREATE, "MAP", , ""] + * @values [18, MAP_EVENT_ON_DESTROY, "MAP", , ""] + * @values [19, MAP_EVENT_ON_GRID_LOAD, "", "", "Not Implemented"] + * @values [20, MAP_EVENT_ON_GRID_UNLOAD, "", "", "Not Implemented"] + * @values [21, MAP_EVENT_ON_PLAYER_ENTER, "MAP", , ""] + * @values [22, MAP_EVENT_ON_PLAYER_LEAVE, "MAP", , ""] + * @values [23, MAP_EVENT_ON_UPDATE, "MAP", , ""] + * @values [24, TRIGGER_EVENT_ON_TRIGGER, "MAP", , "Can return true"] + * @values [25, WEATHER_EVENT_ON_CHANGE, "WORLD", , ""] + * @values [26, AUCTION_EVENT_ON_ADD, "WORLD", , ""] + * @values [27, AUCTION_EVENT_ON_REMOVE, "WORLD", , ""] + * @values [28, AUCTION_EVENT_ON_SUCCESSFUL, "WORLD", , ""] + * @values [29, AUCTION_EVENT_ON_EXPIRE, "WORLD", , ""] + * @values [30, ADDON_EVENT_ON_MESSAGE, "WORLD", , "Target can be nil/whisper_target/guild/group/channel. Can return false"] + * @values [31, WORLD_EVENT_ON_DELETE_CREATURE, "MAP", , ""] + * @values [32, WORLD_EVENT_ON_DELETE_GAMEOBJECT, "MAP", , ""] + * @values [33, ALE_EVENT_ON_LUA_STATE_OPEN, "ALL", , "Triggers after all scripts are loaded"] + * @values [34, GAME_EVENT_START, "WORLD", , ""] + * @values [35, GAME_EVENT_STOP, "WORLD", , ""] * * @proto cancel = (event, function) * @proto cancel = (event, function, shots) * - * @param uint32 event : server event ID, refer to ServerEvents above + * @param uint32 event : server event ID, refer to table above * @param function function : function that will be called when the event occurs * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -739,91 +722,88 @@ namespace LuaGlobalFunctions /** * Registers a [Player] event handler. * - *
-     * enum PlayerEvents
-     * {
-     *     PLAYER_EVENT_ON_CHARACTER_CREATE                     =     1,        // (event, player)
-     *     PLAYER_EVENT_ON_CHARACTER_DELETE                     =     2,        // (event, guid)
-     *     PLAYER_EVENT_ON_LOGIN                                =     3,        // (event, player)
-     *     PLAYER_EVENT_ON_LOGOUT                               =     4,        // (event, player)
-     *     PLAYER_EVENT_ON_SPELL_CAST                           =     5,        // (event, player, spell, skipCheck)
-     *     PLAYER_EVENT_ON_KILL_PLAYER                          =     6,        // (event, killer, killed)
-     *     PLAYER_EVENT_ON_KILL_CREATURE                        =     7,        // (event, killer, killed)
-     *     PLAYER_EVENT_ON_KILLED_BY_CREATURE                   =     8,        // (event, killer, killed)
-     *     PLAYER_EVENT_ON_DUEL_REQUEST                         =     9,        // (event, target, challenger)
-     *     PLAYER_EVENT_ON_DUEL_START                           =     10,       // (event, player1, player2)
-     *     PLAYER_EVENT_ON_DUEL_END                             =     11,       // (event, winner, loser, type)
-     *     PLAYER_EVENT_ON_GIVE_XP                              =     12,       // (event, player, amount, victim, source) - Can return new XP amount
-     *     PLAYER_EVENT_ON_LEVEL_CHANGE                         =     13,       // (event, player, oldLevel)
-     *     PLAYER_EVENT_ON_MONEY_CHANGE                         =     14,       // (event, player, amount) - Can return new money amount
-     *     PLAYER_EVENT_ON_REPUTATION_CHANGE                    =     15,       // (event, player, factionId, standing, incremental) - Can return new standing -> if standing == -1, it will prevent default action (rep gain)
-     *     PLAYER_EVENT_ON_TALENTS_CHANGE                       =     16,       // (event, player, points)
-     *     PLAYER_EVENT_ON_TALENTS_RESET                        =     17,       // (event, player, noCost)
-     *     PLAYER_EVENT_ON_CHAT                                 =     18,       // (event, player, msg, Type, lang) - Can return false, newMessage
-     *     PLAYER_EVENT_ON_WHISPER                              =     19,       // (event, player, msg, Type, lang, receiver) - Can return false, newMessage
-     *     PLAYER_EVENT_ON_GROUP_CHAT                           =     20,       // (event, player, msg, Type, lang, group) - Can return false, newMessage
-     *     PLAYER_EVENT_ON_GUILD_CHAT                           =     21,       // (event, player, msg, Type, lang, guild) - Can return false, newMessage
-     *     PLAYER_EVENT_ON_CHANNEL_CHAT                         =     22,       // (event, player, msg, Type, lang, channel) - channel is negative for custom channels. Can return false, newMessage
-     *     PLAYER_EVENT_ON_EMOTE                                =     23,       // (event, player, emote) - Not triggered on any known emote
-     *     PLAYER_EVENT_ON_TEXT_EMOTE                           =     24,       // (event, player, textEmote, emoteNum, guid)
-     *     PLAYER_EVENT_ON_SAVE                                 =     25,       // (event, player)
-     *     PLAYER_EVENT_ON_BIND_TO_INSTANCE                     =     26,       // (event, player, difficulty, mapid, permanent)
-     *     PLAYER_EVENT_ON_UPDATE_ZONE                          =     27,       // (event, player, newZone, newArea)
-     *     PLAYER_EVENT_ON_MAP_CHANGE                           =     28,       // (event, player)
-     *
-     *     // Custom
-     *     PLAYER_EVENT_ON_EQUIP                                =     29,       // (event, player, item, bag, slot)
-     *     PLAYER_EVENT_ON_FIRST_LOGIN                          =     30,       // (event, player)
-     *     PLAYER_EVENT_ON_CAN_USE_ITEM                         =     31,       // (event, player, itemEntry) - Can return InventoryResult enum value
-     *     PLAYER_EVENT_ON_LOOT_ITEM                            =     32,       // (event, player, item, count)
-     *     PLAYER_EVENT_ON_ENTER_COMBAT                         =     33,       // (event, player, enemy)
-     *     PLAYER_EVENT_ON_LEAVE_COMBAT                         =     34,       // (event, player)
-     *     PLAYER_EVENT_ON_REPOP                                =     35,       // (event, player)
-     *     PLAYER_EVENT_ON_RESURRECT                            =     36,       // (event, player)
-     *     PLAYER_EVENT_ON_LOOT_MONEY                           =     37,       // (event, player, amount)
-     *     PLAYER_EVENT_ON_QUEST_ABANDON                        =     38,       // (event, player, questId)
-     *     PLAYER_EVENT_ON_LEARN_TALENTS                        =     39,       // (event, player, talentId, talentRank, spellid)
-     *     // UNUSED                                            =     40,       // (event, player)
-     *     // UNUSED                                            =     41,       // (event, player)
-     *     PLAYER_EVENT_ON_COMMAND                              =     42,       // (event, player, command, chatHandler) - player is nil if command used from console. Can return false
-     *     PLAYER_EVENT_ON_PET_ADDED_TO_WORLD                   =     43,       // (event, player, pet)
-     *     PLAYER_EVENT_ON_LEARN_SPELL                          =     44,       // (event, player, spellId)
-     *     PLAYER_EVENT_ON_ACHIEVEMENT_COMPLETE                 =     45,       // (event, player, achievement)
-     *     PLAYER_EVENT_ON_FFAPVP_CHANGE                        =     46,       // (event, player, hasFfaPvp)
-     *     PLAYER_EVENT_ON_UPDATE_AREA                          =     47,       // (event, player, oldArea, newArea)
-     *     PLAYER_EVENT_ON_CAN_INIT_TRADE                       =     48,       // (event, player, target) - Can return false to prevent the trade
-     *     PLAYER_EVENT_ON_CAN_SEND_MAIL                        =     49,       // (event, player, receiverGuid, mailbox, subject, body, money, cod, item) - Can return false to prevent sending the mail
-     *     PLAYER_EVENT_ON_CAN_JOIN_LFG                         =     50,       // (event, player, roles, dungeons, comment) - Can return false to prevent queueing
-     *     PLAYER_EVENT_ON_QUEST_REWARD_ITEM                    =     51,       //  (event, player, item, count)
-     *     PLAYER_EVENT_ON_CREATE_ITEM                          =     52,       //  (event, player, item, count)
-     *     PLAYER_EVENT_ON_STORE_NEW_ITEM                       =     53,       //  (event, player, item, count)
-     *     PLAYER_EVENT_ON_COMPLETE_QUEST                       =     54,       // (event, player, quest)
-     *     PLAYER_EVENT_ON_CAN_GROUP_INVITE                     =     55,       // (event, player, memberName) - Can return false to prevent inviting
-     *     PLAYER_EVENT_ON_GROUP_ROLL_REWARD_ITEM               =     56,       // (event, player, item, count, voteType, roll)
-     *     PLAYER_EVENT_ON_BG_DESERTION                         =     57,       // (event, player, type)
-     *     PLAYER_EVENT_ON_PET_KILL                             =     58,       // (event, player, killer)
-     *     PLAYER_EVENT_ON_CAN_RESURRECT                        =     59,       // (event, player)
-     *     PLAYER_EVENT_ON_CAN_UPDATE_SKILL                     =     60,       // (event, player, skill_id) -- Can return true or false
-     *     PLAYER_EVENT_ON_BEFORE_UPDATE_SKILL                  =     61,       // (event, player, skill_id, value, max, step) -- Can return new amount
-     *     PLAYER_EVENT_ON_UPDATE_SKILL                         =     62,       // (event, player, skill_id, value, max, step, new_value)
-     *     PLAYER_EVENT_ON_QUEST_ACCEPT                         =     63,       // (event, player, quest)
-     *     PLAYER_EVENT_ON_AURA_APPLY                           =     64,       // (event, player, aura)
-     *     PLAYER_EVENT_ON_HEAL                                 =     65,       // (event, player, target, heal) - Can return new heal amount
-     *     PLAYER_EVENT_ON_DAMAGE                               =     66,       // (event, player, target, damage) - Can return new damage amount
-     *     PLAYER_EVENT_ON_AURA_REMOVE                          =     67,       // (event, player, aura, remove_mode)
-     *     PLAYER_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK    =     68,    // (event, player, target, damage, spellInfo) - Can return new damage amount
-     *     PLAYER_EVENT_ON_MODIFY_MELEE_DAMAGE                  =     69,       // (event, player, target, damage) - Can return new damage amount
-     *     PLAYER_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN            =     70,       // (event, player, target, damage, spellInfo) - Can return new damage amount
-     *     PLAYER_EVENT_ON_MODIFY_HEAL_RECEIVED                 =     71,       // (event, player, target, heal, spellInfo) - Can return new heal amount
-     *     PLAYER_EVENT_ON_DEAL_DAMAGE                          =     72,       // (event, player, target, damage, damagetype) - Can return new damage amount
-     *     PLAYER_EVENT_ON_RELEASED_GHOST                       =     73,       // (event, player)
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, PLAYER_EVENT_ON_CHARACTER_CREATE, "WORLD", , ""] + * @values [2, PLAYER_EVENT_ON_CHARACTER_DELETE, "WORLD", , ""] + * @values [3, PLAYER_EVENT_ON_LOGIN, "WORLD", , ""] + * @values [4, PLAYER_EVENT_ON_LOGOUT, "WORLD", , ""] + * @values [5, PLAYER_EVENT_ON_SPELL_CAST, "MAP", , ""] + * @values [6, PLAYER_EVENT_ON_KILL_PLAYER, "MAP", , ""] + * @values [7, PLAYER_EVENT_ON_KILL_CREATURE, "MAP", , ""] + * @values [8, PLAYER_EVENT_ON_KILLED_BY_CREATURE, "MAP", , ""] + * @values [9, PLAYER_EVENT_ON_DUEL_REQUEST, "MAP", , ""] + * @values [10, PLAYER_EVENT_ON_DUEL_START, "MAP", , ""] + * @values [11, PLAYER_EVENT_ON_DUEL_END, "MAP", , ""] + * @values [12, PLAYER_EVENT_ON_GIVE_XP, "MAP", , "Can return new XP amount"] + * @values [13, PLAYER_EVENT_ON_LEVEL_CHANGE, "MAP", , ""] + * @values [14, PLAYER_EVENT_ON_MONEY_CHANGE, "MAP", , "Can return new money amount"] + * @values [15, PLAYER_EVENT_ON_REPUTATION_CHANGE, "MAP", , "Can return new standing. If standing == -1 it will prevent default action (rep gain)"] + * @values [16, PLAYER_EVENT_ON_TALENTS_CHANGE, "MAP", , ""] + * @values [17, PLAYER_EVENT_ON_TALENTS_RESET, "MAP", , ""] + * @values [18, PLAYER_EVENT_ON_CHAT, "WORLD", , "Can return false, newMessage"] + * @values [19, PLAYER_EVENT_ON_WHISPER, "WORLD", , "Can return false, newMessage"] + * @values [20, PLAYER_EVENT_ON_GROUP_CHAT, "WORLD", , "Can return false, newMessage"] + * @values [21, PLAYER_EVENT_ON_GUILD_CHAT, "WORLD", , "Can return false, newMessage"] + * @values [22, PLAYER_EVENT_ON_CHANNEL_CHAT, "WORLD", , "Channel is negative for custom channels. Can return false, newMessage"] + * @values [23, PLAYER_EVENT_ON_EMOTE, "MAP", , "Not triggered on any known emote"] + * @values [24, PLAYER_EVENT_ON_TEXT_EMOTE, "MAP", , ""] + * @values [25, PLAYER_EVENT_ON_SAVE, "MAP", , ""] + * @values [26, PLAYER_EVENT_ON_BIND_TO_INSTANCE, "MAP", , ""] + * @values [27, PLAYER_EVENT_ON_UPDATE_ZONE, "MAP", , ""] + * @values [28, PLAYER_EVENT_ON_MAP_CHANGE, "MAP", , ""] + * @values [29, PLAYER_EVENT_ON_EQUIP, "MAP", , ""] + * @values [30, PLAYER_EVENT_ON_FIRST_LOGIN, "WORLD", , ""] + * @values [31, PLAYER_EVENT_ON_CAN_USE_ITEM, "MAP", , "Can return InventoryResult enum value"] + * @values [32, PLAYER_EVENT_ON_LOOT_ITEM, "MAP", , ""] + * @values [33, PLAYER_EVENT_ON_ENTER_COMBAT, "MAP", , ""] + * @values [34, PLAYER_EVENT_ON_LEAVE_COMBAT, "MAP", , ""] + * @values [35, PLAYER_EVENT_ON_REPOP, "MAP", , ""] + * @values [36, PLAYER_EVENT_ON_RESURRECT, "MAP", , ""] + * @values [37, PLAYER_EVENT_ON_LOOT_MONEY, "MAP", , ""] + * @values [38, PLAYER_EVENT_ON_QUEST_ABANDON, "MAP", , ""] + * @values [39, PLAYER_EVENT_ON_LEARN_TALENTS, "MAP", , ""] + * @values [42, PLAYER_EVENT_ON_COMMAND, "WORLD", , "Player is nil if command used from console. Can return false"] + * @values [43, PLAYER_EVENT_ON_PET_ADDED_TO_WORLD, "MAP", , ""] + * @values [44, PLAYER_EVENT_ON_LEARN_SPELL, "MAP", , ""] + * @values [45, PLAYER_EVENT_ON_ACHIEVEMENT_COMPLETE, "MAP", , ""] + * @values [46, PLAYER_EVENT_ON_FFAPVP_CHANGE, "MAP", , ""] + * @values [47, PLAYER_EVENT_ON_UPDATE_AREA, "MAP", , ""] + * @values [48, PLAYER_EVENT_ON_CAN_INIT_TRADE, "MAP", , "Can return false to prevent the trade"] + * @values [49, PLAYER_EVENT_ON_CAN_SEND_MAIL, "MAP", , "Can return false to prevent sending the mail"] + * @values [50, PLAYER_EVENT_ON_CAN_JOIN_LFG, "MAP", , "Can return false to prevent queueing"] + * @values [51, PLAYER_EVENT_ON_QUEST_REWARD_ITEM, "MAP", , ""] + * @values [52, PLAYER_EVENT_ON_CREATE_ITEM, "MAP", , ""] + * @values [53, PLAYER_EVENT_ON_STORE_NEW_ITEM, "MAP", , ""] + * @values [54, PLAYER_EVENT_ON_COMPLETE_QUEST, "MAP", , ""] + * @values [55, PLAYER_EVENT_ON_CAN_GROUP_INVITE, "MAP", , "Can return false to prevent inviting"] + * @values [56, PLAYER_EVENT_ON_GROUP_ROLL_REWARD_ITEM, "MAP", , ""] + * @values [57, PLAYER_EVENT_ON_BG_DESERTION, "MAP", , ""] + * @values [58, PLAYER_EVENT_ON_PET_KILL, "MAP", , ""] + * @values [59, PLAYER_EVENT_ON_CAN_RESURRECT, "MAP", , ""] + * @values [60, PLAYER_EVENT_ON_CAN_UPDATE_SKILL, "MAP", , "Can return true or false"] + * @values [61, PLAYER_EVENT_ON_BEFORE_UPDATE_SKILL, "MAP", , "Can return new amount"] + * @values [62, PLAYER_EVENT_ON_UPDATE_SKILL, "MAP", , ""] + * @values [63, PLAYER_EVENT_ON_QUEST_ACCEPT, "MAP", , ""] + * @values [64, PLAYER_EVENT_ON_AURA_APPLY, "MAP", , ""] + * @values [65, PLAYER_EVENT_ON_HEAL, "MAP", , "Can return new heal amount"] + * @values [66, PLAYER_EVENT_ON_DAMAGE, "MAP", , "Can return new damage amount"] + * @values [67, PLAYER_EVENT_ON_AURA_REMOVE, "MAP", , ""] + * @values [68, PLAYER_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK, "MAP", , "Can return new damage amount"] + * @values [69, PLAYER_EVENT_ON_MODIFY_MELEE_DAMAGE, "MAP", , "Can return new damage amount"] + * @values [70, PLAYER_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN, "MAP", , "Can return new damage amount"] + * @values [71, PLAYER_EVENT_ON_MODIFY_HEAL_RECEIVED, "MAP", , "Can return new heal amount"] + * @values [72, PLAYER_EVENT_ON_DEAL_DAMAGE, "MAP", , "Can return new damage amount"] + * @values [73, PLAYER_EVENT_ON_RELEASED_GHOST, "MAP", , ""] * * @proto cancel = (event, function) * @proto cancel = (event, function, shots) * - * @param uint32 event : [Player] event Id, refer to PlayerEvents above + * @param uint32 event : [Player] event Id, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -837,30 +817,28 @@ namespace LuaGlobalFunctions /** * Registers a [Guild] event handler. * - *
-     * enum GuildEvents
-     * {
-     *     // Guild
-     *     GUILD_EVENT_ON_ADD_MEMBER               =     1,       // (event, guild, player, rank)
-     *     GUILD_EVENT_ON_REMOVE_MEMBER            =     2,       // (event, guild, player, isDisbanding)
-     *     GUILD_EVENT_ON_MOTD_CHANGE              =     3,       // (event, guild, newMotd)
-     *     GUILD_EVENT_ON_INFO_CHANGE              =     4,       // (event, guild, newInfo)
-     *     GUILD_EVENT_ON_CREATE                   =     5,       // (event, guild, leader, name)  // Not on TC
-     *     GUILD_EVENT_ON_DISBAND                  =     6,       // (event, guild)
-     *     GUILD_EVENT_ON_MONEY_WITHDRAW           =     7,       // (event, guild, player, amount, isRepair) - Can return new money amount
-     *     GUILD_EVENT_ON_MONEY_DEPOSIT            =     8,       // (event, guild, player, amount) - Can return new money amount
-     *     GUILD_EVENT_ON_ITEM_MOVE                =     9,       // (event, guild, player, item, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId)   // TODO
-     *     GUILD_EVENT_ON_EVENT                    =     10,      // (event, guild, eventType, plrGUIDLow1, plrGUIDLow2, newRank)  // TODO
-     *     GUILD_EVENT_ON_BANK_EVENT               =     11,      // (event, guild, eventType, tabId, playerGUIDLow, itemOrMoney, itemStackCount, destTabId)
-     *
-     *     GUILD_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, GUILD_EVENT_ON_ADD_MEMBER, "WORLD", , ""] + * @values [2, GUILD_EVENT_ON_REMOVE_MEMBER, "WORLD", , ""] + * @values [3, GUILD_EVENT_ON_MOTD_CHANGE, "WORLD", , ""] + * @values [4, GUILD_EVENT_ON_INFO_CHANGE, "WORLD", , ""] + * @values [5, GUILD_EVENT_ON_CREATE, "WORLD", , "Not on TC"] + * @values [6, GUILD_EVENT_ON_DISBAND, "WORLD", , ""] + * @values [7, GUILD_EVENT_ON_MONEY_WITHDRAW, "WORLD", , "Can return new money amount"] + * @values [8, GUILD_EVENT_ON_MONEY_DEPOSIT, "WORLD", , "Can return new money amount"] + * @values [9, GUILD_EVENT_ON_ITEM_MOVE, "WORLD", , "TODO"] + * @values [10, GUILD_EVENT_ON_EVENT, "WORLD", , "TODO"] + * @values [11, GUILD_EVENT_ON_BANK_EVENT, "WORLD", , ""] * * @proto cancel = (event, function) * @proto cancel = (event, function, shots) * - * @param uint32 event : [Guild] event Id, refer to GuildEvents above + * @param uint32 event : [Guild] event Id, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -874,25 +852,23 @@ namespace LuaGlobalFunctions /** * Registers a [Group] event handler. * - *
-     * enum GroupEvents
-     * {
-     *     // Group
-     *     GROUP_EVENT_ON_MEMBER_ADD               =     1,       // (event, group, guid)
-     *     GROUP_EVENT_ON_MEMBER_INVITE            =     2,       // (event, group, guid)
-     *     GROUP_EVENT_ON_MEMBER_REMOVE            =     3,       // (event, group, guid, method, kicker, reason)
-     *     GROUP_EVENT_ON_LEADER_CHANGE            =     4,       // (event, group, newLeaderGuid, oldLeaderGuid)
-     *     GROUP_EVENT_ON_DISBAND                  =     5,       // (event, group)
-     *     GROUP_EVENT_ON_CREATE                   =     6,       // (event, group, leaderGuid, groupType)
-     *
-     *     GROUP_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, GROUP_EVENT_ON_MEMBER_ADD, "WORLD", , ""] + * @values [2, GROUP_EVENT_ON_MEMBER_INVITE, "WORLD", , ""] + * @values [3, GROUP_EVENT_ON_MEMBER_REMOVE, "WORLD", , ""] + * @values [4, GROUP_EVENT_ON_LEADER_CHANGE, "WORLD", , ""] + * @values [5, GROUP_EVENT_ON_DISBAND, "WORLD", , ""] + * @values [6, GROUP_EVENT_ON_CREATE, "WORLD", , ""] * * @proto cancel = (event, function) * @proto cancel = (event, function, shots) * - * @param uint32 event : [Group] event Id, refer to GroupEvents above + * @param uint32 event : [Group] event Id, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -906,21 +882,21 @@ namespace LuaGlobalFunctions /** * Registers a [BattleGround] event handler. * - *
-     * enum BGEvents
-     * {
-     *     BG_EVENT_ON_START                               = 1,    // (event, bg, bgId, instanceId) - Needs to be added to TC
-     *     BG_EVENT_ON_END                                 = 2,    // (event, bg, bgId, instanceId, winner) - Needs to be added to TC
-     *     BG_EVENT_ON_CREATE                              = 3,    // (event, bg, bgId, instanceId) - Needs to be added to TC
-     *     BG_EVENT_ON_PRE_DESTROY                         = 4,    // (event, bg, bgId, instanceId) - Needs to be added to TC
-     *     BG_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, BG_EVENT_ON_START, "MAP", , "Needs to be added to TC"] + * @values [2, BG_EVENT_ON_END, "MAP", , "Needs to be added to TC"] + * @values [3, BG_EVENT_ON_CREATE, "MAP", , "Needs to be added to TC"] + * @values [4, BG_EVENT_ON_PRE_DESTROY, "MAP", , "Needs to be added to TC"] * * @proto cancel = (event, function) * @proto cancel = (event, function, shots) * - * @param uint32 event : [BattleGround] event Id, refer to BGEvents above + * @param uint32 event : [BattleGround] event Id, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -934,22 +910,21 @@ namespace LuaGlobalFunctions /** * Registers a [WorldPacket] event handler. * - *
-     * enum PacketEvents
-     * {
-     *     PACKET_EVENT_ON_PACKET_RECEIVE          =     5,       // (event, packet, player) - Player only if accessible. Can return false, newPacket
-     *     PACKET_EVENT_ON_PACKET_RECEIVE_UNKNOWN  =     6,       // Not Implemented
-     *     PACKET_EVENT_ON_PACKET_SEND             =     7,       // (event, packet, player) - Player only if accessible. Can return false, newPacket
+     * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state.
+     *
+     * In Compatibility mode, all events are registered to the WORLD state (-1).
      *
-     *     PACKET_EVENT_COUNT
-     * };
-     * 
+ * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [5, PACKET_EVENT_ON_PACKET_RECEIVE, "WORLD", , "Player only if accessible. Can return false, newPacket"] + * @values [6, PACKET_EVENT_ON_PACKET_RECEIVE_UNKNOWN, "", "", "Not Implemented"] + * @values [7, PACKET_EVENT_ON_PACKET_SEND, "WORLD", , "Player only if accessible. Can return false, newPacket"] * * @proto cancel = (entry, event, function) * @proto cancel = (entry, event, function, shots) * * @param uint32 entry : opcode - * @param uint32 event : packet event Id, refer to PacketEvents above + * @param uint32 event : packet event Id, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -963,20 +938,20 @@ namespace LuaGlobalFunctions /** * Registers a [Creature] gossip event handler. * - *
-     * enum GossipEvents
-     * {
-     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
-     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
-     *     GOSSIP_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, GOSSIP_EVENT_ON_HELLO, "MAP", , "Object is the Creature/GameObject/Item. Can return false to do default action."] + * @values [2, GOSSIP_EVENT_ON_SELECT, "MAP", , "Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action."] * * @proto cancel = (entry, event, function) * @proto cancel = (entry, event, function, shots) * * @param uint32 entry : [Creature] entry Id - * @param uint32 event : [Creature] gossip event Id, refer to GossipEvents above + * @param uint32 event : [Creature] gossip event Id, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -990,20 +965,20 @@ namespace LuaGlobalFunctions /** * Registers a [GameObject] gossip event handler. * - *
-     * enum GossipEvents
-     * {
-     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
-     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
-     *     GOSSIP_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, GOSSIP_EVENT_ON_HELLO, "MAP", , "Object is the Creature/GameObject/Item. Can return false to do default action."] + * @values [2, GOSSIP_EVENT_ON_SELECT, "MAP", , "Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action."] * * @proto cancel = (entry, event, function) * @proto cancel = (entry, event, function, shots) * * @param uint32 entry : [GameObject] entry Id - * @param uint32 event : [GameObject] gossip event Id, refer to GossipEvents above + * @param uint32 event : [GameObject] gossip event Id, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -1017,23 +992,23 @@ namespace LuaGlobalFunctions /** * Registers an [Item] event handler. * - *
-     * enum ItemEvents
-     * {
-     *     ITEM_EVENT_ON_DUMMY_EFFECT                      = 1,    // (event, caster, spellid, effindex, item)
-     *     ITEM_EVENT_ON_USE                               = 2,    // (event, player, item, target) - Can return false to stop the spell casting
-     *     ITEM_EVENT_ON_QUEST_ACCEPT                      = 3,    // (event, player, item, quest) - Can return true
-     *     ITEM_EVENT_ON_EXPIRE                            = 4,    // (event, player, itemid) - Can return true
-     *     ITEM_EVENT_ON_REMOVE                            = 5,    // (event, player, item) - Can return true
-     *     ITEM_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, ITEM_EVENT_ON_DUMMY_EFFECT, "MAP", , ""] + * @values [2, ITEM_EVENT_ON_USE, "MAP", , "Can return false to stop the spell casting"] + * @values [3, ITEM_EVENT_ON_QUEST_ACCEPT, "MAP", , "Can return true"] + * @values [4, ITEM_EVENT_ON_EXPIRE, "MAP", , "Can return true"] + * @values [5, ITEM_EVENT_ON_REMOVE, "MAP", , "Can return true"] * * @proto cancel = (entry, event, function) * @proto cancel = (entry, event, function, shots) * * @param uint32 entry : [Item] entry Id - * @param uint32 event : [Item] event Id, refer to ItemEvents above + * @param uint32 event : [Item] event Id, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -1047,20 +1022,20 @@ namespace LuaGlobalFunctions /** * Registers an [Item] gossip event handler. * - *
-     * enum GossipEvents
-     * {
-     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
-     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
-     *     GOSSIP_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, GOSSIP_EVENT_ON_HELLO, "MAP", , "Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting."] + * @values [2, GOSSIP_EVENT_ON_SELECT, "MAP", , "Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action."] * * @proto cancel = (entry, event, function) * @proto cancel = (entry, event, function, shots) * * @param uint32 entry : [Item] entry Id - * @param uint32 event : [Item] gossip event Id, refer to GossipEvents above + * @param uint32 event : [Item] gossip event Id, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -1074,22 +1049,22 @@ namespace LuaGlobalFunctions /** * Registers a [Map] event handler for all instance of a [Map]. * - *
-     * enum InstanceEvents
-     * {
-     *     INSTANCE_EVENT_ON_INITIALIZE                    = 1,    // (event, instance_data, map)
-     *     INSTANCE_EVENT_ON_LOAD                          = 2,    // (event, instance_data, map)
-     *     INSTANCE_EVENT_ON_UPDATE                        = 3,    // (event, instance_data, map, diff)
-     *     INSTANCE_EVENT_ON_PLAYER_ENTER                  = 4,    // (event, instance_data, map, player)
-     *     INSTANCE_EVENT_ON_CREATURE_CREATE               = 5,    // (event, instance_data, map, creature)
-     *     INSTANCE_EVENT_ON_GAMEOBJECT_CREATE             = 6,    // (event, instance_data, map, go)
-     *     INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS   = 7,    // (event, instance_data, map)
-     *     INSTANCE_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, INSTANCE_EVENT_ON_INITIALIZE, "MAP", , ""] + * @values [2, INSTANCE_EVENT_ON_LOAD, "MAP", , ""] + * @values [3, INSTANCE_EVENT_ON_UPDATE, "MAP", , ""] + * @values [4, INSTANCE_EVENT_ON_PLAYER_ENTER, "MAP", , ""] + * @values [5, INSTANCE_EVENT_ON_CREATURE_CREATE, "MAP", , ""] + * @values [6, INSTANCE_EVENT_ON_GAMEOBJECT_CREATE, "MAP", , ""] + * @values [7, INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS, "MAP", , ""] * * @param uint32 map_id : ID of a [Map] - * @param uint32 event : [Map] event ID, refer to MapEvents above + * @param uint32 event : [Map] event ID, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" */ @@ -1101,22 +1076,22 @@ namespace LuaGlobalFunctions /** * Registers a [Map] event handler for one instance of a [Map]. * - *
-     * enum InstanceEvents
-     * {
-     *     INSTANCE_EVENT_ON_INITIALIZE                    = 1,    // (event, instance_data, map)
-     *     INSTANCE_EVENT_ON_LOAD                          = 2,    // (event, instance_data, map)
-     *     INSTANCE_EVENT_ON_UPDATE                        = 3,    // (event, instance_data, map, diff)
-     *     INSTANCE_EVENT_ON_PLAYER_ENTER                  = 4,    // (event, instance_data, map, player)
-     *     INSTANCE_EVENT_ON_CREATURE_CREATE               = 5,    // (event, instance_data, map, creature)
-     *     INSTANCE_EVENT_ON_GAMEOBJECT_CREATE             = 6,    // (event, instance_data, map, go)
-     *     INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS   = 7,    // (event, instance_data, map)
-     *     INSTANCE_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, INSTANCE_EVENT_ON_INITIALIZE, "MAP", , ""] + * @values [2, INSTANCE_EVENT_ON_LOAD, "MAP", , ""] + * @values [3, INSTANCE_EVENT_ON_UPDATE, "MAP", , ""] + * @values [4, INSTANCE_EVENT_ON_PLAYER_ENTER, "MAP", , ""] + * @values [5, INSTANCE_EVENT_ON_CREATURE_CREATE, "MAP", , ""] + * @values [6, INSTANCE_EVENT_ON_GAMEOBJECT_CREATE, "MAP", , ""] + * @values [7, INSTANCE_EVENT_ON_CHECK_ENCOUNTER_IN_PROGRESS, "MAP", , ""] * * @param uint32 instance_id : ID of an instance of a [Map] - * @param uint32 event : [Map] event ID, refer to MapEvents above + * @param uint32 event : [Map] event ID, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" */ @@ -1128,22 +1103,22 @@ namespace LuaGlobalFunctions /** * Registers a [Player] gossip event handler. * + * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * * Note that you can not use `GOSSIP_EVENT_ON_HELLO` with this hook. It does nothing since players dont have an "on hello". * - *
-     * enum GossipEvents
-     * {
-     *     GOSSIP_EVENT_ON_HELLO                           = 1,    // (event, player, object) - Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting.
-     *     GOSSIP_EVENT_ON_SELECT                          = 2,    // (event, player, object, sender, intid, code, menu_id) - Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action.
-     *     GOSSIP_EVENT_COUNT
-     * };
-     * 
+ * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, GOSSIP_EVENT_ON_HELLO, "MAP", , "Object is the Creature/GameObject/Item. Can return false to do default action. For item gossip can return false to stop spell casting."] + * @values [2, GOSSIP_EVENT_ON_SELECT, "MAP", , "Object is the Creature/GameObject/Item/Player, menu_id is only for player gossip. Can return false to do default action."] * * @proto cancel = (menu_id, event, function) * @proto cancel = (menu_id, event, function, shots) * * @param uint32 menu_id : [Player] gossip menu Id - * @param uint32 event : [Player] gossip event Id, refer to GossipEvents above + * @param uint32 event : [Player] gossip event Id, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -1157,64 +1132,55 @@ namespace LuaGlobalFunctions /** * Registers a [Creature] event handler. * - *
-     * enum CreatureEvents
-     * {
-     *     CREATURE_EVENT_ON_ENTER_COMBAT                       = 1,  // (event, creature, target) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_LEAVE_COMBAT                       = 2,  // (event, creature) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_TARGET_DIED                        = 3,  // (event, creature, victim) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_DIED                               = 4,  // (event, creature, killer) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_SPAWN                              = 5,  // (event, creature) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_REACH_WP                           = 6,  // (event, creature, type, id) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_AIUPDATE                           = 7,  // (event, creature, diff) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_RECEIVE_EMOTE                      = 8,  // (event, creature, player, emoteid) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_DAMAGE_TAKEN                       = 9,  // (event, creature, attacker, damage) - Can return true to stop normal action, can return new damage as second return value.
-     *     CREATURE_EVENT_ON_PRE_COMBAT                         = 10, // (event, creature, target) - Can return true to stop normal action
-     *     // UNUSED
-     *     CREATURE_EVENT_ON_OWNER_ATTACKED                     = 12, // (event, creature, target) - Can return true to stop normal action            // Not on mangos
-     *     CREATURE_EVENT_ON_OWNER_ATTACKED_AT                  = 13, // (event, creature, attacker) - Can return true to stop normal action          // Not on mangos
-     *     CREATURE_EVENT_ON_HIT_BY_SPELL                       = 14, // (event, creature, caster, spellid) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_SPELL_HIT_TARGET                   = 15, // (event, creature, target, spellid) - Can return true to stop normal action
-     *     // UNUSED                                            = 16, // (event, creature)
-     *     // UNUSED                                            = 17, // (event, creature)
-     *     // UNUSED                                            = 18, // (event, creature)
-     *     CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE             = 19, // (event, creature, summon) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN          = 20, // (event, creature, summon) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED             = 21, // (event, creature, summon, killer) - Can return true to stop normal action    // Not on mangos
-     *     CREATURE_EVENT_ON_SUMMONED                           = 22, // (event, creature, summoner) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_RESET                              = 23, // (event, creature)
-     *     CREATURE_EVENT_ON_REACH_HOME                         = 24, // (event, creature) - Can return true to stop normal action
-     *     // UNUSED                                            = 25, // (event, creature)
-     *     CREATURE_EVENT_ON_CORPSE_REMOVED                     = 26, // (event, creature, respawndelay) - Can return true to stop normal action, can return new respawndelay as second return value
-     *     CREATURE_EVENT_ON_MOVE_IN_LOS                        = 27, // (event, creature, unit) - Can return true to stop normal action. Does not actually check LOS, just uses the sight range
-     *     // UNUSED                                            = 28, // (event, creature)
-     *     // UNUSED                                            = 29, // (event, creature)
-     *     CREATURE_EVENT_ON_DUMMY_EFFECT                       = 30, // (event, caster, spellid, effindex, creature)
-     *     CREATURE_EVENT_ON_QUEST_ACCEPT                       = 31, // (event, player, creature, quest) - Can return true
-     *     // UNUSED                                            = 32, // (event, creature)
-     *     // UNUSED                                            = 33, // (event, creature)
-     *     CREATURE_EVENT_ON_QUEST_REWARD                       = 34, // (event, player, creature, quest, opt) - Can return true
-     *     CREATURE_EVENT_ON_DIALOG_STATUS                      = 35, // (event, player, creature)
-     *     CREATURE_EVENT_ON_ADD                                = 36, // (event, creature)
-     *     CREATURE_EVENT_ON_REMOVE                             = 37, // (event, creature)
-     *     CREATURE_EVENT_ON_AURA_APPLY                         = 38, // (event, creature, aura)
-     *     CREATURE_EVENT_ON_HEAL                               = 39, // (event, creature, target, heal) - Can return new heal amount
-     *     CREATURE_EVENT_ON_DAMAGE                             = 40, // (event, creature, target, damage) - Can return new damage amount
-     *     CREATURE_EVENT_ON_AURA_REMOVE                        = 41, // (event, creature, aura, remove_mode)
-     *     CREATURE_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK  = 42, // (event, creature, target, damage, spellInfo) - Can return new damage amount
-     *     CREATURE_EVENT_ON_MODIFY_MELEE_DAMAGE                = 43, // (event, creature, target, damage) - Can return new damage amount
-     *     CREATURE_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN          = 44, // (event, creature, target, damage, spellInfo) - Can return new damage amount
-     *     CREATURE_EVENT_ON_MODIFY_HEAL_RECEIVED               = 45, // (event, creature, target, heal, spellInfo) - Can return new heal amount
-     *     CREATURE_EVENT_ON_DEAL_DAMAGE                        = 46, // (event, creature, target, damage, damagetype) - Can return new damage amount
-     *     CREATURE_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, CREATURE_EVENT_ON_ENTER_COMBAT, "MAP", , "Can return true to stop normal action"] + * @values [2, CREATURE_EVENT_ON_LEAVE_COMBAT, "MAP", , "Can return true to stop normal action"] + * @values [3, CREATURE_EVENT_ON_TARGET_DIED, "MAP", , "Can return true to stop normal action"] + * @values [4, CREATURE_EVENT_ON_DIED, "MAP", , "Can return true to stop normal action"] + * @values [5, CREATURE_EVENT_ON_SPAWN, "MAP", , "Can return true to stop normal action"] + * @values [6, CREATURE_EVENT_ON_REACH_WP, "MAP", , "Can return true to stop normal action"] + * @values [7, CREATURE_EVENT_ON_AIUPDATE, "MAP", , "Can return true to stop normal action"] + * @values [8, CREATURE_EVENT_ON_RECEIVE_EMOTE, "MAP", , "Can return true to stop normal action"] + * @values [9, CREATURE_EVENT_ON_DAMAGE_TAKEN, "MAP", , "Can return true to stop normal action, can return new damage as second return value."] + * @values [10, CREATURE_EVENT_ON_PRE_COMBAT, "MAP", , "Can return true to stop normal action"] + * @values [12, CREATURE_EVENT_ON_OWNER_ATTACKED, "MAP", , "Can return true to stop normal action. Not on mangos"] + * @values [13, CREATURE_EVENT_ON_OWNER_ATTACKED_AT, "MAP", , "Can return true to stop normal action. Not on mangos"] + * @values [14, CREATURE_EVENT_ON_HIT_BY_SPELL, "MAP", , "Can return true to stop normal action"] + * @values [15, CREATURE_EVENT_ON_SPELL_HIT_TARGET, "MAP", , "Can return true to stop normal action"] + * @values [19, CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, "MAP", , "Can return true to stop normal action"] + * @values [20, CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, "MAP", , "Can return true to stop normal action"] + * @values [21, CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, "MAP", , "Can return true to stop normal action. Not on mangos"] + * @values [22, CREATURE_EVENT_ON_SUMMONED, "MAP", , "Can return true to stop normal action"] + * @values [23, CREATURE_EVENT_ON_RESET, "MAP", , ""] + * @values [24, CREATURE_EVENT_ON_REACH_HOME, "MAP", , "Can return true to stop normal action"] + * @values [26, CREATURE_EVENT_ON_CORPSE_REMOVED, "MAP", , "Can return true to stop normal action, can return new respawndelay as second return value"] + * @values [27, CREATURE_EVENT_ON_MOVE_IN_LOS, "MAP", , "Can return true to stop normal action. Does not actually check LOS, just uses the sight range"] + * @values [30, CREATURE_EVENT_ON_DUMMY_EFFECT, "MAP", , ""] + * @values [31, CREATURE_EVENT_ON_QUEST_ACCEPT, "MAP", , "Can return true"] + * @values [34, CREATURE_EVENT_ON_QUEST_REWARD, "MAP", , "Can return true"] + * @values [35, CREATURE_EVENT_ON_DIALOG_STATUS, "MAP", , ""] + * @values [36, CREATURE_EVENT_ON_ADD, "MAP", , ""] + * @values [37, CREATURE_EVENT_ON_REMOVE, "MAP", , ""] + * @values [38, CREATURE_EVENT_ON_AURA_APPLY, "MAP", , ""] + * @values [39, CREATURE_EVENT_ON_HEAL, "MAP", , "Can return new heal amount"] + * @values [40, CREATURE_EVENT_ON_DAMAGE, "MAP", , "Can return new damage amount"] + * @values [41, CREATURE_EVENT_ON_AURA_REMOVE, "MAP", , ""] + * @values [42, CREATURE_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK, "MAP", , "Can return new damage amount"] + * @values [43, CREATURE_EVENT_ON_MODIFY_MELEE_DAMAGE, "MAP", , "Can return new damage amount"] + * @values [44, CREATURE_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN, "MAP", , "Can return new damage amount"] + * @values [45, CREATURE_EVENT_ON_MODIFY_HEAL_RECEIVED, "MAP", , "Can return new heal amount"] + * @values [46, CREATURE_EVENT_ON_DEAL_DAMAGE, "MAP", , "Can return new damage amount"] * * @proto cancel = (entry, event, function) * @proto cancel = (entry, event, function, shots) * * @param uint32 entry : the ID of one or more [Creature]s - * @param uint32 event : refer to CreatureEvents above + * @param uint32 event : refer to table above * @param function function : function that will be called when the event occurs * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -1228,65 +1194,56 @@ namespace LuaGlobalFunctions /** * Registers a [Creature] event handler for a *single* [Creature]. * - *
-     * enum CreatureEvents
-     * {
-     *     CREATURE_EVENT_ON_ENTER_COMBAT                    = 1,  // (event, creature, target) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_LEAVE_COMBAT                    = 2,  // (event, creature) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_TARGET_DIED                     = 3,  // (event, creature, victim) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_DIED                            = 4,  // (event, creature, killer) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_SPAWN                           = 5,  // (event, creature) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_REACH_WP                        = 6,  // (event, creature, type, id) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_AIUPDATE                        = 7,  // (event, creature, diff) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_RECEIVE_EMOTE                   = 8,  // (event, creature, player, emoteid) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_DAMAGE_TAKEN                    = 9,  // (event, creature, attacker, damage) - Can return true to stop normal action, can return new damage as second return value.
-     *     CREATURE_EVENT_ON_PRE_COMBAT                      = 10, // (event, creature, target) - Can return true to stop normal action
-     *     // UNUSED
-     *     CREATURE_EVENT_ON_OWNER_ATTACKED                  = 12, // (event, creature, target) - Can return true to stop normal action            // Not on mangos
-     *     CREATURE_EVENT_ON_OWNER_ATTACKED_AT               = 13, // (event, creature, attacker) - Can return true to stop normal action          // Not on mangos
-     *     CREATURE_EVENT_ON_HIT_BY_SPELL                    = 14, // (event, creature, caster, spellid) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_SPELL_HIT_TARGET                = 15, // (event, creature, target, spellid) - Can return true to stop normal action
-     *     // UNUSED                                         = 16, // (event, creature)
-     *     // UNUSED                                         = 17, // (event, creature)
-     *     // UNUSED                                         = 18, // (event, creature)
-     *     CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE          = 19, // (event, creature, summon) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN       = 20, // (event, creature, summon) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED          = 21, // (event, creature, summon, killer) - Can return true to stop normal action    // Not on mangos
-     *     CREATURE_EVENT_ON_SUMMONED                        = 22, // (event, creature, summoner) - Can return true to stop normal action
-     *     CREATURE_EVENT_ON_RESET                           = 23, // (event, creature)
-     *     CREATURE_EVENT_ON_REACH_HOME                      = 24, // (event, creature) - Can return true to stop normal action
-     *     // UNUSED                                         = 25, // (event, creature)
-     *     CREATURE_EVENT_ON_CORPSE_REMOVED                  = 26, // (event, creature, respawndelay) - Can return true to stop normal action, can return new respawndelay as second return value
-     *     CREATURE_EVENT_ON_MOVE_IN_LOS                     = 27, // (event, creature, unit) - Can return true to stop normal action. Does not actually check LOS, just uses the sight range
-     *     // UNUSED                                         = 28, // (event, creature)
-     *     // UNUSED                                         = 29, // (event, creature)
-     *     CREATURE_EVENT_ON_DUMMY_EFFECT                    = 30, // (event, caster, spellid, effindex, creature)
-     *     CREATURE_EVENT_ON_QUEST_ACCEPT                    = 31, // (event, player, creature, quest) - Can return true
-     *     // UNUSED                                         = 32, // (event, creature)
-     *     // UNUSED                                         = 33, // (event, creature)
-     *     CREATURE_EVENT_ON_QUEST_REWARD                    = 34, // (event, player, creature, quest, opt) - Can return true
-     *     CREATURE_EVENT_ON_DIALOG_STATUS                   = 35, // (event, player, creature)
-     *     CREATURE_EVENT_ON_ADD                             = 36, // (event, creature)
-     *     CREATURE_EVENT_ON_REMOVE                          = 37, // (event, creature)
-     *     CREATURE_EVENT_ON_AURA_APPLY                      = 38, // (event, creature, aura)
-     *     CREATURE_EVENT_ON_HEAL                            = 39, // (event, creature, target, gain) - Can return new heal amount
-     *     CREATURE_EVENT_ON_DAMAGE                          = 40, // (event, creature, target, damage) - Can return new damage amount
-     *     CREATURE_EVENT_ON_AURA_REMOVE                     = 41, // (event, creature, aura, remove_mode)
-     *     CREATURE_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK = 42, // (event, creature, target, damage, spellInfo) - Can return new damage amount
-     *     CREATURE_EVENT_ON_MODIFY_MELEE_DAMAGE            = 43, // (event, creature, target, damage) - Can return new damage amount
-     *     CREATURE_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN      = 44, // (event, creature, target, damage, spellInfo) - Can return new damage amount
-     *     CREATURE_EVENT_ON_MODIFY_HEAL_RECEIVED           = 45, // (event, creature, target, heal, spellInfo) - Can return new heal amount
-     *     CREATURE_EVENT_ON_DEAL_DAMAGE                    = 46, // (event, creature, target, damage, damagetype) - Can return new damage amount
-     *     CREATURE_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, CREATURE_EVENT_ON_ENTER_COMBAT, "MAP", , "Can return true to stop normal action"] + * @values [2, CREATURE_EVENT_ON_LEAVE_COMBAT, "MAP", , "Can return true to stop normal action"] + * @values [3, CREATURE_EVENT_ON_TARGET_DIED, "MAP", , "Can return true to stop normal action"] + * @values [4, CREATURE_EVENT_ON_DIED, "MAP", , "Can return true to stop normal action"] + * @values [5, CREATURE_EVENT_ON_SPAWN, "MAP", , "Can return true to stop normal action"] + * @values [6, CREATURE_EVENT_ON_REACH_WP, "MAP", , "Can return true to stop normal action"] + * @values [7, CREATURE_EVENT_ON_AIUPDATE, "MAP", , "Can return true to stop normal action"] + * @values [8, CREATURE_EVENT_ON_RECEIVE_EMOTE, "MAP", , "Can return true to stop normal action"] + * @values [9, CREATURE_EVENT_ON_DAMAGE_TAKEN, "MAP", , "Can return true to stop normal action, can return new damage as second return value."] + * @values [10, CREATURE_EVENT_ON_PRE_COMBAT, "MAP", , "Can return true to stop normal action"] + * @values [12, CREATURE_EVENT_ON_OWNER_ATTACKED, "MAP", , "Can return true to stop normal action. Not on mangos"] + * @values [13, CREATURE_EVENT_ON_OWNER_ATTACKED_AT, "MAP", , "Can return true to stop normal action. Not on mangos"] + * @values [14, CREATURE_EVENT_ON_HIT_BY_SPELL, "MAP", , "Can return true to stop normal action"] + * @values [15, CREATURE_EVENT_ON_SPELL_HIT_TARGET, "MAP", , "Can return true to stop normal action"] + * @values [19, CREATURE_EVENT_ON_JUST_SUMMONED_CREATURE, "MAP", , "Can return true to stop normal action"] + * @values [20, CREATURE_EVENT_ON_SUMMONED_CREATURE_DESPAWN, "MAP", , "Can return true to stop normal action"] + * @values [21, CREATURE_EVENT_ON_SUMMONED_CREATURE_DIED, "MAP", , "Can return true to stop normal action. Not on mangos"] + * @values [22, CREATURE_EVENT_ON_SUMMONED, "MAP", , "Can return true to stop normal action"] + * @values [23, CREATURE_EVENT_ON_RESET, "MAP", , ""] + * @values [24, CREATURE_EVENT_ON_REACH_HOME, "MAP", , "Can return true to stop normal action"] + * @values [26, CREATURE_EVENT_ON_CORPSE_REMOVED, "MAP", , "Can return true to stop normal action, can return new respawndelay as second return value"] + * @values [27, CREATURE_EVENT_ON_MOVE_IN_LOS, "MAP", , "Can return true to stop normal action. Does not actually check LOS, just uses the sight range"] + * @values [30, CREATURE_EVENT_ON_DUMMY_EFFECT, "MAP", , ""] + * @values [31, CREATURE_EVENT_ON_QUEST_ACCEPT, "MAP", , "Can return true"] + * @values [34, CREATURE_EVENT_ON_QUEST_REWARD, "MAP", , "Can return true"] + * @values [35, CREATURE_EVENT_ON_DIALOG_STATUS, "MAP", , ""] + * @values [36, CREATURE_EVENT_ON_ADD, "MAP", , ""] + * @values [37, CREATURE_EVENT_ON_REMOVE, "MAP", , ""] + * @values [38, CREATURE_EVENT_ON_AURA_APPLY, "MAP", , ""] + * @values [39, CREATURE_EVENT_ON_HEAL, "MAP", , "Can return new heal amount"] + * @values [40, CREATURE_EVENT_ON_DAMAGE, "MAP", , "Can return new damage amount"] + * @values [41, CREATURE_EVENT_ON_AURA_REMOVE, "MAP", , ""] + * @values [42, CREATURE_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK, "MAP", , "Can return new damage amount"] + * @values [43, CREATURE_EVENT_ON_MODIFY_MELEE_DAMAGE, "MAP", , "Can return new damage amount"] + * @values [44, CREATURE_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN, "MAP", , "Can return new damage amount"] + * @values [45, CREATURE_EVENT_ON_MODIFY_HEAL_RECEIVED, "MAP", , "Can return new heal amount"] + * @values [46, CREATURE_EVENT_ON_DEAL_DAMAGE, "MAP", , "Can return new damage amount"] * * @proto cancel = (guid, instance_id, event, function) * @proto cancel = (guid, instance_id, event, function, shots) * * @param ObjectGuid guid : the GUID of a single [Creature] * @param uint32 instance_id : the instance ID of a single [Creature] - * @param uint32 event : refer to CreatureEvents above + * @param uint32 event : refer to table above * @param function function : function that will be called when the event occurs * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -1300,32 +1257,31 @@ namespace LuaGlobalFunctions /** * Registers a [GameObject] event handler. * - *
-     * enum GameObjectEvents
-     * {
-     *     GAMEOBJECT_EVENT_ON_AIUPDATE                    = 1,    // (event, go, diff)
-     *     GAMEOBJECT_EVENT_ON_SPAWN                       = 2,    // (event, go)
-     *     GAMEOBJECT_EVENT_ON_DUMMY_EFFECT                = 3,    // (event, caster, spellid, effindex, go) - Can return true to stop normal action
-     *     GAMEOBJECT_EVENT_ON_QUEST_ACCEPT                = 4,    // (event, player, go, quest) - Can return true to stop normal action
-     *     GAMEOBJECT_EVENT_ON_QUEST_REWARD                = 5,    // (event, player, go, quest, opt) - Can return true to stop normal action
-     *     GAMEOBJECT_EVENT_ON_DIALOG_STATUS               = 6,    // (event, player, go)
-     *     GAMEOBJECT_EVENT_ON_DESTROYED                   = 7,    // (event, go, attacker)
-     *     GAMEOBJECT_EVENT_ON_DAMAGED                     = 8,    // (event, go, attacker)
-     *     GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE           = 9,    // (event, go, state)
-     *     GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED            = 10,   // (event, go, state)
-     *     // UNUSED                                       = 11,   // (event, gameobject)
-     *     GAMEOBJECT_EVENT_ON_ADD                         = 12,   // (event, gameobject)
-     *     GAMEOBJECT_EVENT_ON_REMOVE                      = 13,   // (event, gameobject)
-     *     GAMEOBJECT_EVENT_ON_USE                         = 14,   // (event, go, player) - Can return true to stop normal action
-     *     GAMEOBJECT_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, GAMEOBJECT_EVENT_ON_AIUPDATE, "MAP", , ""] + * @values [2, GAMEOBJECT_EVENT_ON_SPAWN, "MAP", , ""] + * @values [3, GAMEOBJECT_EVENT_ON_DUMMY_EFFECT, "MAP", , "Can return true to stop normal action"] + * @values [4, GAMEOBJECT_EVENT_ON_QUEST_ACCEPT, "MAP", , "Can return true to stop normal action"] + * @values [5, GAMEOBJECT_EVENT_ON_QUEST_REWARD, "MAP", , "Can return true to stop normal action"] + * @values [6, GAMEOBJECT_EVENT_ON_DIALOG_STATUS, "MAP", , ""] + * @values [7, GAMEOBJECT_EVENT_ON_DESTROYED, "MAP", , ""] + * @values [8, GAMEOBJECT_EVENT_ON_DAMAGED, "MAP", , ""] + * @values [9, GAMEOBJECT_EVENT_ON_LOOT_STATE_CHANGE, "MAP", , ""] + * @values [10, GAMEOBJECT_EVENT_ON_GO_STATE_CHANGED, "MAP", , ""] + * @values [12, GAMEOBJECT_EVENT_ON_ADD, "MAP", , ""] + * @values [13, GAMEOBJECT_EVENT_ON_REMOVE, "MAP", , ""] + * @values [14, GAMEOBJECT_EVENT_ON_USE, "MAP", , "Can return true to stop normal action"] * * @proto cancel = (entry, event, function) * @proto cancel = (entry, event, function, shots) * * @param uint32 entry : [GameObject] entry Id - * @param uint32 event : [GameObject] event Id, refer to GameObjectEvents above + * @param uint32 event : [GameObject] event Id, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" * @@ -1339,19 +1295,19 @@ namespace LuaGlobalFunctions /** * Registers a [Ticket] event handler. * - *
-     * enum TicketEvents
-     * {
-     *     TICKET_EVENT_ON_CREATE                          = 1,    // (event, player, ticket)
-     *     TICKET_EVENT_ON_UPDATE                          = 2,    // (event, player, ticket, message)
-     *     TICKET_EVENT_ON_CLOSE                           = 3,    // (event, player, ticket)
-     *     TICKET_EVENT_STATUS_UPDATE                      = 4,    // (event, player, ticket)
-     *     TICKET_EVENT_ON_RESOLVE                         = 5,    // (event, player, ticket)
-     *     TICKET_EVENT_COUNT
-     * };
-     * 
- * - * @param uint32 event : event ID, refer to UnitEvents above + * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, TICKET_EVENT_ON_CREATE, "WORLD", , ""] + * @values [2, TICKET_EVENT_ON_UPDATE, "WORLD", , ""] + * @values [3, TICKET_EVENT_ON_CLOSE, "WORLD", , ""] + * @values [4, TICKET_EVENT_STATUS_UPDATE, "WORLD", , ""] + * @values [5, TICKET_EVENT_ON_RESOLVE, "WORLD", , ""] + * + * @param uint32 event : event ID, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" */ @@ -1363,18 +1319,18 @@ namespace LuaGlobalFunctions /** * Registers a [Spell] event handler. * - *
-     * enum SpellEvents
-     * {
-     *     SPELL_EVENT_ON_PREPARE                          = 1, // (event, caster, spell)
-     *     SPELL_EVENT_ON_CAST                             = 2, // (event, caster, spell, skipCheck)
-     *     SPELL_EVENT_ON_CAST_CANCEL                      = 3, // (event, caster, spell, bySelf)
-     *     SPELL_EVENT_COUNT
-     * };
-     * 
+ * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, SPELL_EVENT_ON_PREPARE, "MAP", , ""] + * @values [2, SPELL_EVENT_ON_CAST, "MAP", , ""] + * @values [3, SPELL_EVENT_ON_CAST_CANCEL, "MAP", , ""] * * @param uint32 entry : [Spell] entry Id - * @param uint32 event : event ID, refer to SpellEvents above + * @param uint32 event : event ID, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" */ @@ -1386,27 +1342,27 @@ namespace LuaGlobalFunctions /** * Registers a [Creature] event handler. It used AllCreatureScript so this don't need creature entry as a key. * - *
-     * enum AllCreatureEvents
-     * {
-     *     ALL_CREATURE_EVENT_ON_ADD                               = 1, // (event, creature)
-     *     ALL_CREATURE_EVENT_ON_REMOVE                            = 2, // (event, creature)
-     *     ALL_CREATURE_EVENT_ON_SELECT_LEVEL                      = 3, // (event, creature_template, creature)
-     *     ALL_CREATURE_EVENT_ON_BEFORE_SELECT_LEVEL               = 4, // (event, creature_template, creature, level) - Can return the new level
-     *     ALL_CREATURE_EVENT_ON_AURA_APPLY                        = 5, // (event, creature, aura)
-     *     ALL_CREATURE_EVENT_ON_HEAL                              = 6, // (event, creature, target, gain) - Can return new heal amount
-     *     ALL_CREATURE_EVENT_ON_DAMAGE                            = 7, // (event, creature, target, damage) - Can return new damage amount
-     *     ALL_CREATURE_EVENT_ON_AURA_REMOVE                       = 8, // (event, creature, aura, remove_mode)
-     *     ALL_CREATURE_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK = 9, // (event, creature, target, damage, spellInfo) - Can return new damage amount
-     *     ALL_CREATURE_EVENT_ON_MODIFY_MELEE_DAMAGE               = 10, // (event, creature, target, damage) - Can return new damage amount
-     *     ALL_CREATURE_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN         = 11, // (event, creature, target, damage, spellInfo) - Can return new damage amount
-     *     ALL_CREATURE_EVENT_ON_MODIFY_HEAL_RECEIVED              = 12, // (event, creature, target, heal, spellInfo) - Can return new heal amount
-     *     ALL_CREATURE_EVENT_ON_DEAL_DAMAGE                       = 13, // (event, creature, target, damage, damagetype) - Can return new damage amount
-     *     ALL_CREATURE_EVENT_COUNT
-     * };
-     * 
- * - * @param uint32 event : event ID, refer to AllCreatureEvents above + * In Multistate mode (default), events are either registered to the WORLD state (-1) or the MAP states (map ID). These events will only ever trigger on their respective state. + * + * In Compatibility mode, all events are registered to the WORLD state (-1). + * + * @table + * @columns [ID, Event, State, Parameters, Comment] + * @values [1, ALL_CREATURE_EVENT_ON_ADD, "MAP", , ""] + * @values [2, ALL_CREATURE_EVENT_ON_REMOVE, "MAP", , ""] + * @values [3, ALL_CREATURE_EVENT_ON_SELECT_LEVEL, "MAP", , ""] + * @values [4, ALL_CREATURE_EVENT_ON_BEFORE_SELECT_LEVEL, "MAP", , "Can return the new level"] + * @values [5, ALL_CREATURE_EVENT_ON_AURA_APPLY, "MAP", , ""] + * @values [6, ALL_CREATURE_EVENT_ON_HEAL, "MAP", , "Can return new heal amount"] + * @values [7, ALL_CREATURE_EVENT_ON_DAMAGE, "MAP", , "Can return new damage amount"] + * @values [8, ALL_CREATURE_EVENT_ON_AURA_REMOVE, "MAP", , ""] + * @values [9, ALL_CREATURE_EVENT_ON_MODIFY_PERIODIC_DAMAGE_AURAS_TICK, "MAP", , "Can return new damage amount"] + * @values [10, ALL_CREATURE_EVENT_ON_MODIFY_MELEE_DAMAGE, "MAP", , "Can return new damage amount"] + * @values [11, ALL_CREATURE_EVENT_ON_MODIFY_SPELL_DAMAGE_TAKEN, "MAP", , "Can return new damage amount"] + * @values [12, ALL_CREATURE_EVENT_ON_MODIFY_HEAL_RECEIVED, "MAP", , "Can return new heal amount"] + * @values [13, ALL_CREATURE_EVENT_ON_DEAL_DAMAGE, "MAP", , "Can return new damage amount"] + * + * @param uint32 event : event ID, refer to table above * @param function function : function to register * @param uint32 shots = 0 : the number of times the function will be called, 0 means "always call this function" */