From cd2fe2f9a17f0b3ba175f82138e96158b953664b Mon Sep 17 00:00:00 2001 From: Crow Date: Fri, 22 May 2026 21:25:07 -0500 Subject: [PATCH] Use Stones for Prot Paladins & Reduce Oils (#2405) ## Pull Request Description Back when I did the Stones/Oils PR, I gave Wizard Oil to Prot Paladins. I was operating based on their mechanics in TBC and have since realized that their damage is much more physical-based in WotLK as opposed to spell-based in TBC. So I've changed them to now get stones upon maintenance and apply stones. I also reduced weapon oils given during maintenance from 4 to 2 stacks. I did 4 originally because oils stack to 5 so it would align with the amount given of stones and poisons (which stack to 20). But 4 inventory slots taken up by oils is excessive, and 2 still last far longer than buffing reagents in a raid context. So this is just to reduce inventory clutter. Other stuff is just little code stuff like reformatting or reordering things to be more efficient. ## Feature Evaluation - Describe the **minimum logic** required to achieve the intended behavior. - Describe the **processing cost** when this logic executes across many bots. There's nothing new--essentially with respect to consumables, prot paladins now are lumped with ret. ## How to Test the Changes Create a prot paladin, turn on selfbot. Use maintenance and the paladin should be given stones and no oils. The paladin should then apply the stone to its weapon (if it is equipping a level-eligible weapon). Create a caster, turn on selfbot. Use maintenance and they should be given 2 stacks of oils. ## Impact Assessment - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - - [x] No, not at all - - [ ] Minimal impact (**explain below**) - - [ ] Moderate impact (**explain below**) - Does this change modify default bot behavior? - - [ ] No - - [x] Yes (**explain why**) Prot paladins will now use stones in their inventory and will not use oils in their inventories. This is better for their mechanics. - Does this change add new decision branches or increase maintenance complexity? - - [x] No - - [ ] Yes (**explain below**) ## AI Assistance Was AI assistance used while working on this change? - - [x] No - - [ ] Yes (**explain below**) ## Final Checklist - - [x] Stability is not compromised. - - [x] Performance impact is understood, tested, and acceptable. - - [x] Added logic complexity is justified and explained. - - [x] Any new bot dialogue lines are translated. - - [x] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers --- .../GenericPaladinNonCombatStrategy.cpp | 4 +- src/Bot/Factory/PlayerbotFactory.cpp | 119 +++++++++--------- 2 files changed, 61 insertions(+), 62 deletions(-) diff --git a/src/Ai/Class/Paladin/Strategy/GenericPaladinNonCombatStrategy.cpp b/src/Ai/Class/Paladin/Strategy/GenericPaladinNonCombatStrategy.cpp index 670d7e629..84f449813 100644 --- a/src/Ai/Class/Paladin/Strategy/GenericPaladinNonCombatStrategy.cpp +++ b/src/Ai/Class/Paladin/Strategy/GenericPaladinNonCombatStrategy.cpp @@ -26,8 +26,8 @@ void GenericPaladinNonCombatStrategy::InitTriggers(std::vector& tr triggers.push_back(new TriggerNode("not sensing undead", { NextAction("sense undead", ACTION_IDLE + 1.0f) })); int specTab = AiFactory::GetPlayerSpecTab(botAI->GetBot()); - if (specTab == PALADIN_TAB_HOLY || specTab == PALADIN_TAB_PROTECTION) + if (specTab == PALADIN_TAB_HOLY) triggers.push_back(new TriggerNode("often", { NextAction("apply oil", ACTION_IDLE + 1.0f) })); - if (specTab == PALADIN_TAB_RETRIBUTION) + if (specTab == PALADIN_TAB_PROTECTION || specTab == PALADIN_TAB_RETRIBUTION) triggers.push_back(new TriggerNode("often", { NextAction("apply stone", ACTION_IDLE + 1.0f) })); } diff --git a/src/Bot/Factory/PlayerbotFactory.cpp b/src/Bot/Factory/PlayerbotFactory.cpp index f8e0e5dfe..3b35ccb6e 100644 --- a/src/Bot/Factory/PlayerbotFactory.cpp +++ b/src/Bot/Factory/PlayerbotFactory.cpp @@ -850,36 +850,36 @@ void PlayerbotFactory::Refresh() void PlayerbotFactory::InitConsumables() { - int specTab = AiFactory::GetPlayerSpecTab(bot); + uint8 specTab = AiFactory::GetPlayerSpecTab(bot); std::vector> items; switch (bot->getClass()) { case CLASS_PRIEST: { - // Discipline or Holy: Mana Oil - if (specTab == 0 || specTab == 1) + if (specTab == PRIEST_TAB_SHADOW) { - std::vector mana_oils = {BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL}; - for (uint32 itemId : mana_oils) - { - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); - if (proto->RequiredLevel > level || level > 75) - continue; - items.push_back({itemId, 4}); - break; - } - } - // Shadow: Wizard Oil - if (specTab == 2) - { - std::vector wizard_oils = {BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL}; + std::vector wizard_oils = { + BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL }; for (uint32 itemId : wizard_oils) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); if (proto->RequiredLevel > level || level > 75) continue; - items.push_back({itemId, 4}); + items.push_back({itemId, 2}); + break; + } + } + else + { + std::vector mana_oils = { + BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL }; + for (uint32 itemId : mana_oils) + { + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); + if (proto->RequiredLevel > level || level > 75) + continue; + items.push_back({itemId, 2}); break; } } @@ -887,38 +887,41 @@ void PlayerbotFactory::InitConsumables() } case CLASS_MAGE: { - // Always Wizard Oil - std::vector wizard_oils = {BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL}; + std::vector wizard_oils = { + BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL }; for (uint32 itemId : wizard_oils) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); if (proto->RequiredLevel > level || level > 75) continue; - items.push_back({itemId, 4}); + items.push_back({itemId, 2}); break; } break; } case CLASS_DRUID: { - // Balance: Wizard Oil - if (specTab == 0) + if (specTab == DRUID_TAB_BALANCE) { - std::vector wizard_oils = {BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL}; + std::vector wizard_oils = { + BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL }; for (uint32 itemId : wizard_oils) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); if (proto->RequiredLevel > level || level > 75) continue; - items.push_back({itemId, 4}); + items.push_back({itemId, 2}); break; } } - // Feral: Sharpening Stones & Weightstones - else if (specTab == 1) + else if (specTab == DRUID_TAB_FERAL) { - std::vector sharpening_stones = {ADAMANTITE_SHARPENING_STONE, FEL_SHARPENING_STONE, DENSE_SHARPENING_STONE, SOLID_SHARPENING_STONE, HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE}; - std::vector weightstones = {ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE, HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE}; + std::vector sharpening_stones = { + ADAMANTITE_SHARPENING_STONE, FEL_SHARPENING_STONE, DENSE_SHARPENING_STONE, SOLID_SHARPENING_STONE, + HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE }; + std::vector weightstones = { + ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE, + HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE }; for (uint32 itemId : sharpening_stones) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); @@ -936,16 +939,16 @@ void PlayerbotFactory::InitConsumables() break; } } - // Restoration: Mana Oil - else if (specTab == 2) + else { - std::vector mana_oils = {BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL}; + std::vector mana_oils = { + BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL }; for (uint32 itemId : mana_oils) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); if (proto->RequiredLevel > level || level > 75) continue; - items.push_back({itemId, 4}); + items.push_back({itemId, 2}); break; } } @@ -953,37 +956,27 @@ void PlayerbotFactory::InitConsumables() } case CLASS_PALADIN: { - // Holy: Mana Oil - if (specTab == 0) + if (specTab == PALADIN_TAB_HOLY) { - std::vector mana_oils = {BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL}; + std::vector mana_oils = { + BRILLIANT_MANA_OIL, SUPERIOR_MANA_OIL, LESSER_MANA_OIL, MINOR_MANA_OIL }; for (uint32 itemId : mana_oils) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); if (proto->RequiredLevel > level || level > 75) continue; - items.push_back({itemId, 4}); + items.push_back({itemId, 2}); break; } } - // Protection: Wizard Oil (Protection prioritizes Superior over Brilliant) - else if (specTab == 1) + else { - std::vector wizard_oils = {BRILLIANT_WIZARD_OIL, SUPERIOR_WIZARD_OIL, WIZARD_OIL, LESSER_WIZARD_OIL, MINOR_WIZARD_OIL}; - for (uint32 itemId : wizard_oils) - { - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); - if (proto->RequiredLevel > level || level > 75) - continue; - items.push_back({itemId, 4}); - break; - } - } - // Retribution: Sharpening Stones & Weightstones - else if (specTab == 2) - { - std::vector sharpening_stones = {ADAMANTITE_SHARPENING_STONE, FEL_SHARPENING_STONE, DENSE_SHARPENING_STONE, SOLID_SHARPENING_STONE, HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE}; - std::vector weightstones = {ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE, HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE}; + std::vector sharpening_stones = { + ADAMANTITE_SHARPENING_STONE, FEL_SHARPENING_STONE, DENSE_SHARPENING_STONE, SOLID_SHARPENING_STONE, + HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE }; + std::vector weightstones = { + ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE, + HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE }; for (uint32 itemId : sharpening_stones) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); @@ -1006,9 +999,12 @@ void PlayerbotFactory::InitConsumables() case CLASS_WARRIOR: case CLASS_HUNTER: { - // Sharpening Stones & Weightstones - std::vector sharpening_stones = {ADAMANTITE_SHARPENING_STONE, FEL_SHARPENING_STONE, DENSE_SHARPENING_STONE, SOLID_SHARPENING_STONE, HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE}; - std::vector weightstones = {ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE, HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE}; + std::vector sharpening_stones = { + ADAMANTITE_SHARPENING_STONE, FEL_SHARPENING_STONE, DENSE_SHARPENING_STONE, SOLID_SHARPENING_STONE, + HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE }; + std::vector weightstones = { + ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE, + HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE }; for (uint32 itemId : sharpening_stones) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId); @@ -1029,9 +1025,12 @@ void PlayerbotFactory::InitConsumables() } case CLASS_ROGUE: { - // Poisons - std::vector instant_poisons = {INSTANT_POISON_IX, INSTANT_POISON_VIII, INSTANT_POISON_VII, INSTANT_POISON_VI, INSTANT_POISON_V, INSTANT_POISON_IV, INSTANT_POISON_III, INSTANT_POISON_II, INSTANT_POISON}; - std::vector deadly_poisons = {DEADLY_POISON_IX, DEADLY_POISON_VIII, DEADLY_POISON_VII, DEADLY_POISON_VI, DEADLY_POISON_V, DEADLY_POISON_IV, DEADLY_POISON_III, DEADLY_POISON_II, DEADLY_POISON}; + std::vector instant_poisons = { + INSTANT_POISON_IX, INSTANT_POISON_VIII, INSTANT_POISON_VII, INSTANT_POISON_VI, INSTANT_POISON_V, + INSTANT_POISON_IV, INSTANT_POISON_III, INSTANT_POISON_II, INSTANT_POISON }; + std::vector deadly_poisons = { + DEADLY_POISON_IX, DEADLY_POISON_VIII, DEADLY_POISON_VII, DEADLY_POISON_VI, DEADLY_POISON_V, + DEADLY_POISON_IV, DEADLY_POISON_III, DEADLY_POISON_II, DEADLY_POISON }; for (uint32 itemId : deadly_poisons) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId);