diff --git a/data/sql/updates/pending_db_world/rev_1732397002606741000.sql b/data/sql/updates/pending_db_world/rev_1732397002606741000.sql new file mode 100644 index 000000000..aa37bb210 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1732397002606741000.sql @@ -0,0 +1,3 @@ +-- disable SmartAI for creatures and gameobjects without SmartAI entries +UPDATE `creature_template` SET `AIName` = '' WHERE (`entry` IN (100, 10042, 10158, 1020, 10296, 10337, 10338, 1039, 10639, 11018, 1128, 11327, 114, 11698, 11724, 11725, 11789, 11858, 11918, 1199, 1201, 12160, 1224, 13017, 13159, 14275, 14276, 14369, 14378, 15186, 1520, 1537, 1543, 1547, 1548, 1549, 15591, 15651, 15652, 16054, 16069, 1654, 1655, 1656, 1658, 16591, 16599, 1662, 16764, 1693, 17056, 17405, 17417, 17493, 17558, 1770, 18043, 18075, 18076, 18521, 1869, 1871, 19048, 1934, 1935, 19355, 19421, 19425, 19426, 19432, 19562, 19579, 19580, 19647, 19653, 19686, 1972, 19836, 19932, 20154, 20480, 20520, 20710, 20825, 21456, 2164, 21867, 22134, 22265, 2248, 2275, 23146, 232, 2321, 2322, 2323, 23401, 2347, 23845, 23852, 23853, 23854, 23855, 24043, 24385, 24717, 2473, 2474, 24821, 24826, 24827, 24828, 24829, 24831, 24832, 24837, 24958, 2535, 2536, 25471, 25472, 25473, 2559, 25751, 2578, 2723, 2735, 2736, 2773, 2780, 2781, 2782, 27896, 27897, 27993, 28206, 28355, 28374, 28843, 28878, 2923, 2944, 29500, 29620, 29915, 3, 30315, 30316, 30317, 30318, 30423, 30889, 31195, 31418, 32326, 32364, 32367, 32711, 3285, 3476, 36, 36508, 3722, 37782, 3812, 3814, 39371, 39372, 3988, 3999, 4130, 4388, 4390, 4419, 4620, 4661, 4687, 5061, 5192, 5246, 5253, 5260, 5292, 5293, 5300, 5435, 5461, 5477, 5602, 5622, 5850, 5853, 6020, 6068, 6093, 6233, 6352, 7032, 7067, 7287, 7307, 7369, 756, 757, 822, 8256, 8447, 862, 880, 92, 5287, 4389, 4872)); +UPDATE `gameobject_template` SET `AIName` = '' WHERE (`entry` IN (164881, 164882, 164883, 164884, 173325, 173326, 174609, 174616, 174617, 174618, 174619, 174620, 174621, 174622, 174623, 174624, 174625, 174685, 174687, 174710, 174711, 179829, 186432)); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 44c85241d..4d4a35416 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -296,10 +296,89 @@ void SmartAIMgr::LoadSmartAIFromDB() mEventMap[source_type][temp.entryOrGuid].push_back(temp); } while (result->NextRow()); + CheckIfSmartAIInDatabaseExists(); + LOG_INFO("server.loading", ">> Loaded {} SmartAI scripts in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", " "); } +void SmartAIMgr::CheckIfSmartAIInDatabaseExists() +{ + // SMART_SCRIPT_TYPE_CREATURE + for (auto const& [entry, creatureTemplate] : *sObjectMgr->GetCreatureTemplates()) + { + if (creatureTemplate.AIName != "SmartAI") + continue; + + bool found = false; + + // check template SAI + if (mEventMap[uint32(SmartScriptType::SMART_SCRIPT_TYPE_CREATURE)].find(creatureTemplate.Entry) != mEventMap[uint32(SmartScriptType::SMART_SCRIPT_TYPE_CREATURE)].end()) + found = true; + else + { + // check GUID SAI + for (auto const& pair : sObjectMgr->GetAllCreatureData()) + { + if (pair.second.id1 != creatureTemplate.Entry) + continue; + + if (mEventMap[uint32(SmartScriptType::SMART_SCRIPT_TYPE_CREATURE)].find((-1) * pair.first) != mEventMap[uint32(SmartScriptType::SMART_SCRIPT_TYPE_CREATURE)].end()) + { + found = true; + break; + } + } + } + + if (!found) + LOG_ERROR("sql.sql", "Creature entry ({}) has SmartAI enabled but no SmartAI entries in the database.", creatureTemplate.Entry); + } + + // SMART_SCRIPT_TYPE_GAMEOBJECT + for (auto const& [entry, gameobjectTemplate] : *sObjectMgr->GetGameObjectTemplates()) + { + if (gameobjectTemplate.AIName != "SmartGameObjectAI") + continue; + + bool found = false; + + // check template SAI + if (mEventMap[uint32(SmartScriptType::SMART_SCRIPT_TYPE_GAMEOBJECT)].find(gameobjectTemplate.entry) != mEventMap[uint32(SmartScriptType::SMART_SCRIPT_TYPE_GAMEOBJECT)].end()) + found = true; + else + { + // check GUID SAI + for (auto const& pair : sObjectMgr->GetAllGOData()) + { + if (pair.second.id != gameobjectTemplate.entry) + continue; + + if (mEventMap[uint32(SmartScriptType::SMART_SCRIPT_TYPE_GAMEOBJECT)].find((-1) * pair.first) != mEventMap[uint32(SmartScriptType::SMART_SCRIPT_TYPE_GAMEOBJECT)].end()) + { + found = true; + break; + } + } + } + + if (!found) + LOG_ERROR("sql.sql", "Gameobject entry ({}) has SmartGameobjectAI enabled but no SmartAI entries in the database.", gameobjectTemplate.entry); + } + + // SMART_SCRIPT_TYPE_AREATRIGGER + uint32 scriptID = sObjectMgr->GetScriptId("SmartTrigger"); + + for (auto const& pair : sObjectMgr->GetAllAreaTriggerScriptData()) + { + if (pair.second != scriptID) + continue; + + if (mEventMap[uint32(SmartScriptType::SMART_SCRIPT_TYPE_AREATRIGGER)].find(pair.first) == mEventMap[uint32(SmartScriptType::SMART_SCRIPT_TYPE_AREATRIGGER)].end()) + LOG_ERROR("sql.sql", "AreaTrigger entry ({}) has SmartTrigger enabled but no SmartAI entries in the database.", pair.first); + } +} + /*static*/ bool SmartAIMgr::EventHasInvoker(SMART_EVENT event) { switch (event) diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index be8508e6b..bf414f532 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -2060,6 +2060,7 @@ public: static SmartAIMgr* instance(); void LoadSmartAIFromDB(); + void CheckIfSmartAIInDatabaseExists(); SmartAIEventList GetScript(int32 entry, SmartScriptType type) { diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 8c25ade40..f1d53892e 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -884,6 +884,7 @@ public: [[nodiscard]] AreaTriggerTeleport const* GetGoBackTrigger(uint32 Map) const; [[nodiscard]] AreaTriggerTeleport const* GetMapEntranceTrigger(uint32 Map) const; + [[nodiscard]] AreaTriggerScriptContainer const& GetAllAreaTriggerScriptData() const { return _areaTriggerScriptStore; } uint32 GetAreaTriggerScriptId(uint32 trigger_id); SpellScriptsBounds GetSpellScriptsBounds(uint32 spell_id);