diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index adf53668..9589a8f2 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -594,18 +594,6 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const nonCombatEngine->addStrategy("dps assist", false); break; case CLASS_WARLOCK: - if (tab == WARLOCK_TAB_AFFLICATION) - { - nonCombatEngine->addStrategiesNoInit("felhunter", nullptr); - } - else if (tab == WARLOCK_TAB_DEMONOLOGY) - { - nonCombatEngine->addStrategiesNoInit("felguard", nullptr); - } - else if (tab == WARLOCK_TAB_DESTRUCTION) - { - nonCombatEngine->addStrategiesNoInit("imp", nullptr); - } nonCombatEngine->addStrategiesNoInit("dps assist", nullptr); break; case CLASS_DEATH_KNIGHT: diff --git a/src/strategy/warlock/DpsWarlockStrategy.cpp b/src/strategy/warlock/DpsWarlockStrategy.cpp deleted file mode 100644 index 49b6a2be..00000000 --- a/src/strategy/warlock/DpsWarlockStrategy.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license, you may redistribute it - * and/or modify it under version 2 of the License, or (at your option), any later version. - */ - -#include "DpsWarlockStrategy.h" -#include "Playerbots.h" - -// This strategy is designed for low-level Warlocks without talents. -// All of the important spells/cooldowns have been migrated to -// their respective specs. - -// ===== Action Node Factory ===== -class DpsWarlockStrategyActionNodeFactory : public NamedObjectFactory -{ -public: - DpsWarlockStrategyActionNodeFactory() - { - creators["corruption"] = &corruption; - creators["curse of agony"] = &curse_of_agony; - creators["immolate"] = &immolate; - creators["shadow bolt"] = &shadow_bolt; - creators["life tap"] = &life_tap; - creators["shadowflame"] = &shadowflame; - creators["seed of corruption"] = &seed_of_corruption; - creators["rain of fire"] = &rain_of_fire; - creators["drain soul"] = &drain_soul; - } - -private: - static ActionNode* corruption(PlayerbotAI*) { return new ActionNode("corruption", nullptr, nullptr, nullptr); } - static ActionNode* curse_of_agony(PlayerbotAI*){return new ActionNode("curse of agony", nullptr, nullptr, nullptr);} - static ActionNode* immolate(PlayerbotAI*) { return new ActionNode("immolate", nullptr, nullptr, nullptr); } - static ActionNode* shadow_bolt(PlayerbotAI*) { return new ActionNode("shadow bolt", nullptr, nullptr, nullptr); } - static ActionNode* life_tap(PlayerbotAI*) { return new ActionNode("life tap", nullptr, nullptr, nullptr); } - static ActionNode* shadowflame(PlayerbotAI*) { return new ActionNode("shadowflame", nullptr, nullptr, nullptr); } - static ActionNode* seed_of_corruption(PlayerbotAI*){return new ActionNode("seed of corruption", nullptr, nullptr, nullptr);} - static ActionNode* rain_of_fire(PlayerbotAI*) { return new ActionNode("rain of fire", nullptr, nullptr, nullptr); } - static ActionNode* drain_soul(PlayerbotAI*) { return new ActionNode("drain soul", nullptr, nullptr, nullptr); } -}; - -// ===== Single Target Strategy ===== -DpsWarlockStrategy::DpsWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrategy(botAI) -{ - actionNodeFactories.Add(new DpsWarlockStrategyActionNodeFactory()); -} - -// ===== Default Actions ===== -NextAction** DpsWarlockStrategy::getDefaultActions() -{ - return NextAction::array(0, - new NextAction("immolate", 5.5f), - new NextAction("corruption", 5.4f), - new NextAction("curse of agony", 5.3f), - new NextAction("shadow bolt", 5.2f), - new NextAction("shoot", 5.0f), nullptr); -} - -// ===== Trigger Initialization === -void DpsWarlockStrategy::InitTriggers(std::vector& triggers) -{ - GenericWarlockStrategy::InitTriggers(triggers); - - // Main DoT triggers for high uptime - triggers.push_back(new TriggerNode("corruption on attacker", NextAction::array(0, new NextAction("corruption on attacker", 20.0f), nullptr))); - triggers.push_back(new TriggerNode("curse of agony on attacker", NextAction::array(0, new NextAction("curse of agony on attacker", 19.5f), nullptr))); - triggers.push_back(new TriggerNode("immolate on attacker", NextAction::array(0, new NextAction("immolate on attacker", 19.0f), nullptr))); - triggers.push_back(new TriggerNode("corruption", NextAction::array(0, new NextAction("corruption", 18.5f), nullptr))); - triggers.push_back(new TriggerNode("curse of agony", NextAction::array(0, new NextAction("curse of agony", 18.0f), nullptr))); - triggers.push_back(new TriggerNode("immolate", NextAction::array(0, new NextAction("immolate", 17.5f), nullptr))); - - // Drain Soul as execute if target is low HP - triggers.push_back(new TriggerNode("target critical health", NextAction::array(0, new NextAction("drain soul", 17.0f), nullptr))); - - // Cast during movement or to activate glyph buff - triggers.push_back(new TriggerNode("life tap", NextAction::array(0, new NextAction("life tap", ACTION_DEFAULT + 0.1f), nullptr))); - triggers.push_back(new TriggerNode("life tap glyph buff", NextAction::array(0, new NextAction("life tap", 28.0f), NULL))); -} - -// ===== AoE Strategy, 3+ enemies ===== -void DpsAoeWarlockStrategy::InitTriggers(std::vector& triggers) -{ - triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, - new NextAction("shadowflame", 22.5f), - new NextAction("seed of corruption on attacker", 22.0f), - new NextAction("seed of corruption", 21.5f), - new NextAction("rain of fire", 21.0f), nullptr))); -} diff --git a/src/strategy/warlock/DpsWarlockStrategy.h b/src/strategy/warlock/DpsWarlockStrategy.h deleted file mode 100644 index 4ae63930..00000000 --- a/src/strategy/warlock/DpsWarlockStrategy.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license, you may redistribute it - * and/or modify it under version 2 of the License, or (at your option), any later version. - */ - -#ifndef _PLAYERBOT_DPSWARLOCKSTRATEGY_H -#define _PLAYERBOT_DPSWARLOCKSTRATEGY_H - -#include "GenericWarlockStrategy.h" -#include "Strategy.h" - -class PlayerbotAI; - -class DpsWarlockStrategy : public GenericWarlockStrategy -{ -public: - DpsWarlockStrategy(PlayerbotAI* botAI); - - std::string const getName() override { return "dps"; } - void InitTriggers(std::vector& triggers) override; - NextAction** getDefaultActions() override; - uint32 GetType() const override { return GenericWarlockStrategy::GetType() | STRATEGY_TYPE_DPS; } -}; - -class DpsAoeWarlockStrategy : public CombatStrategy -{ -public: - DpsAoeWarlockStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI) {} - - void InitTriggers(std::vector& triggers) override; - std::string const getName() override { return "aoe"; } -}; -#endif diff --git a/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp b/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp index f575750b..d5baa276 100644 --- a/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp +++ b/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp @@ -89,77 +89,31 @@ void GenericWarlockNonCombatStrategy::InitTriggers(std::vector& tr Player* bot = botAI->GetBot(); int tab = AiFactory::GetPlayerSpecTab(bot); + // Firestone/Spellstone triggers if (tab == 2) // Destruction uses Firestone { - triggers.push_back( - new TriggerNode("no firestone", NextAction::array(0, new NextAction("create firestone", 24.0f), nullptr))); - triggers.push_back( - new TriggerNode("firestone", NextAction::array(0, new NextAction("firestone", 24.0f), nullptr))); + triggers.push_back(new TriggerNode("no firestone", NextAction::array(0, new NextAction("create firestone", 24.0f), nullptr))); + triggers.push_back(new TriggerNode("firestone", NextAction::array(0, new NextAction("firestone", 24.0f), nullptr))); } else // Affliction and Demonology use Spellstone { - triggers.push_back(new TriggerNode("no spellstone", - NextAction::array(0, new NextAction("create spellstone", 24.0f), nullptr))); - triggers.push_back( - new TriggerNode("spellstone", NextAction::array(0, new NextAction("spellstone", 24.0f), nullptr))); + triggers.push_back(new TriggerNode("no spellstone", NextAction::array(0, new NextAction("create spellstone", 24.0f), nullptr))); + triggers.push_back(new TriggerNode("spellstone", NextAction::array(0, new NextAction("spellstone", 24.0f), nullptr))); } -} -// Non-combat strategy for summoning a Imp -// Enabled by default for the Destruction spec -// To enable, type "nc +imp" -// To disable, type "nc -imp" -SummonImpStrategy::SummonImpStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {} - -void SummonImpStrategy::InitTriggers(std::vector& triggers) -{ - triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon imp", 29.0f), NULL))); -} - -// Non-combat strategy for summoning a Voidwalker -// Disabled by default -// To enable, type "nc +voidwalker" -// To disable, type "nc -voidwalker" -SummonVoidwalkerStrategy::SummonVoidwalkerStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {} - -void SummonVoidwalkerStrategy::InitTriggers(std::vector& triggers) -{ - triggers.push_back( - new TriggerNode("no pet", NextAction::array(0, new NextAction("summon voidwalker", 29.0f), NULL))); -} - -// Non-combat strategy for summoning a Succubus -// Disabled by default -// To enable, type "nc +succubus" -// To disable, type "nc -succubus" -SummonSuccubusStrategy::SummonSuccubusStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {} - -void SummonSuccubusStrategy::InitTriggers(std::vector& triggers) -{ - triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon succubus", 29.0f), NULL))); -} - -// Non-combat strategy for summoning a Felhunter -// Enabled by default for the Affliction spec -// To enable, type "nc +felhunter" -// To disable, type "nc -felhunter" -SummonFelhunterStrategy::SummonFelhunterStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {} - -void SummonFelhunterStrategy::InitTriggers(std::vector& triggers) -{ - triggers.push_back( - new TriggerNode("no pet", NextAction::array(0, new NextAction("summon felhunter", 29.0f), NULL))); -} - -// Non-combat strategy for summoning a Felguard -// Enabled by default for the Demonology spec -// To enable, type "nc +felguard" -// To disable, type "nc -felguard" -SummonFelguardStrategy::SummonFelguardStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {} - -void SummonFelguardStrategy::InitTriggers(std::vector& triggers) -{ - triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon felguard", 29.0f), NULL))); + // Pet-summoning triggers based on spec + if (tab == 0) // Affliction + { + triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon felhunter", 29.0f), nullptr))); + } + else if (tab == 1) // Demonology + { + triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon felguard", 29.0f), nullptr))); + } + else if (tab == 2) // Destruction + { + triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon imp", 29.0f), nullptr))); + } } // Non-combat strategy for selecting themselves to receive soulstone diff --git a/src/strategy/warlock/GenericWarlockNonCombatStrategy.h b/src/strategy/warlock/GenericWarlockNonCombatStrategy.h index ef226c50..19277dfd 100644 --- a/src/strategy/warlock/GenericWarlockNonCombatStrategy.h +++ b/src/strategy/warlock/GenericWarlockNonCombatStrategy.h @@ -19,56 +19,6 @@ public: void InitTriggers(std::vector& triggers) override; }; -class SummonImpStrategy : public NonCombatStrategy -{ -public: - SummonImpStrategy(PlayerbotAI* ai); - virtual std::string const getName() override { return "imp"; } - -public: - void InitTriggers(std::vector& triggers) override; -}; - -class SummonVoidwalkerStrategy : public NonCombatStrategy -{ -public: - SummonVoidwalkerStrategy(PlayerbotAI* ai); - virtual std::string const getName() override { return "voidwalker"; } - -public: - void InitTriggers(std::vector& triggers) override; -}; - -class SummonSuccubusStrategy : public NonCombatStrategy -{ -public: - SummonSuccubusStrategy(PlayerbotAI* ai); - virtual std::string const getName() override { return "succubus"; } - -public: - void InitTriggers(std::vector& triggers) override; -}; - -class SummonFelhunterStrategy : public NonCombatStrategy -{ -public: - SummonFelhunterStrategy(PlayerbotAI* ai); - virtual std::string const getName() override { return "felhunter"; } - -public: - void InitTriggers(std::vector& triggers) override; -}; - -class SummonFelguardStrategy : public NonCombatStrategy -{ -public: - SummonFelguardStrategy(PlayerbotAI* ai); - virtual std::string const getName() override { return "felguard"; } - -public: - void InitTriggers(std::vector& triggers) override; -}; - class SoulstoneSelfStrategy : public NonCombatStrategy { public: diff --git a/src/strategy/warlock/GenericWarlockStrategy.h b/src/strategy/warlock/GenericWarlockStrategy.h index 23fa739b..6b134b60 100644 --- a/src/strategy/warlock/GenericWarlockStrategy.h +++ b/src/strategy/warlock/GenericWarlockStrategy.h @@ -18,6 +18,7 @@ public: std::string const getName() override { return "warlock"; } void InitTriggers(std::vector& triggers) override; NextAction** getDefaultActions() override; + uint32 GetType() const override { return CombatStrategy::GetType() | STRATEGY_TYPE_RANGED | STRATEGY_TYPE_DPS; } }; class WarlockBoostStrategy : public Strategy diff --git a/src/strategy/warlock/WarlockActions.cpp b/src/strategy/warlock/WarlockActions.cpp index 8b362cd6..3bb1724b 100644 --- a/src/strategy/warlock/WarlockActions.cpp +++ b/src/strategy/warlock/WarlockActions.cpp @@ -15,6 +15,9 @@ #include "Playerbots.h" #include "ServerFacade.h" #include "Unit.h" +#include "Timer.h" +#include +#include // Checks if the bot has less than 32 soul shards, and if so, allows casting Drain Soul bool CastDrainSoulAction::isUseful() { return AI_VALUE2(uint32, "item count", "soul shard") < 32; } @@ -134,9 +137,29 @@ bool UseSoulstoneSelfAction::Execute(Event event) return UseItem(items[0], ObjectGuid::Empty, nullptr, bot); } +// Reservation map for soulstone targets (GUID -> reservation expiry in ms) +static std::unordered_map soulstoneReservations; +static std::mutex soulstoneReservationsMutex; + +// Helper to clean up expired reservations +void CleanupSoulstoneReservations() +{ + uint32 now = getMSTime(); + std::lock_guard lock(soulstoneReservationsMutex); + for (auto it = soulstoneReservations.begin(); it != soulstoneReservations.end();) + { + if (it->second <= now) + it = soulstoneReservations.erase(it); + else + ++it; + } +} + // Use the soulstone item on the bot's master with nc strategy "ss master" bool UseSoulstoneMasterAction::Execute(Event event) { + CleanupSoulstoneReservations(); + std::vector items = AI_VALUE2(std::vector, "inventory items", "soulstone"); if (items.empty()) return false; @@ -145,6 +168,23 @@ bool UseSoulstoneMasterAction::Execute(Event event) if (!master || HasSoulstoneAura(master)) return false; + uint32 now = getMSTime(); + + { + std::lock_guard lock(soulstoneReservationsMutex); + if (soulstoneReservations.count(master->GetGUID()) && soulstoneReservations[master->GetGUID()] > now) + return false; // Already being soulstoned + + soulstoneReservations[master->GetGUID()] = now + 2500; // Reserve for 2.5 seconds + } + + float distance = sServerFacade->GetDistance2d(bot, master); + if (distance >= 30.0f) + return false; + + if (!bot->IsWithinLOSInMap(master)) + return false; + bot->SetSelection(master->GetGUID()); return UseItem(items[0], ObjectGuid::Empty, nullptr, master); } @@ -152,41 +192,83 @@ bool UseSoulstoneMasterAction::Execute(Event event) // Use the soulstone item on a tank in the group with nc strategy "ss tank" bool UseSoulstoneTankAction::Execute(Event event) { + CleanupSoulstoneReservations(); + std::vector items = AI_VALUE2(std::vector, "inventory items", "soulstone"); if (items.empty()) return false; - Player* tank = nullptr; + Player* chosenTank = nullptr; Group* group = bot->GetGroup(); + uint32 now = getMSTime(); + + // First: Try to soulstone the main tank if (group) { for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) { Player* member = gref->GetSource(); - if (member && member->IsAlive() && botAI->IsTank(member) && !HasSoulstoneAura(member)) + if (member && member->IsAlive() && botAI->IsTank(member) && botAI->IsMainTank(member) && + !HasSoulstoneAura(member)) { - tank = member; - break; + std::lock_guard lock(soulstoneReservationsMutex); + if (soulstoneReservations.count(member->GetGUID()) && soulstoneReservations[member->GetGUID()] > now) + continue; // Already being soulstoned + + float distance = sServerFacade->GetDistance2d(bot, member); + if (distance < 30.0f && bot->IsWithinLOSInMap(member)) + { + chosenTank = member; + soulstoneReservations[chosenTank->GetGUID()] = now + 2500; // Reserve for 2.5 seconds + break; + } + } + } + + // If no main tank found, soulstone another tank + if (!chosenTank) + { + for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) + { + Player* member = gref->GetSource(); + if (member && member->IsAlive() && botAI->IsTank(member) && !HasSoulstoneAura(member)) + { + std::lock_guard lock(soulstoneReservationsMutex); + if (soulstoneReservations.count(member->GetGUID()) && + soulstoneReservations[member->GetGUID()] > now) + continue; // Already being soulstoned + + float distance = sServerFacade->GetDistance2d(bot, member); + if (distance < 30.0f && bot->IsWithinLOSInMap(member)) + { + chosenTank = member; + soulstoneReservations[chosenTank->GetGUID()] = now + 2500; // Reserve for 2.5 seconds + break; + } + } } } } - if (!tank) + if (!chosenTank) return false; - bot->SetSelection(tank->GetGUID()); - return UseItem(items[0], ObjectGuid::Empty, nullptr, tank); + bot->SetSelection(chosenTank->GetGUID()); + return UseItem(items[0], ObjectGuid::Empty, nullptr, chosenTank); } // Use the soulstone item on a healer in the group with nc strategy "ss healer" bool UseSoulstoneHealerAction::Execute(Event event) { + CleanupSoulstoneReservations(); + std::vector items = AI_VALUE2(std::vector, "inventory items", "soulstone"); if (items.empty()) return false; Player* healer = nullptr; Group* group = bot->GetGroup(); + uint32 now = getMSTime(); if (group) { for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) @@ -194,8 +276,20 @@ bool UseSoulstoneHealerAction::Execute(Event event) Player* member = gref->GetSource(); if (member && member->IsAlive() && botAI->IsHeal(member) && !HasSoulstoneAura(member)) { - healer = member; - break; + { + std::lock_guard lock(soulstoneReservationsMutex); + if (soulstoneReservations.count(member->GetGUID()) && + soulstoneReservations[member->GetGUID()] > now) + continue; // Already being soulstoned + + float distance = sServerFacade->GetDistance2d(bot, member); + if (distance < 30.0f && bot->IsWithinLOSInMap(member)) + { + healer = member; + soulstoneReservations[healer->GetGUID()] = now + 2500; // Reserve for 2.5 seconds + break; + } + } } } } diff --git a/src/strategy/warlock/WarlockAiObjectContext.cpp b/src/strategy/warlock/WarlockAiObjectContext.cpp index e3dc6ca9..1de0d00f 100644 --- a/src/strategy/warlock/WarlockAiObjectContext.cpp +++ b/src/strategy/warlock/WarlockAiObjectContext.cpp @@ -8,7 +8,6 @@ #include "DemonologyWarlockStrategy.h" #include "DestructionWarlockStrategy.h" #include "TankWarlockStrategy.h" -#include "DpsWarlockStrategy.h" #include "GenericTriggers.h" #include "GenericWarlockNonCombatStrategy.h" #include "NamedObjectContext.h" @@ -29,15 +28,10 @@ public: creators["boost"] = &WarlockStrategyFactoryInternal::boost; creators["cc"] = &WarlockStrategyFactoryInternal::cc; creators["pet"] = &WarlockStrategyFactoryInternal::pet; - creators["affli"] = &WarlockStrategyFactoryInternal::affliction; creators["affli aoe"] = &WarlockStrategyFactoryInternal::affliction_aoe; - creators["demo"] = &WarlockStrategyFactoryInternal::demonology; creators["demo aoe"] = &WarlockStrategyFactoryInternal::demonology_aoe; - creators["destro"] = &WarlockStrategyFactoryInternal::destruction; creators["destro aoe"] = &WarlockStrategyFactoryInternal::destruction_aoe; creators["meta melee"] = &WarlockStrategyFactoryInternal::meta_melee_aoe; - creators["dps"] = &WarlockStrategyFactoryInternal::dps; - creators["aoe"] = &WarlockStrategyFactoryInternal::aoe; creators["curse of elements"] = &WarlockStrategyFactoryInternal::curse_of_elements; } @@ -47,15 +41,10 @@ private: static Strategy* pull(PlayerbotAI* botAI) { return new PullStrategy(botAI, "shoot"); } static Strategy* boost(PlayerbotAI* botAI) { return new WarlockBoostStrategy(botAI); } static Strategy* cc(PlayerbotAI* botAI) { return new WarlockCcStrategy(botAI); } - static Strategy* affliction(PlayerbotAI* botAI) { return new AfflictionWarlockStrategy(botAI); } static Strategy* affliction_aoe(PlayerbotAI* botAI) { return new AfflictionWarlockAoeStrategy(botAI); } - static Strategy* demonology(PlayerbotAI* botAI) { return new DemonologyWarlockStrategy(botAI); } static Strategy* demonology_aoe(PlayerbotAI* botAI) { return new DemonologyWarlockAoeStrategy(botAI); } - static Strategy* destruction(PlayerbotAI* botAI) { return new DestructionWarlockStrategy(botAI); } static Strategy* destruction_aoe(PlayerbotAI* botAI) { return new DestructionWarlockAoeStrategy(botAI); } static Strategy* meta_melee_aoe(PlayerbotAI* botAI) { return new MetaMeleeAoeStrategy(botAI); } - static Strategy* dps(PlayerbotAI* botAI) { return new DpsWarlockStrategy(botAI); } - static Strategy* aoe(PlayerbotAI* botAI) { return new DpsAoeWarlockStrategy(botAI); } static Strategy* curse_of_elements(PlayerbotAI* botAI) { return new WarlockCurseOfTheElementsStrategy(botAI); } }; @@ -65,10 +54,16 @@ public: WarlockCombatStrategyFactoryInternal() : NamedObjectContext(false, true) { creators["tank"] = &WarlockCombatStrategyFactoryInternal::tank; + creators["affli"] = &WarlockCombatStrategyFactoryInternal::affliction; + creators["demo"] = &WarlockCombatStrategyFactoryInternal::demonology; + creators["destro"] = &WarlockCombatStrategyFactoryInternal::destruction; } private: static Strategy* tank(PlayerbotAI* botAI) { return new TankWarlockStrategy(botAI); } + static Strategy* affliction(PlayerbotAI* botAI) { return new AfflictionWarlockStrategy(botAI); } + static Strategy* demonology(PlayerbotAI* botAI) { return new DemonologyWarlockStrategy(botAI); } + static Strategy* destruction(PlayerbotAI* botAI) { return new DestructionWarlockStrategy(botAI); } }; class NonCombatBuffStrategyFactoryInternal : public NamedObjectContext @@ -76,11 +71,6 @@ class NonCombatBuffStrategyFactoryInternal : public NamedObjectContext public: NonCombatBuffStrategyFactoryInternal() : NamedObjectContext(false, true) { - creators["imp"] = &NonCombatBuffStrategyFactoryInternal::imp; - creators["voidwalker"] = &NonCombatBuffStrategyFactoryInternal::voidwalker; - creators["succubus"] = &NonCombatBuffStrategyFactoryInternal::succubus; - creators["felhunter"] = &NonCombatBuffStrategyFactoryInternal::felhunter; - creators["felguard"] = &NonCombatBuffStrategyFactoryInternal::felguard; creators["ss self"] = &NonCombatBuffStrategyFactoryInternal::soulstone_self; creators["ss master"] = &NonCombatBuffStrategyFactoryInternal::soulstone_master; creators["ss tank"] = &NonCombatBuffStrategyFactoryInternal::soulstone_tank; @@ -88,11 +78,6 @@ public: } private: - static Strategy* imp(PlayerbotAI* ai) { return new SummonImpStrategy(ai); } - static Strategy* voidwalker(PlayerbotAI* ai) { return new SummonVoidwalkerStrategy(ai); } - static Strategy* succubus(PlayerbotAI* ai) { return new SummonSuccubusStrategy(ai); } - static Strategy* felhunter(PlayerbotAI* ai) { return new SummonFelhunterStrategy(ai); } - static Strategy* felguard(PlayerbotAI* ai) { return new SummonFelguardStrategy(ai); } static Strategy* soulstone_self(PlayerbotAI* ai) { return new SoulstoneSelfStrategy(ai); } static Strategy* soulstone_master(PlayerbotAI* ai) { return new SoulstoneMasterStrategy(ai); } static Strategy* soulstone_tank(PlayerbotAI* ai) { return new SoulstoneTankStrategy(ai); }