From 473b2ab5c6f42c5450361f119a08a9642e6a68d4 Mon Sep 17 00:00:00 2001 From: XYUU Date: Fri, 20 Mar 2026 20:37:44 +0100 Subject: [PATCH] Fix: WLK shaman totem quest vs relic totems: avoid keeping 4 totem items when relic exists #2119 (#2197) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary * Detects shaman relics (relic type, totem subclass) in bags/equipment. * Skips adding the four classic totem items (5175–5178) when a relic exists. * Cleans up any existing totem items from bags/equipment/bank when a relic exists, while keeping Ankh handling intact. ## Test plan Verified manually (local environment). --------- Co-authored-by: Keleborn <22352763+Celandriel@users.noreply.github.com> Co-authored-by: bash Co-authored-by: Revision Co-authored-by: kadeshar Co-authored-by: github-actions --- src/Bot/Factory/PlayerbotFactory.cpp | 32 ++++++++++++++++++++++------ src/Mgr/Item/ItemVisitors.h | 23 ++++++++++++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/Bot/Factory/PlayerbotFactory.cpp b/src/Bot/Factory/PlayerbotFactory.cpp index 9e1b30a73..9bf987fef 100644 --- a/src/Bot/Factory/PlayerbotFactory.cpp +++ b/src/Bot/Factory/PlayerbotFactory.cpp @@ -3342,18 +3342,36 @@ void PlayerbotFactory::InitReagents() items.push_back({44615, 40}); // Devout Candle break; case CLASS_SHAMAN: - if (level >= 4) - items.push_back({5175, 1}); // Earth Totem - if (level >= 10) - items.push_back({5176, 1}); // Flame Totem - if (level >= 20) - items.push_back({5177, 1}); // Water Totem + { + HasRelicBySubclassVisitor relicVisitor(ITEM_SUBCLASS_ARMOR_TOTEM); + IterateItems(&relicVisitor, (IterateItemsMask)(ITERATE_ITEMS_IN_BAGS | ITERATE_ITEMS_IN_EQUIP)); + bool hasRelic = relicVisitor.found; + + if (!hasRelic) + { + if (level >= 4) + items.push_back({5175, 1}); // Earth Totem + if (level >= 10) + items.push_back({5176, 1}); // Flame Totem + if (level >= 20) + items.push_back({5177, 1}); // Water Totem + } + else + { + ItemIds totemIds = {5175, 5176, 5177, 5178}; + FindItemByIdsVisitor totemVisitor(totemIds); + IterateItems(&totemVisitor, (IterateItemsMask)(ITERATE_ITEMS_IN_BAGS | ITERATE_ITEMS_IN_EQUIP | ITERATE_ITEMS_IN_BANK)); + for (Item* item : totemVisitor.GetResult()) + bot->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); + } if (level >= 30) { - items.push_back({5178, 1}); // Air Totem + if (!hasRelic) + items.push_back({5178, 1}); // Air Totem items.push_back({17030, 20}); // Ankh } break; + } case CLASS_WARLOCK: items.push_back({6265, 5}); // Soul Shard break; diff --git a/src/Mgr/Item/ItemVisitors.h b/src/Mgr/Item/ItemVisitors.h index e42b14f89..930aa1f4a 100644 --- a/src/Mgr/Item/ItemVisitors.h +++ b/src/Mgr/Item/ItemVisitors.h @@ -66,6 +66,29 @@ private: Player* bot; }; +class HasRelicBySubclassVisitor : public IterateItemsVisitor +{ +public: + HasRelicBySubclassVisitor(uint32 subClass) : subClass(subClass) {} + + bool Visit(Item* item) override + { + ItemTemplate const* proto = item->GetTemplate(); + if (proto && proto->InventoryType == INVTYPE_RELIC && proto->SubClass == subClass) + { + found = true; + return false; + } + + return true; + } + + bool found = false; + +private: + uint32 subClass; +}; + class FindItemsByQualityVisitor : public IterateItemsVisitor { public: