From 45c8f242c292a33ee82c0446b61dc5d67f34c504 Mon Sep 17 00:00:00 2001 From: sogladev Date: Wed, 14 Jan 2026 13:52:01 +0100 Subject: [PATCH] fix(Core/ObjectMgr): warn trainer creature with no gossip_menu_option (#24336) --- .../rev_1767728687116016669.sql | 65 +++++++++++++++++++ src/server/game/Globals/ObjectMgr.cpp | 22 +++++++ 2 files changed, 87 insertions(+) create mode 100644 data/sql/updates/pending_db_world/rev_1767728687116016669.sql diff --git a/data/sql/updates/pending_db_world/rev_1767728687116016669.sql b/data/sql/updates/pending_db_world/rev_1767728687116016669.sql new file mode 100644 index 000000000..25bb621c0 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1767728687116016669.sql @@ -0,0 +1,65 @@ +-- +DELETE FROM `gossip_menu_option` WHERE (`MenuID` IN (1041, 1042, 1465, 1467, 1468, 1469, 2741, 2743, 2749, 2784, 3202, 3203, 4110, 4111, 4117, 4128, 4129, 4134, 4135, 4136, 4138, 4151, 4156, 4160, 4164, 4165, 4169, 4170, 4171, 4184, 4186, 4208, 4211, 4241, 4242, 4244, 4263, 4351, 4356, 4748, 4842, 4843, 7455, 7459, 7512, 7809, 7815, 7820, 7833, 8308, 8460, 8522, 8760, 8863, 9084, 9131, 9132, 10363, 10437, 10568, 21222, 61025)); +INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES +(1041, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(1042, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(1465, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(1467, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(1468, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(1469, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(2741, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(2743, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(2749, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(2784, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(3202, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(3203, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4110, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4111, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4117, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4128, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4129, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4134, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4135, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4136, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4138, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4151, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4156, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4160, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4164, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4165, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4169, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4170, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4171, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4184, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4186, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4208, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4211, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4241, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4242, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4244, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4263, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4351, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4356, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4748, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4842, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(4843, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(7455, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(7459, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(7512, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(7809, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(7815, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(7820, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(7833, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(8308, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(8460, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(8522, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(8760, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(8863, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(9084, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(9131, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(9132, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(10363, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(10437, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(10568, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(21222, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0), +(61025, 0, 3, 'Train me.', 3266, 5, 16, 0, 0, 0, 0, '', 0, 0); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 9e9cf6727..b0f3f5613 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -9629,6 +9629,28 @@ void ObjectMgr::LoadGossipMenuItems() _gossipMenuItemsStore.insert(GossipMenuItemsContainer::value_type(gMenuItem.MenuID, gMenuItem)); } while (result->NextRow()); + // Warn if any trainer creature templates reference a GossipMenuId that has no gossip_menu_option entries + // This will cause the gossip menu to fallback to MenuID 0 at runtime which will display: "I wish to unlearn my talents." + std::set checkedMenuIds; + for (auto const& [entry, tmpl] : _creatureTemplateStore) + { + uint32 menuId = tmpl.GossipMenuId; + if (!menuId) + continue; + + if (!(tmpl.npcflag & UNIT_NPC_FLAG_TRAINER)) + continue; + + if (checkedMenuIds.contains(menuId)) + continue; + + checkedMenuIds.insert(menuId); + + auto [first, second] = _gossipMenuItemsStore.equal_range(menuId); + if (first == second) + LOG_WARN("server.loading", "Trainer creature template references GossipMenuId {} has no `gossip_menu_option` entries. This will fallback to MenuID 0.", menuId); + } + LOG_INFO("server.loading", ">> Loaded {} gossip_menu_option entries in {} ms", uint32(_gossipMenuItemsStore.size()), GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", " "); }