Warlock Ranged Designation/DPS Strategy Cleanup

Hello community,

This PR focuses on 4 things:

Recognizing the Warlock as a "ranged" bot, so they will follow ranged commands and strategies, in GenericWarlockStrategy.h:
uint32 GetType() const override { return CombatStrategy::GetType() | STRATEGY_TYPE_RANGED | STRATEGY_TYPE_DPS; }

Cleanup/deletion of the DpsWarlockStrategy.cpp and .h (no longer used or referenced anywhere)

Fixes soulstone logic so multiple Warlocks don't soulstone the same target, and don't try to soulstone a target that is too far away or out of line of sight (WarlockActions.cpp)

Moved summoning of pets to the main non-combat strategy inittriggers:

// 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)));
    }
This commit is contained in:
ThePenguinMan96
2025-07-04 03:32:29 -07:00
parent 40535f6e55
commit 59af34809c
8 changed files with 128 additions and 277 deletions

View File

@@ -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:

View File

@@ -1,88 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, 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<ActionNode>
{
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<TriggerNode*>& 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<TriggerNode*>& 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)));
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, 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<TriggerNode*>& 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<TriggerNode*>& triggers) override;
std::string const getName() override { return "aoe"; }
};
#endif

View File

@@ -89,77 +89,31 @@ void GenericWarlockNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& 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<TriggerNode*>& 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<TriggerNode*>& 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<TriggerNode*>& 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<TriggerNode*>& 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<TriggerNode*>& 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

View File

@@ -19,56 +19,6 @@ public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
};
class SummonImpStrategy : public NonCombatStrategy
{
public:
SummonImpStrategy(PlayerbotAI* ai);
virtual std::string const getName() override { return "imp"; }
public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
};
class SummonVoidwalkerStrategy : public NonCombatStrategy
{
public:
SummonVoidwalkerStrategy(PlayerbotAI* ai);
virtual std::string const getName() override { return "voidwalker"; }
public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
};
class SummonSuccubusStrategy : public NonCombatStrategy
{
public:
SummonSuccubusStrategy(PlayerbotAI* ai);
virtual std::string const getName() override { return "succubus"; }
public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
};
class SummonFelhunterStrategy : public NonCombatStrategy
{
public:
SummonFelhunterStrategy(PlayerbotAI* ai);
virtual std::string const getName() override { return "felhunter"; }
public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
};
class SummonFelguardStrategy : public NonCombatStrategy
{
public:
SummonFelguardStrategy(PlayerbotAI* ai);
virtual std::string const getName() override { return "felguard"; }
public:
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
};
class SoulstoneSelfStrategy : public NonCombatStrategy
{
public:

View File

@@ -18,6 +18,7 @@ public:
std::string const getName() override { return "warlock"; }
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
NextAction** getDefaultActions() override;
uint32 GetType() const override { return CombatStrategy::GetType() | STRATEGY_TYPE_RANGED | STRATEGY_TYPE_DPS; }
};
class WarlockBoostStrategy : public Strategy

View File

@@ -15,6 +15,9 @@
#include "Playerbots.h"
#include "ServerFacade.h"
#include "Unit.h"
#include "Timer.h"
#include <unordered_map>
#include <mutex>
// 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<ObjectGuid, uint32> soulstoneReservations;
static std::mutex soulstoneReservationsMutex;
// Helper to clean up expired reservations
void CleanupSoulstoneReservations()
{
uint32 now = getMSTime();
std::lock_guard<std::mutex> 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<Item*> items = AI_VALUE2(std::vector<Item*>, "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<std::mutex> 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<Item*> items = AI_VALUE2(std::vector<Item*>, "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<std::mutex> 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<std::mutex> 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<Item*> items = AI_VALUE2(std::vector<Item*>, "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<std::mutex> 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;
}
}
}
}
}

View File

@@ -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<Strategy>(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<Strategy>
@@ -76,11 +71,6 @@ class NonCombatBuffStrategyFactoryInternal : public NamedObjectContext<Strategy>
public:
NonCombatBuffStrategyFactoryInternal() : NamedObjectContext<Strategy>(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); }