Merge remote-tracking branch 'upstream/master' into worldbuff

This commit is contained in:
crow
2025-07-26 11:16:33 -05:00
42 changed files with 988 additions and 244 deletions

View File

@@ -88,6 +88,9 @@ uint8 AiFactory::GetPlayerSpecTab(Player* bot)
case CLASS_PRIEST: case CLASS_PRIEST:
tab = PRIEST_TAB_HOLY; tab = PRIEST_TAB_HOLY;
break; break;
case CLASS_WARLOCK:
tab = WARLOCK_TAB_DEMONOLOGY;
break;
} }
return tab; return tab;

View File

@@ -6,6 +6,8 @@
#include "LootObjectStack.h" #include "LootObjectStack.h"
#include "LootMgr.h" #include "LootMgr.h"
#include "Object.h"
#include "ObjectAccessor.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "Unit.h" #include "Unit.h"
@@ -287,7 +289,7 @@ bool LootObject::IsLootPossible(Player* bot)
if (reqItem && !bot->HasItemCount(reqItem, 1)) if (reqItem && !bot->HasItemCount(reqItem, 1))
return false; return false;
if (abs(worldObj->GetPositionZ() - bot->GetPositionZ()) > INTERACTION_DISTANCE -2.0f) if (abs(worldObj->GetPositionZ() - bot->GetPositionZ()) > INTERACTION_DISTANCE - 2.0f)
return false; return false;
Creature* creature = botAI->GetCreature(guid); Creature* creature = botAI->GetCreature(guid);
@@ -299,7 +301,7 @@ bool LootObject::IsLootPossible(Player* bot)
// Prevent bot from running to chests that are unlootable (e.g. Gunship Armory before completing the event) // Prevent bot from running to chests that are unlootable (e.g. Gunship Armory before completing the event)
GameObject* go = botAI->GetGameObject(guid); GameObject* go = botAI->GetGameObject(guid);
if (go && go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE)) if (go && go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE))
return false; return false;
if (skillId == SKILL_NONE) if (skillId == SKILL_NONE)
@@ -317,29 +319,17 @@ bool LootObject::IsLootPossible(Player* bot)
uint32 skillValue = uint32(bot->GetSkillValue(skillId)); uint32 skillValue = uint32(bot->GetSkillValue(skillId));
if (reqSkillValue > skillValue) if (reqSkillValue > skillValue)
return false; return false;
if (skillId == SKILL_MINING && if (skillId == SKILL_MINING && !bot->HasItemCount(756, 1) && !bot->HasItemCount(778, 1) &&
!bot->HasItemCount(756, 1) && !bot->HasItemCount(1819, 1) && !bot->HasItemCount(1893, 1) && !bot->HasItemCount(1959, 1) &&
!bot->HasItemCount(778, 1) && !bot->HasItemCount(2901, 1) && !bot->HasItemCount(9465, 1) && !bot->HasItemCount(20723, 1) &&
!bot->HasItemCount(1819, 1) && !bot->HasItemCount(40772, 1) && !bot->HasItemCount(40892, 1) && !bot->HasItemCount(40893, 1))
!bot->HasItemCount(1893, 1) &&
!bot->HasItemCount(1959, 1) &&
!bot->HasItemCount(2901, 1) &&
!bot->HasItemCount(9465, 1) &&
!bot->HasItemCount(20723, 1) &&
!bot->HasItemCount(40772, 1) &&
!bot->HasItemCount(40892, 1) &&
!bot->HasItemCount(40893, 1))
{ {
return false; // Bot is missing a mining pick return false; // Bot is missing a mining pick
} }
if (skillId == SKILL_SKINNING && if (skillId == SKILL_SKINNING && !bot->HasItemCount(7005, 1) && !bot->HasItemCount(40772, 1) &&
!bot->HasItemCount(7005, 1) && !bot->HasItemCount(40893, 1) && !bot->HasItemCount(12709, 1) && !bot->HasItemCount(19901, 1))
!bot->HasItemCount(40772, 1) &&
!bot->HasItemCount(40893, 1) &&
!bot->HasItemCount(12709, 1) &&
!bot->HasItemCount(19901, 1))
{ {
return false; // Bot is missing a skinning knife return false; // Bot is missing a skinning knife
} }
@@ -376,42 +366,45 @@ void LootObjectStack::Clear() { availableLoot.clear(); }
bool LootObjectStack::CanLoot(float maxDistance) bool LootObjectStack::CanLoot(float maxDistance)
{ {
std::vector<LootObject> ordered = OrderByDistance(maxDistance); LootObject nearest = GetNearest(maxDistance);
return !ordered.empty(); return !nearest.IsEmpty();
} }
LootObject LootObjectStack::GetLoot(float maxDistance) LootObject LootObjectStack::GetLoot(float maxDistance)
{ {
std::vector<LootObject> ordered = OrderByDistance(maxDistance); LootObject nearest = GetNearest(maxDistance);
return ordered.empty() ? LootObject() : *ordered.begin(); return nearest.IsEmpty() ? LootObject() : nearest;
} }
std::vector<LootObject> LootObjectStack::OrderByDistance(float maxDistance)
LootObject LootObjectStack::GetNearest(float maxDistance)
{ {
availableLoot.shrink(time(nullptr) - 30); availableLoot.shrink(time(nullptr) - 30);
std::map<float, LootObject> sortedMap; LootObject nearest;
float nearestDistance = std::numeric_limits<float>::max();
LootTargetList safeCopy(availableLoot); LootTargetList safeCopy(availableLoot);
for (LootTargetList::iterator i = safeCopy.begin(); i != safeCopy.end(); i++) for (LootTargetList::iterator i = safeCopy.begin(); i != safeCopy.end(); i++)
{ {
ObjectGuid guid = i->guid; ObjectGuid guid = i->guid;
LootObject lootObject(bot, guid);
if (!lootObject.IsLootPossible(bot)) // Ensure loot object is valid
continue;
WorldObject* worldObj = lootObject.GetWorldObject(bot); WorldObject* worldObj = ObjectAccessor::GetWorldObject(*bot, guid);
if (!worldObj) // Prevent null pointer dereference if (!worldObj)
{
continue; continue;
}
float distance = bot->GetDistance(worldObj); float distance = bot->GetDistance(worldObj);
if (!maxDistance || distance <= maxDistance)
sortedMap[distance] = lootObject; if (distance >= nearestDistance || (maxDistance && distance > maxDistance))
continue;
LootObject lootObject(bot, guid);
if (!lootObject.IsLootPossible(bot))
continue;
nearestDistance = distance;
nearest = lootObject;
} }
std::vector<LootObject> result; return nearest;
for (auto& [_, lootObject] : sortedMap) }
result.push_back(lootObject);
return result;
}

View File

@@ -78,7 +78,7 @@ public:
LootObject GetLoot(float maxDistance = 0); LootObject GetLoot(float maxDistance = 0);
private: private:
std::vector<LootObject> OrderByDistance(float maxDistance = 0); LootObject GetNearest(float maxDistance = 0);
Player* bot; Player* bot;
LootTargetList availableLoot; LootTargetList availableLoot;

View File

@@ -1049,6 +1049,9 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet)
default: default:
return; return;
} }
if (chanName == "World")
return;
// do not reply to self but always try to reply to real player // do not reply to self but always try to reply to real player
if (guid1 != bot->GetGUID()) if (guid1 != bot->GetGUID())

View File

@@ -610,12 +610,7 @@ bool PlayerbotAIConfig::Initialize()
sPlayerbotTextMgr->LoadBotTextChance(); sPlayerbotTextMgr->LoadBotTextChance();
PlayerbotFactory::Init(); PlayerbotFactory::Init();
if (!sPlayerbotAIConfig->autoDoQuests) AiObjectContext::BuildAllSharedContexts();
{
LOG_INFO("server.loading", "Loading Quest Detail Data...");
sTravelMgr->LoadQuestTravelTable();
}
if (sPlayerbotAIConfig->randomBotSuggestDungeons) if (sPlayerbotAIConfig->randomBotSuggestDungeons)
{ {

View File

@@ -8,39 +8,89 @@
#include "ActionContext.h" #include "ActionContext.h"
#include "ChatActionContext.h" #include "ChatActionContext.h"
#include "ChatTriggerContext.h" #include "ChatTriggerContext.h"
#include "DKAiObjectContext.h"
#include "DruidAiObjectContext.h"
#include "HunterAiObjectContext.h"
#include "MageAiObjectContext.h"
#include "PaladinAiObjectContext.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "RaidUlduarTriggerContext.h" #include "PriestAiObjectContext.h"
#include "RaidUlduarActionContext.h" #include "RaidUlduarActionContext.h"
#include "RaidUlduarTriggerContext.h"
#include "RogueAiObjectContext.h"
#include "ShamanAiObjectContext.h"
#include "SharedValueContext.h" #include "SharedValueContext.h"
#include "StrategyContext.h" #include "StrategyContext.h"
#include "TriggerContext.h" #include "TriggerContext.h"
#include "ValueContext.h" #include "ValueContext.h"
#include "WarlockAiObjectContext.h"
#include "WarriorAiObjectContext.h"
#include "WorldPacketActionContext.h" #include "WorldPacketActionContext.h"
#include "WorldPacketTriggerContext.h" #include "WorldPacketTriggerContext.h"
#include "raids/RaidStrategyContext.h"
#include "raids/blackwinglair/RaidBwlActionContext.h"
#include "raids/blackwinglair/RaidBwlTriggerContext.h"
#include "raids/naxxramas/RaidNaxxActionContext.h"
#include "raids/naxxramas/RaidNaxxTriggerContext.h"
#include "raids/icecrown/RaidIccActionContext.h"
#include "raids/icecrown/RaidIccTriggerContext.h"
#include "raids/obsidiansanctum/RaidOsActionContext.h"
#include "raids/obsidiansanctum/RaidOsTriggerContext.h"
#include "raids/eyeofeternity/RaidEoEActionContext.h"
#include "raids/vaultofarchavon/RaidVoATriggerContext.h"
#include "raids/onyxia/RaidOnyxiaActionContext.h"
#include "raids/onyxia/RaidOnyxiaTriggerContext.h"
#include "raids/vaultofarchavon/RaidVoAActionContext.h"
#include "raids/eyeofeternity/RaidEoETriggerContext.h"
#include "raids/moltencore/RaidMcActionContext.h"
#include "raids/moltencore/RaidMcTriggerContext.h"
#include "raids/aq20/RaidAq20ActionContext.h"
#include "raids/aq20/RaidAq20TriggerContext.h"
#include "dungeons/DungeonStrategyContext.h" #include "dungeons/DungeonStrategyContext.h"
#include "dungeons/wotlk/WotlkDungeonActionContext.h" #include "dungeons/wotlk/WotlkDungeonActionContext.h"
#include "dungeons/wotlk/WotlkDungeonTriggerContext.h" #include "dungeons/wotlk/WotlkDungeonTriggerContext.h"
#include "raids/RaidStrategyContext.h"
#include "raids/aq20/RaidAq20ActionContext.h"
#include "raids/aq20/RaidAq20TriggerContext.h"
#include "raids/blackwinglair/RaidBwlActionContext.h"
#include "raids/blackwinglair/RaidBwlTriggerContext.h"
#include "raids/eyeofeternity/RaidEoEActionContext.h"
#include "raids/eyeofeternity/RaidEoETriggerContext.h"
#include "raids/icecrown/RaidIccActionContext.h"
#include "raids/icecrown/RaidIccTriggerContext.h"
#include "raids/moltencore/RaidMcActionContext.h"
#include "raids/moltencore/RaidMcTriggerContext.h"
#include "raids/naxxramas/RaidNaxxActionContext.h"
#include "raids/naxxramas/RaidNaxxTriggerContext.h"
#include "raids/obsidiansanctum/RaidOsActionContext.h"
#include "raids/obsidiansanctum/RaidOsTriggerContext.h"
#include "raids/onyxia/RaidOnyxiaActionContext.h"
#include "raids/onyxia/RaidOnyxiaTriggerContext.h"
#include "raids/vaultofarchavon/RaidVoAActionContext.h"
#include "raids/vaultofarchavon/RaidVoATriggerContext.h"
AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) SharedNamedObjectContextList<Strategy> AiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> AiObjectContext::sharedActionContexts;
SharedNamedObjectContextList<Trigger> AiObjectContext::sharedTriggerContexts;
SharedNamedObjectContextList<UntypedValue> AiObjectContext::sharedValueContexts;
AiObjectContext::AiObjectContext(PlayerbotAI* botAI, SharedNamedObjectContextList<Strategy>& sharedStrategyContext,
SharedNamedObjectContextList<Action>& sharedActionContext,
SharedNamedObjectContextList<Trigger>& sharedTriggerContext,
SharedNamedObjectContextList<UntypedValue>& sharedValueContext)
: PlayerbotAIAware(botAI),
strategyContexts(sharedStrategyContext),
actionContexts(sharedActionContext),
triggerContexts(sharedTriggerContext),
valueContexts(sharedValueContext)
{
}
void AiObjectContext::BuildAllSharedContexts()
{
AiObjectContext::BuildSharedContexts();
PriestAiObjectContext::BuildSharedContexts();
MageAiObjectContext::BuildSharedContexts();
WarlockAiObjectContext::BuildSharedContexts();
WarriorAiObjectContext::BuildSharedContexts();
ShamanAiObjectContext::BuildSharedContexts();
PaladinAiObjectContext::BuildSharedContexts();
DruidAiObjectContext::BuildSharedContexts();
HunterAiObjectContext::BuildSharedContexts();
RogueAiObjectContext::BuildSharedContexts();
DKAiObjectContext::BuildSharedContexts();
}
void AiObjectContext::BuildSharedContexts()
{
BuildSharedStrategyContexts(sharedStrategyContexts);
BuildSharedActionContexts(sharedActionContexts);
BuildSharedTriggerContexts(sharedTriggerContexts);
BuildSharedValueContexts(sharedValueContexts);
}
void AiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
{ {
strategyContexts.Add(new StrategyContext()); strategyContexts.Add(new StrategyContext());
strategyContexts.Add(new MovementStrategyContext()); strategyContexts.Add(new MovementStrategyContext());
@@ -48,7 +98,10 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
strategyContexts.Add(new QuestStrategyContext()); strategyContexts.Add(new QuestStrategyContext());
strategyContexts.Add(new RaidStrategyContext()); strategyContexts.Add(new RaidStrategyContext());
strategyContexts.Add(new DungeonStrategyContext()); strategyContexts.Add(new DungeonStrategyContext());
}
void AiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
{
actionContexts.Add(new ActionContext()); actionContexts.Add(new ActionContext());
actionContexts.Add(new ChatActionContext()); actionContexts.Add(new ChatActionContext());
actionContexts.Add(new WorldPacketActionContext()); actionContexts.Add(new WorldPacketActionContext());
@@ -77,7 +130,10 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
actionContexts.Add(new WotlkDungeonFoSActionContext()); actionContexts.Add(new WotlkDungeonFoSActionContext());
actionContexts.Add(new WotlkDungeonPoSActionContext()); actionContexts.Add(new WotlkDungeonPoSActionContext());
actionContexts.Add(new WotlkDungeonToCActionContext()); actionContexts.Add(new WotlkDungeonToCActionContext());
}
void AiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
{
triggerContexts.Add(new TriggerContext()); triggerContexts.Add(new TriggerContext());
triggerContexts.Add(new ChatTriggerContext()); triggerContexts.Add(new ChatTriggerContext());
triggerContexts.Add(new WorldPacketTriggerContext()); triggerContexts.Add(new WorldPacketTriggerContext());
@@ -106,26 +162,11 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
triggerContexts.Add(new WotlkDungeonFoSTriggerContext()); triggerContexts.Add(new WotlkDungeonFoSTriggerContext());
triggerContexts.Add(new WotlkDungeonPoSTriggerContext()); triggerContexts.Add(new WotlkDungeonPoSTriggerContext());
triggerContexts.Add(new WotlkDungeonToCTriggerContext()); triggerContexts.Add(new WotlkDungeonToCTriggerContext());
}
void AiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
{
valueContexts.Add(new ValueContext()); valueContexts.Add(new ValueContext());
valueContexts.Add(sSharedValueContext);
}
void AiObjectContext::Update()
{
strategyContexts.Update();
triggerContexts.Update();
actionContexts.Update();
valueContexts.Update();
}
void AiObjectContext::Reset()
{
strategyContexts.Reset();
triggerContexts.Reset();
actionContexts.Reset();
valueContexts.Reset();
} }
std::vector<std::string> AiObjectContext::Save() std::vector<std::string> AiObjectContext::Save()
@@ -218,5 +259,3 @@ std::string const AiObjectContext::FormatValues()
return out.str(); return out.str();
} }
void AiObjectContext::AddShared(NamedObjectContext<UntypedValue>* sharedValues) { valueContexts.Add(sharedValues); }

View File

@@ -19,10 +19,19 @@
class PlayerbotAI; class PlayerbotAI;
typedef Strategy* (*StrategyCreator)(PlayerbotAI* botAI);
typedef Action* (*ActionCreator)(PlayerbotAI* botAI);
typedef Trigger* (*TriggerCreator)(PlayerbotAI* botAI);
typedef UntypedValue* (*ValueCreator)(PlayerbotAI* botAI);
class AiObjectContext : public PlayerbotAIAware class AiObjectContext : public PlayerbotAIAware
{ {
public: public:
AiObjectContext(PlayerbotAI* botAI); AiObjectContext(PlayerbotAI* botAI,
SharedNamedObjectContextList<Strategy>& sharedStrategyContext = sharedStrategyContexts,
SharedNamedObjectContextList<Action>& sharedActionContext = sharedActionContexts,
SharedNamedObjectContextList<Trigger>& sharedTriggerContext = sharedTriggerContexts,
SharedNamedObjectContextList<UntypedValue>& sharedValueContext = sharedValueContexts);
virtual ~AiObjectContext() {} virtual ~AiObjectContext() {}
virtual Strategy* GetStrategy(std::string const name); virtual Strategy* GetStrategy(std::string const name);
@@ -56,20 +65,30 @@ public:
std::set<std::string> GetSupportedActions(); std::set<std::string> GetSupportedActions();
std::string const FormatValues(); std::string const FormatValues();
virtual void Update();
virtual void Reset();
virtual void AddShared(NamedObjectContext<UntypedValue>* sharedValues);
std::vector<std::string> Save(); std::vector<std::string> Save();
void Load(std::vector<std::string> data); void Load(std::vector<std::string> data);
std::vector<std::string> performanceStack; std::vector<std::string> performanceStack;
static void BuildAllSharedContexts();
static void BuildSharedContexts();
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
protected: protected:
NamedObjectContextList<Strategy> strategyContexts; NamedObjectContextList<Strategy> strategyContexts;
NamedObjectContextList<Action> actionContexts; NamedObjectContextList<Action> actionContexts;
NamedObjectContextList<Trigger> triggerContexts; NamedObjectContextList<Trigger> triggerContexts;
NamedObjectContextList<UntypedValue> valueContexts; NamedObjectContextList<UntypedValue> valueContexts;
private:
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
static SharedNamedObjectContextList<Action> sharedActionContexts;
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
}; };
#endif #endif

View File

@@ -11,6 +11,7 @@
#include "Playerbots.h" #include "Playerbots.h"
#include "Queue.h" #include "Queue.h"
#include "Strategy.h" #include "Strategy.h"
#include "Timer.h"
Engine::Engine(PlayerbotAI* botAI, AiObjectContext* factory) : PlayerbotAIAware(botAI), aiObjectContext(factory) Engine::Engine(PlayerbotAI* botAI, AiObjectContext* factory) : PlayerbotAIAware(botAI), aiObjectContext(factory)
{ {
@@ -108,6 +109,8 @@ void Engine::Reset()
} }
multipliers.clear(); multipliers.clear();
actionNodeFactories.creators.clear();
} }
void Engine::Init() void Engine::Init()
@@ -120,9 +123,10 @@ void Engine::Init()
strategyTypeMask |= strategy->GetType(); strategyTypeMask |= strategy->GetType();
strategy->InitMultipliers(multipliers); strategy->InitMultipliers(multipliers);
strategy->InitTriggers(triggers); strategy->InitTriggers(triggers);
for (auto &iter : strategy->actionNodeFactories.creators)
Event emptyEvent; {
MultiplyAndPush(strategy->getDefaultActions(), 0.0f, false, emptyEvent, "default"); actionNodeFactories.creators[iter.first] = iter.second;
}
} }
if (testMode) if (testMode)
@@ -248,11 +252,9 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
ActionNode* Engine::CreateActionNode(std::string const name) ActionNode* Engine::CreateActionNode(std::string const name)
{ {
for (std::map<std::string, Strategy*>::iterator i = strategies.begin(); i != strategies.end(); i++) ActionNode* node = actionNodeFactories.GetContextObject(name, botAI);
{ if (node)
if (ActionNode* node = i->second->GetAction(name)) return node;
return node;
}
return new ActionNode(name, return new ActionNode(name,
/*P*/ nullptr, /*P*/ nullptr,
@@ -432,6 +434,7 @@ bool Engine::HasStrategy(std::string const name) { return strategies.find(name)
void Engine::ProcessTriggers(bool minimal) void Engine::ProcessTriggers(bool minimal)
{ {
std::unordered_map<Trigger*, Event> fires; std::unordered_map<Trigger*, Event> fires;
uint32 now = getMSTime();
for (std::vector<TriggerNode*>::iterator i = triggers.begin(); i != triggers.end(); i++) for (std::vector<TriggerNode*>::iterator i = triggers.begin(); i != triggers.end(); i++)
{ {
TriggerNode* node = *i; TriggerNode* node = *i;
@@ -451,7 +454,7 @@ void Engine::ProcessTriggers(bool minimal)
if (fires.find(trigger) != fires.end()) if (fires.find(trigger) != fires.end())
continue; continue;
if (testMode || trigger->needCheck()) if (testMode || trigger->needCheck(now))
{ {
if (minimal && node->getFirstRelevance() < 100) if (minimal && node->getFirstRelevance() < 100)
continue; continue;

View File

@@ -114,6 +114,7 @@ protected:
float lastRelevance; float lastRelevance;
std::string lastAction; std::string lastAction;
uint32 strategyTypeMask; uint32 strategyTypeMask;
NamedObjectFactoryList<ActionNode> actionNodeFactories;
}; };
#endif #endif

View File

@@ -29,7 +29,8 @@ public:
std::string const getQualifier() { return qualifier; } std::string const getQualifier() { return qualifier; }
static std::string const MultiQualify(std::vector<std::string> qualifiers, const std::string& separator, const std::string_view brackets = "{}"); static std::string const MultiQualify(std::vector<std::string> qualifiers, const std::string& separator,
const std::string_view brackets = "{}");
static std::vector<std::string> getMultiQualifiers(std::string const qualifier1); static std::vector<std::string> getMultiQualifiers(std::string const qualifier1);
static int32 getMultiQualifier(std::string const qualifier1, uint32 pos); static int32 getMultiQualifier(std::string const qualifier1, uint32 pos);
@@ -40,9 +41,9 @@ protected:
template <class T> template <class T>
class NamedObjectFactory class NamedObjectFactory
{ {
protected: public:
typedef T* (*ActionCreator)(PlayerbotAI* botAI); typedef T* (*ObjectCreator)(PlayerbotAI* botAI);
std::unordered_map<std::string, ActionCreator> creators; std::unordered_map<std::string, ObjectCreator> creators;
public: public:
T* create(std::string name, PlayerbotAI* botAI) T* create(std::string name, PlayerbotAI* botAI)
@@ -58,7 +59,7 @@ public:
if (creators.find(name) == creators.end()) if (creators.find(name) == creators.end())
return nullptr; return nullptr;
ActionCreator creator = creators[name]; ObjectCreator creator = creators[name];
if (!creator) if (!creator)
return nullptr; return nullptr;
@@ -73,7 +74,7 @@ public:
std::set<std::string> supports() std::set<std::string> supports()
{ {
std::set<std::string> keys; std::set<std::string> keys;
for (typename std::unordered_map<std::string, ActionCreator>::iterator it = creators.begin(); for (typename std::unordered_map<std::string, ObjectCreator>::iterator it = creators.begin();
it != creators.end(); it++) it != creators.end(); it++)
keys.insert(it->first); keys.insert(it->first);
@@ -111,24 +112,6 @@ public:
created.clear(); created.clear();
} }
void Update()
{
for (typename std::unordered_map<std::string, T*>::iterator i = created.begin(); i != created.end(); i++)
{
if (i->second)
i->second->Update();
}
}
void Reset()
{
for (typename std::unordered_map<std::string, T*>::iterator i = created.begin(); i != created.end(); i++)
{
if (i->second)
i->second->Reset();
}
}
bool IsShared() { return shared; } bool IsShared() { return shared; }
bool IsSupportsSiblings() { return supportsSiblings; } bool IsSupportsSiblings() { return supportsSiblings; }
@@ -147,53 +130,93 @@ protected:
bool supportsSiblings; bool supportsSiblings;
}; };
template <class T>
class SharedNamedObjectContextList
{
public:
typedef T* (*ObjectCreator)(PlayerbotAI* botAI);
std::unordered_map<std::string, ObjectCreator> creators;
std::vector<NamedObjectContext<T>*> contexts;
~SharedNamedObjectContextList()
{
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
delete *i;
}
void Add(NamedObjectContext<T>* context)
{
contexts.push_back(context);
for (const auto& iter : context->creators)
{
creators[iter.first] = iter.second;
}
}
};
template <class T> template <class T>
class NamedObjectContextList class NamedObjectContextList
{ {
public: public:
virtual ~NamedObjectContextList() typedef T* (*ObjectCreator)(PlayerbotAI* botAI);
const std::unordered_map<std::string, ObjectCreator>& creators;
const std::vector<NamedObjectContext<T>*>& contexts;
std::unordered_map<std::string, T*> created;
NamedObjectContextList(const SharedNamedObjectContextList<T>& shared)
: creators(shared.creators), contexts(shared.contexts)
{ {
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
NamedObjectContext<T>* context = *i;
if (!context->IsShared())
delete context;
}
} }
void Add(NamedObjectContext<T>* context) { contexts.push_back(context); } ~NamedObjectContextList()
{
for (typename std::unordered_map<std::string, T*>::iterator i = created.begin(); i != created.end(); i++)
{
if (i->second)
delete i->second;
}
created.clear();
}
T* create(std::string name, PlayerbotAI* botAI)
{
size_t found = name.find("::");
std::string qualifier;
if (found != std::string::npos)
{
qualifier = name.substr(found + 2);
name = name.substr(0, found);
}
if (creators.find(name) == creators.end())
return nullptr;
ObjectCreator creator = creators.at(name);
if (!creator)
return nullptr;
T* object = (*creator)(botAI);
Qualified* q = dynamic_cast<Qualified*>(object);
if (q && found != std::string::npos)
q->Qualify(qualifier);
return object;
}
T* GetContextObject(std::string const name, PlayerbotAI* botAI) T* GetContextObject(std::string const name, PlayerbotAI* botAI)
{ {
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++) if (created.find(name) == created.end())
{ {
if (T* object = (*i)->create(name, botAI)) if (T* object = create(name, botAI))
return object; return created[name] = object;
}
return nullptr;
}
void Update()
{
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
if (!(*i)->IsShared())
(*i)->Update();
}
}
void Reset()
{
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
(*i)->Reset();
} }
return created[name];
} }
std::set<std::string> GetSiblings(std::string const name) std::set<std::string> GetSiblings(std::string const name)
{ {
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++) for (auto i = contexts.begin(); i != contexts.end(); i++)
{ {
if (!(*i)->IsSupportsSiblings()) if (!(*i)->IsSupportsSiblings())
continue; continue;
@@ -213,7 +236,7 @@ public:
std::set<std::string> supports() std::set<std::string> supports()
{ {
std::set<std::string> result; std::set<std::string> result;
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++) for (auto i = contexts.begin(); i != contexts.end(); i++)
{ {
std::set<std::string> supported = (*i)->supports(); std::set<std::string> supported = (*i)->supports();
@@ -227,46 +250,69 @@ public:
std::set<std::string> GetCreated() std::set<std::string> GetCreated()
{ {
std::set<std::string> result; std::set<std::string> result;
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++) for (typename std::unordered_map<std::string, T*>::iterator i = created.begin(); i != created.end(); i++)
{ {
std::set<std::string> createdKeys = (*i)->GetCreated(); result.insert(i->first);
for (std::set<std::string>::iterator j = createdKeys.begin(); j != createdKeys.end(); j++)
result.insert(*j);
} }
return result; return result;
} }
private:
std::vector<NamedObjectContext<T>*> contexts;
}; };
template <class T> template <class T>
class NamedObjectFactoryList class NamedObjectFactoryList
{ {
public: public:
typedef T* (*ObjectCreator)(PlayerbotAI* botAI);
std::vector<NamedObjectFactory<T>*> factories;
std::unordered_map<std::string, ObjectCreator> creators;
virtual ~NamedObjectFactoryList() virtual ~NamedObjectFactoryList()
{ {
for (typename std::list<NamedObjectFactory<T>*>::iterator i = factories.begin(); i != factories.end(); i++) for (typename std::vector<NamedObjectFactory<T>*>::iterator i = factories.begin(); i != factories.end(); i++)
delete *i; delete *i;
} }
void Add(NamedObjectFactory<T>* context) { factories.push_front(context); } T* create(std::string name, PlayerbotAI* botAI)
T* GetContextObject(std::string const& name, PlayerbotAI* botAI)
{ {
for (typename std::list<NamedObjectFactory<T>*>::iterator i = factories.begin(); i != factories.end(); i++) size_t found = name.find("::");
std::string qualifier;
if (found != std::string::npos)
{ {
if (T* object = (*i)->create(name, botAI)) qualifier = name.substr(found + 2);
return object; name = name.substr(0, found);
} }
return nullptr; if (creators.find(name) == creators.end())
return nullptr;
ObjectCreator creator = creators[name];
if (!creator)
return nullptr;
T* object = (*creator)(botAI);
Qualified* q = dynamic_cast<Qualified*>(object);
if (q && found != std::string::npos)
q->Qualify(qualifier);
return object;
} }
private: void Add(NamedObjectFactory<T>* context)
std::list<NamedObjectFactory<T>*> factories; {
factories.push_back(context);
for (const auto& iter : context->creators)
{
creators[iter.first] = iter.second;
}
}
T* GetContextObject(std::string const name, PlayerbotAI* botAI)
{
if (T* object = create(name, botAI))
return object;
return nullptr;
}
}; };
#endif #endif

View File

@@ -69,7 +69,7 @@ public:
void Update() {} void Update() {}
void Reset() {} void Reset() {}
protected: public:
NamedObjectFactoryList<ActionNode> actionNodeFactories; NamedObjectFactoryList<ActionNode> actionNodeFactories;
}; };

View File

@@ -32,12 +32,11 @@ Value<Unit*>* Trigger::GetTargetValue() { return context->GetValue<Unit*>(GetTar
Unit* Trigger::GetTarget() { return GetTargetValue()->Get(); } Unit* Trigger::GetTarget() { return GetTargetValue()->Get(); }
bool Trigger::needCheck() bool Trigger::needCheck(uint32 now)
{ {
if (checkInterval < 2) if (checkInterval < 2)
return true; return true;
uint32 now = getMSTime();
if (!lastCheckTime || now - lastCheckTime >= checkInterval) if (!lastCheckTime || now - lastCheckTime >= checkInterval)
{ {
lastCheckTime = now; lastCheckTime = now;

View File

@@ -30,7 +30,7 @@ public:
virtual Value<Unit*>* GetTargetValue(); virtual Value<Unit*>* GetTargetValue();
virtual std::string const GetTargetName() { return "self target"; } virtual std::string const GetTargetName() { return "self target"; }
bool needCheck(); bool needCheck(uint32 now);
protected: protected:
int32 checkInterval; int32 checkInterval;

View File

@@ -108,14 +108,20 @@ private:
static Trigger* blood_strike(PlayerbotAI* botAI) { return new BloodStrikeTrigger(botAI); } static Trigger* blood_strike(PlayerbotAI* botAI) { return new BloodStrikeTrigger(botAI); }
static Trigger* plague_strike(PlayerbotAI* botAI) { return new PlagueStrikeDebuffTrigger(botAI); } static Trigger* plague_strike(PlayerbotAI* botAI) { return new PlagueStrikeDebuffTrigger(botAI); }
static Trigger* plague_strike_3s(PlayerbotAI* botAI) { return new PlagueStrike3sDebuffTrigger(botAI); } static Trigger* plague_strike_3s(PlayerbotAI* botAI) { return new PlagueStrike3sDebuffTrigger(botAI); }
static Trigger* dd_cd_and_plague_strike_3s(PlayerbotAI* botAI) { return new TwoTriggers(botAI, "death and decay cooldown", "plague strike 3s"); } static Trigger* dd_cd_and_plague_strike_3s(PlayerbotAI* botAI)
{
return new TwoTriggers(botAI, "death and decay cooldown", "plague strike 3s");
}
static Trigger* plague_strike_on_attacker(PlayerbotAI* botAI) static Trigger* plague_strike_on_attacker(PlayerbotAI* botAI)
{ {
return new PlagueStrikeDebuffOnAttackerTrigger(botAI); return new PlagueStrikeDebuffOnAttackerTrigger(botAI);
} }
static Trigger* icy_touch(PlayerbotAI* botAI) { return new IcyTouchDebuffTrigger(botAI); } static Trigger* icy_touch(PlayerbotAI* botAI) { return new IcyTouchDebuffTrigger(botAI); }
static Trigger* icy_touch_3s(PlayerbotAI* botAI) { return new IcyTouch3sDebuffTrigger(botAI); } static Trigger* icy_touch_3s(PlayerbotAI* botAI) { return new IcyTouch3sDebuffTrigger(botAI); }
static Trigger* dd_cd_and_icy_touch_3s(PlayerbotAI* botAI) { return new TwoTriggers(botAI, "death and decay cooldown", "icy touch 3s"); } static Trigger* dd_cd_and_icy_touch_3s(PlayerbotAI* botAI)
{
return new TwoTriggers(botAI, "death and decay cooldown", "icy touch 3s");
}
static Trigger* death_coil(PlayerbotAI* botAI) { return new DeathCoilTrigger(botAI); } static Trigger* death_coil(PlayerbotAI* botAI) { return new DeathCoilTrigger(botAI); }
static Trigger* icy_touch_on_attacker(PlayerbotAI* botAI) { return new IcyTouchDebuffOnAttackerTrigger(botAI); } static Trigger* icy_touch_on_attacker(PlayerbotAI* botAI) { return new IcyTouchDebuffOnAttackerTrigger(botAI); }
static Trigger* improved_icy_talons(PlayerbotAI* botAI) { return new ImprovedIcyTalonsTrigger(botAI); } static Trigger* improved_icy_talons(PlayerbotAI* botAI) { return new ImprovedIcyTalonsTrigger(botAI); }
@@ -140,7 +146,10 @@ private:
static Trigger* no_rune(PlayerbotAI* botAI) { return new NoRuneTrigger(botAI); } static Trigger* no_rune(PlayerbotAI* botAI) { return new NoRuneTrigger(botAI); }
static Trigger* freezing_fog(PlayerbotAI* botAI) { return new FreezingFogTrigger(botAI); } static Trigger* freezing_fog(PlayerbotAI* botAI) { return new FreezingFogTrigger(botAI); }
static Trigger* no_desolation(PlayerbotAI* botAI) { return new DesolationTrigger(botAI); } static Trigger* no_desolation(PlayerbotAI* botAI) { return new DesolationTrigger(botAI); }
static Trigger* dd_cd_and_no_desolation(PlayerbotAI* botAI) { return new TwoTriggers(botAI, "death and decay cooldown", "no desolation"); } static Trigger* dd_cd_and_no_desolation(PlayerbotAI* botAI)
{
return new TwoTriggers(botAI, "death and decay cooldown", "no desolation");
}
static Trigger* death_and_decay_cooldown(PlayerbotAI* botAI) { return new DeathAndDecayCooldownTrigger(botAI); } static Trigger* death_and_decay_cooldown(PlayerbotAI* botAI) { return new DeathAndDecayCooldownTrigger(botAI); }
static Trigger* army_of_the_dead(PlayerbotAI* botAI) { return new ArmyOfTheDeadTrigger(botAI); } static Trigger* army_of_the_dead(PlayerbotAI* botAI) { return new ArmyOfTheDeadTrigger(botAI); }
}; };
@@ -265,11 +274,45 @@ private:
} }
}; };
DKAiObjectContext::DKAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) SharedNamedObjectContextList<Strategy> DKAiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> DKAiObjectContext::sharedActionContexts;
SharedNamedObjectContextList<Trigger> DKAiObjectContext::sharedTriggerContexts;
SharedNamedObjectContextList<UntypedValue> DKAiObjectContext::sharedValueContexts;
DKAiObjectContext::DKAiObjectContext(PlayerbotAI* botAI)
: AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts)
{ {
}
void DKAiObjectContext::BuildSharedContexts()
{
BuildSharedStrategyContexts(sharedStrategyContexts);
BuildSharedActionContexts(sharedActionContexts);
BuildSharedTriggerContexts(sharedTriggerContexts);
BuildSharedValueContexts(sharedValueContexts);
}
void DKAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
{
AiObjectContext::BuildSharedStrategyContexts(strategyContexts);
strategyContexts.Add(new DeathKnightStrategyFactoryInternal()); strategyContexts.Add(new DeathKnightStrategyFactoryInternal());
strategyContexts.Add(new DeathKnightCombatStrategyFactoryInternal()); strategyContexts.Add(new DeathKnightCombatStrategyFactoryInternal());
strategyContexts.Add(new DeathKnightDKBuffStrategyFactoryInternal()); strategyContexts.Add(new DeathKnightDKBuffStrategyFactoryInternal());
}
void DKAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
{
AiObjectContext::BuildSharedActionContexts(actionContexts);
actionContexts.Add(new DeathKnightAiObjectContextInternal()); actionContexts.Add(new DeathKnightAiObjectContextInternal());
}
void DKAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
{
AiObjectContext::BuildSharedTriggerContexts(triggerContexts);
triggerContexts.Add(new DeathKnightTriggerFactoryInternal()); triggerContexts.Add(new DeathKnightTriggerFactoryInternal());
} }
void DKAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
{
AiObjectContext::BuildSharedValueContexts(valueContexts);
}

View File

@@ -14,6 +14,17 @@ class DKAiObjectContext : public AiObjectContext
{ {
public: public:
DKAiObjectContext(PlayerbotAI* botAI); DKAiObjectContext(PlayerbotAI* botAI);
static void BuildSharedContexts();
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
static SharedNamedObjectContextList<Action> sharedActionContexts;
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
}; };
#endif #endif

View File

@@ -8,7 +8,6 @@
#include "BearTankDruidStrategy.h" #include "BearTankDruidStrategy.h"
#include "CasterDruidStrategy.h" #include "CasterDruidStrategy.h"
#include "CatDpsDruidStrategy.h" #include "CatDpsDruidStrategy.h"
#include "OffhealDruidCatStrategy.h"
#include "DruidActions.h" #include "DruidActions.h"
#include "DruidBearActions.h" #include "DruidBearActions.h"
#include "DruidCatActions.h" #include "DruidCatActions.h"
@@ -18,6 +17,7 @@
#include "GenericDruidStrategy.h" #include "GenericDruidStrategy.h"
#include "HealDruidStrategy.h" #include "HealDruidStrategy.h"
#include "MeleeDruidStrategy.h" #include "MeleeDruidStrategy.h"
#include "OffhealDruidCatStrategy.h"
#include "Playerbots.h" #include "Playerbots.h"
class DruidStrategyFactoryInternal : public NamedObjectContext<Strategy> class DruidStrategyFactoryInternal : public NamedObjectContext<Strategy>
@@ -324,10 +324,44 @@ private:
static Action* force_of_nature(PlayerbotAI* ai) { return new CastForceOfNatureAction(ai); } static Action* force_of_nature(PlayerbotAI* ai) { return new CastForceOfNatureAction(ai); }
}; };
DruidAiObjectContext::DruidAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) SharedNamedObjectContextList<Strategy> DruidAiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> DruidAiObjectContext::sharedActionContexts;
SharedNamedObjectContextList<Trigger> DruidAiObjectContext::sharedTriggerContexts;
SharedNamedObjectContextList<UntypedValue> DruidAiObjectContext::sharedValueContexts;
DruidAiObjectContext::DruidAiObjectContext(PlayerbotAI* botAI)
: AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts)
{ {
}
void DruidAiObjectContext::BuildSharedContexts()
{
BuildSharedStrategyContexts(sharedStrategyContexts);
BuildSharedActionContexts(sharedActionContexts);
BuildSharedTriggerContexts(sharedTriggerContexts);
BuildSharedValueContexts(sharedValueContexts);
}
void DruidAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
{
AiObjectContext::BuildSharedStrategyContexts(strategyContexts);
strategyContexts.Add(new DruidStrategyFactoryInternal()); strategyContexts.Add(new DruidStrategyFactoryInternal());
strategyContexts.Add(new DruidDruidStrategyFactoryInternal()); strategyContexts.Add(new DruidDruidStrategyFactoryInternal());
}
void DruidAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
{
AiObjectContext::BuildSharedActionContexts(actionContexts);
actionContexts.Add(new DruidAiObjectContextInternal()); actionContexts.Add(new DruidAiObjectContextInternal());
}
void DruidAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
{
AiObjectContext::BuildSharedTriggerContexts(triggerContexts);
triggerContexts.Add(new DruidTriggerFactoryInternal()); triggerContexts.Add(new DruidTriggerFactoryInternal());
} }
void DruidAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
{
AiObjectContext::BuildSharedValueContexts(valueContexts);
}

View File

@@ -14,6 +14,17 @@ class DruidAiObjectContext : public AiObjectContext
{ {
public: public:
DruidAiObjectContext(PlayerbotAI* botAI); DruidAiObjectContext(PlayerbotAI* botAI);
static void BuildSharedContexts();
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
static SharedNamedObjectContextList<Action> sharedActionContexts;
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
}; };
#endif #endif

View File

@@ -4,16 +4,17 @@
*/ */
#include "HunterAiObjectContext.h" #include "HunterAiObjectContext.h"
#include "BeastMasteryHunterStrategy.h" #include "BeastMasteryHunterStrategy.h"
#include "MarksmanshipHunterStrategy.h"
#include "SurvivalHunterStrategy.h"
#include "GenericHunterNonCombatStrategy.h" #include "GenericHunterNonCombatStrategy.h"
#include "GenericHunterStrategy.h" #include "GenericHunterStrategy.h"
#include "HunterActions.h" #include "HunterActions.h"
#include "HunterBuffStrategies.h" #include "HunterBuffStrategies.h"
#include "HunterTriggers.h" #include "HunterTriggers.h"
#include "MarksmanshipHunterStrategy.h"
#include "NamedObjectContext.h" #include "NamedObjectContext.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "SurvivalHunterStrategy.h"
class HunterStrategyFactoryInternal : public NamedObjectContext<Strategy> class HunterStrategyFactoryInternal : public NamedObjectContext<Strategy>
{ {
@@ -105,7 +106,10 @@ public:
private: private:
static Trigger* auto_shot(PlayerbotAI* botAI) { return new AutoShotTrigger(botAI); } static Trigger* auto_shot(PlayerbotAI* botAI) { return new AutoShotTrigger(botAI); }
static Trigger* scare_beast(PlayerbotAI* botAI) { return new ScareBeastTrigger(botAI); } static Trigger* scare_beast(PlayerbotAI* botAI) { return new ScareBeastTrigger(botAI); }
static Trigger* concussive_shot_on_snare_target(PlayerbotAI* botAI) { return new ConsussiveShotSnareTrigger(botAI); } static Trigger* concussive_shot_on_snare_target(PlayerbotAI* botAI)
{
return new ConsussiveShotSnareTrigger(botAI);
}
static Trigger* pet_not_happy(PlayerbotAI* botAI) { return new HunterPetNotHappy(botAI); } static Trigger* pet_not_happy(PlayerbotAI* botAI) { return new HunterPetNotHappy(botAI); }
static Trigger* serpent_sting_on_attacker(PlayerbotAI* botAI) { return new SerpentStingOnAttackerTrigger(botAI); } static Trigger* serpent_sting_on_attacker(PlayerbotAI* botAI) { return new SerpentStingOnAttackerTrigger(botAI); }
static Trigger* trueshot_aura(PlayerbotAI* botAI) { return new TrueshotAuraTrigger(botAI); } static Trigger* trueshot_aura(PlayerbotAI* botAI) { return new TrueshotAuraTrigger(botAI); }
@@ -258,10 +262,44 @@ private:
static Action* intimidation(PlayerbotAI* ai) { return new CastIntimidationAction(ai); } static Action* intimidation(PlayerbotAI* ai) { return new CastIntimidationAction(ai); }
}; };
HunterAiObjectContext::HunterAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) SharedNamedObjectContextList<Strategy> HunterAiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> HunterAiObjectContext::sharedActionContexts;
SharedNamedObjectContextList<Trigger> HunterAiObjectContext::sharedTriggerContexts;
SharedNamedObjectContextList<UntypedValue> HunterAiObjectContext::sharedValueContexts;
HunterAiObjectContext::HunterAiObjectContext(PlayerbotAI* botAI)
: AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts)
{ {
}
void HunterAiObjectContext::BuildSharedContexts()
{
BuildSharedStrategyContexts(sharedStrategyContexts);
BuildSharedActionContexts(sharedActionContexts);
BuildSharedTriggerContexts(sharedTriggerContexts);
BuildSharedValueContexts(sharedValueContexts);
}
void HunterAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
{
AiObjectContext::BuildSharedStrategyContexts(strategyContexts);
strategyContexts.Add(new HunterStrategyFactoryInternal()); strategyContexts.Add(new HunterStrategyFactoryInternal());
strategyContexts.Add(new HunterBuffStrategyFactoryInternal()); strategyContexts.Add(new HunterBuffStrategyFactoryInternal());
}
void HunterAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
{
AiObjectContext::BuildSharedActionContexts(actionContexts);
actionContexts.Add(new HunterAiObjectContextInternal()); actionContexts.Add(new HunterAiObjectContextInternal());
}
void HunterAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
{
AiObjectContext::BuildSharedTriggerContexts(triggerContexts);
triggerContexts.Add(new HunterTriggerFactoryInternal()); triggerContexts.Add(new HunterTriggerFactoryInternal());
} }
void HunterAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
{
AiObjectContext::BuildSharedValueContexts(valueContexts);
}

View File

@@ -14,6 +14,17 @@ class HunterAiObjectContext : public AiObjectContext
{ {
public: public:
HunterAiObjectContext(PlayerbotAI* botAI); HunterAiObjectContext(PlayerbotAI* botAI);
static void BuildSharedContexts();
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
static SharedNamedObjectContextList<Action> sharedActionContexts;
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
}; };
#endif #endif

View File

@@ -24,7 +24,7 @@ public:
creators["nc"] = &MageStrategyFactoryInternal::nc; creators["nc"] = &MageStrategyFactoryInternal::nc;
creators["pull"] = &MageStrategyFactoryInternal::pull; creators["pull"] = &MageStrategyFactoryInternal::pull;
creators["fire aoe"] = &MageStrategyFactoryInternal::fire_aoe; creators["fire aoe"] = &MageStrategyFactoryInternal::fire_aoe;
creators["frostfire aoe"] = &MageStrategyFactoryInternal::frostfire_aoe; creators["frostfire aoe"] = &MageStrategyFactoryInternal::frostfire_aoe;
creators["frost aoe"] = &MageStrategyFactoryInternal::frost_aoe; creators["frost aoe"] = &MageStrategyFactoryInternal::frost_aoe;
creators["arcane aoe"] = &MageStrategyFactoryInternal::arcane_aoe; creators["arcane aoe"] = &MageStrategyFactoryInternal::arcane_aoe;
creators["cure"] = &MageStrategyFactoryInternal::cure; creators["cure"] = &MageStrategyFactoryInternal::cure;
@@ -268,11 +268,45 @@ private:
static Action* blink_back(PlayerbotAI* botAI) { return new CastBlinkBackAction(botAI); } static Action* blink_back(PlayerbotAI* botAI) { return new CastBlinkBackAction(botAI); }
}; };
MageAiObjectContext::MageAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) SharedNamedObjectContextList<Strategy> MageAiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> MageAiObjectContext::sharedActionContexts;
SharedNamedObjectContextList<Trigger> MageAiObjectContext::sharedTriggerContexts;
SharedNamedObjectContextList<UntypedValue> MageAiObjectContext::sharedValueContexts;
MageAiObjectContext::MageAiObjectContext(PlayerbotAI* botAI)
: AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts)
{ {
}
void MageAiObjectContext::BuildSharedContexts()
{
BuildSharedStrategyContexts(sharedStrategyContexts);
BuildSharedActionContexts(sharedActionContexts);
BuildSharedTriggerContexts(sharedTriggerContexts);
BuildSharedValueContexts(sharedValueContexts);
}
void MageAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
{
AiObjectContext::BuildSharedStrategyContexts(strategyContexts);
strategyContexts.Add(new MageStrategyFactoryInternal()); strategyContexts.Add(new MageStrategyFactoryInternal());
strategyContexts.Add(new MageCombatStrategyFactoryInternal()); strategyContexts.Add(new MageCombatStrategyFactoryInternal());
strategyContexts.Add(new MageBuffStrategyFactoryInternal()); strategyContexts.Add(new MageBuffStrategyFactoryInternal());
}
void MageAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
{
AiObjectContext::BuildSharedActionContexts(actionContexts);
actionContexts.Add(new MageAiObjectContextInternal()); actionContexts.Add(new MageAiObjectContextInternal());
}
void MageAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
{
AiObjectContext::BuildSharedTriggerContexts(triggerContexts);
triggerContexts.Add(new MageTriggerFactoryInternal()); triggerContexts.Add(new MageTriggerFactoryInternal());
} }
void MageAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
{
AiObjectContext::BuildSharedValueContexts(valueContexts);
}

View File

@@ -14,6 +14,17 @@ class MageAiObjectContext : public AiObjectContext
{ {
public: public:
MageAiObjectContext(PlayerbotAI* botAI); MageAiObjectContext(PlayerbotAI* botAI);
static void BuildSharedContexts();
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
static SharedNamedObjectContextList<Action> sharedActionContexts;
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
}; };
#endif #endif

View File

@@ -8,8 +8,8 @@
#include "DpsPaladinStrategy.h" #include "DpsPaladinStrategy.h"
#include "GenericPaladinNonCombatStrategy.h" #include "GenericPaladinNonCombatStrategy.h"
#include "HealPaladinStrategy.h" #include "HealPaladinStrategy.h"
#include "OffhealRetPaladinStrategy.h"
#include "NamedObjectContext.h" #include "NamedObjectContext.h"
#include "OffhealRetPaladinStrategy.h"
#include "PaladinActions.h" #include "PaladinActions.h"
#include "PaladinBuffStrategies.h" #include "PaladinBuffStrategies.h"
#include "PaladinTriggers.h" #include "PaladinTriggers.h"
@@ -207,9 +207,15 @@ private:
static Trigger* sacred_shield_on_main_tank(PlayerbotAI* ai) { return new SacredShieldOnMainTankTrigger(ai); } static Trigger* sacred_shield_on_main_tank(PlayerbotAI* ai) { return new SacredShieldOnMainTankTrigger(ai); }
static Trigger* blessing_of_kings_on_party(PlayerbotAI* botAI) { return new BlessingOfKingsOnPartyTrigger(botAI); } static Trigger* blessing_of_kings_on_party(PlayerbotAI* botAI) { return new BlessingOfKingsOnPartyTrigger(botAI); }
static Trigger* blessing_of_wisdom_on_party(PlayerbotAI* botAI) { return new BlessingOfWisdomOnPartyTrigger(botAI); } static Trigger* blessing_of_wisdom_on_party(PlayerbotAI* botAI)
{
return new BlessingOfWisdomOnPartyTrigger(botAI);
}
static Trigger* blessing_of_might_on_party(PlayerbotAI* botAI) { return new BlessingOfMightOnPartyTrigger(botAI); } static Trigger* blessing_of_might_on_party(PlayerbotAI* botAI) { return new BlessingOfMightOnPartyTrigger(botAI); }
static Trigger* blessing_of_sanctuary_on_party(PlayerbotAI* botAI) { return new BlessingOfSanctuaryOnPartyTrigger(botAI); } static Trigger* blessing_of_sanctuary_on_party(PlayerbotAI* botAI)
{
return new BlessingOfSanctuaryOnPartyTrigger(botAI);
}
static Trigger* avenging_wrath(PlayerbotAI* botAI) { return new AvengingWrathTrigger(botAI); } static Trigger* avenging_wrath(PlayerbotAI* botAI) { return new AvengingWrathTrigger(botAI); }
}; };
@@ -317,10 +323,22 @@ private:
static Action* blessing_of_wisdom(PlayerbotAI* botAI) { return new CastBlessingOfWisdomAction(botAI); } static Action* blessing_of_wisdom(PlayerbotAI* botAI) { return new CastBlessingOfWisdomAction(botAI); }
static Action* blessing_of_kings(PlayerbotAI* botAI) { return new CastBlessingOfKingsAction(botAI); } static Action* blessing_of_kings(PlayerbotAI* botAI) { return new CastBlessingOfKingsAction(botAI); }
static Action* divine_storm(PlayerbotAI* botAI) { return new CastDivineStormAction(botAI); } static Action* divine_storm(PlayerbotAI* botAI) { return new CastDivineStormAction(botAI); }
static Action* blessing_of_kings_on_party(PlayerbotAI* botAI) { return new CastBlessingOfKingsOnPartyAction(botAI); } static Action* blessing_of_kings_on_party(PlayerbotAI* botAI)
static Action* blessing_of_might_on_party(PlayerbotAI* botAI) { return new CastBlessingOfMightOnPartyAction(botAI); } {
static Action* blessing_of_wisdom_on_party(PlayerbotAI* botAI) { return new CastBlessingOfWisdomOnPartyAction(botAI); } return new CastBlessingOfKingsOnPartyAction(botAI);
static Action* blessing_of_sanctuary_on_party(PlayerbotAI* botAI) { return new CastBlessingOfSanctuaryOnPartyAction(botAI); } }
static Action* blessing_of_might_on_party(PlayerbotAI* botAI)
{
return new CastBlessingOfMightOnPartyAction(botAI);
}
static Action* blessing_of_wisdom_on_party(PlayerbotAI* botAI)
{
return new CastBlessingOfWisdomOnPartyAction(botAI);
}
static Action* blessing_of_sanctuary_on_party(PlayerbotAI* botAI)
{
return new CastBlessingOfSanctuaryOnPartyAction(botAI);
}
static Action* redemption(PlayerbotAI* botAI) { return new CastRedemptionAction(botAI); } static Action* redemption(PlayerbotAI* botAI) { return new CastRedemptionAction(botAI); }
static Action* crusader_strike(PlayerbotAI* botAI) { return new CastCrusaderStrikeAction(botAI); } static Action* crusader_strike(PlayerbotAI* botAI) { return new CastCrusaderStrikeAction(botAI); }
static Action* crusader_aura(PlayerbotAI* botAI) { return new CastCrusaderAuraAction(botAI); } static Action* crusader_aura(PlayerbotAI* botAI) { return new CastCrusaderAuraAction(botAI); }
@@ -394,12 +412,46 @@ private:
static Action* cancel_divine_sacrifice(PlayerbotAI* ai) { return new CastCancelDivineSacrificeAction(ai); } static Action* cancel_divine_sacrifice(PlayerbotAI* ai) { return new CastCancelDivineSacrificeAction(ai); }
}; };
PaladinAiObjectContext::PaladinAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) SharedNamedObjectContextList<Strategy> PaladinAiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> PaladinAiObjectContext::sharedActionContexts;
SharedNamedObjectContextList<Trigger> PaladinAiObjectContext::sharedTriggerContexts;
SharedNamedObjectContextList<UntypedValue> PaladinAiObjectContext::sharedValueContexts;
PaladinAiObjectContext::PaladinAiObjectContext(PlayerbotAI* botAI)
: AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts)
{ {
}
void PaladinAiObjectContext::BuildSharedContexts()
{
BuildSharedStrategyContexts(sharedStrategyContexts);
BuildSharedActionContexts(sharedActionContexts);
BuildSharedTriggerContexts(sharedTriggerContexts);
BuildSharedValueContexts(sharedValueContexts);
}
void PaladinAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
{
AiObjectContext::BuildSharedStrategyContexts(strategyContexts);
strategyContexts.Add(new PaladinStrategyFactoryInternal()); strategyContexts.Add(new PaladinStrategyFactoryInternal());
strategyContexts.Add(new PaladinCombatStrategyFactoryInternal()); strategyContexts.Add(new PaladinCombatStrategyFactoryInternal());
strategyContexts.Add(new PaladinBuffStrategyFactoryInternal()); strategyContexts.Add(new PaladinBuffStrategyFactoryInternal());
strategyContexts.Add(new PaladinResistanceStrategyFactoryInternal()); strategyContexts.Add(new PaladinResistanceStrategyFactoryInternal());
}
void PaladinAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
{
AiObjectContext::BuildSharedActionContexts(actionContexts);
actionContexts.Add(new PaladinAiObjectContextInternal()); actionContexts.Add(new PaladinAiObjectContextInternal());
}
void PaladinAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
{
AiObjectContext::BuildSharedTriggerContexts(triggerContexts);
triggerContexts.Add(new PaladinTriggerFactoryInternal()); triggerContexts.Add(new PaladinTriggerFactoryInternal());
} }
void PaladinAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
{
AiObjectContext::BuildSharedValueContexts(valueContexts);
}

View File

@@ -14,6 +14,17 @@ class PaladinAiObjectContext : public AiObjectContext
{ {
public: public:
PaladinAiObjectContext(PlayerbotAI* botAI); PaladinAiObjectContext(PlayerbotAI* botAI);
static void BuildSharedContexts();
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
static SharedNamedObjectContextList<Action> sharedActionContexts;
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
}; };
#endif #endif

View File

@@ -175,8 +175,7 @@ public:
creators["power word: shield on party"] = &PriestAiObjectContextInternal::power_word_shield_on_party; creators["power word: shield on party"] = &PriestAiObjectContextInternal::power_word_shield_on_party;
creators["power word: shield on almost full health below"] = creators["power word: shield on almost full health below"] =
&PriestAiObjectContextInternal::power_word_shield_on_almost_full_health_below; &PriestAiObjectContextInternal::power_word_shield_on_almost_full_health_below;
creators["power word: shield on not full"] = creators["power word: shield on not full"] = &PriestAiObjectContextInternal::power_word_shield_on_not_full;
&PriestAiObjectContextInternal::power_word_shield_on_not_full;
creators["renew"] = &PriestAiObjectContextInternal::renew; creators["renew"] = &PriestAiObjectContextInternal::renew;
creators["renew on party"] = &PriestAiObjectContextInternal::renew_on_party; creators["renew on party"] = &PriestAiObjectContextInternal::renew_on_party;
creators["greater heal"] = &PriestAiObjectContextInternal::greater_heal; creators["greater heal"] = &PriestAiObjectContextInternal::greater_heal;
@@ -289,10 +288,7 @@ private:
{ {
return new CastPowerWordShieldOnAlmostFullHealthBelowAction(ai); return new CastPowerWordShieldOnAlmostFullHealthBelowAction(ai);
} }
static Action* power_word_shield_on_not_full(PlayerbotAI* ai) static Action* power_word_shield_on_not_full(PlayerbotAI* ai) { return new CastPowerWordShieldOnNotFullAction(ai); }
{
return new CastPowerWordShieldOnNotFullAction(ai);
}
static Action* renew(PlayerbotAI* botAI) { return new CastRenewAction(botAI); } static Action* renew(PlayerbotAI* botAI) { return new CastRenewAction(botAI); }
static Action* renew_on_party(PlayerbotAI* botAI) { return new CastRenewOnPartyAction(botAI); } static Action* renew_on_party(PlayerbotAI* botAI) { return new CastRenewOnPartyAction(botAI); }
static Action* greater_heal(PlayerbotAI* botAI) { return new CastGreaterHealAction(botAI); } static Action* greater_heal(PlayerbotAI* botAI) { return new CastGreaterHealAction(botAI); }
@@ -352,10 +348,44 @@ private:
static Action* guardian_spirit_on_party(PlayerbotAI* ai) { return new CastGuardianSpiritOnPartyAction(ai); } static Action* guardian_spirit_on_party(PlayerbotAI* ai) { return new CastGuardianSpiritOnPartyAction(ai); }
}; };
PriestAiObjectContext::PriestAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) SharedNamedObjectContextList<Strategy> PriestAiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> PriestAiObjectContext::sharedActionContexts;
SharedNamedObjectContextList<Trigger> PriestAiObjectContext::sharedTriggerContexts;
SharedNamedObjectContextList<UntypedValue> PriestAiObjectContext::sharedValueContexts;
PriestAiObjectContext::PriestAiObjectContext(PlayerbotAI* botAI)
: AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts)
{ {
}
void PriestAiObjectContext::BuildSharedContexts()
{
BuildSharedStrategyContexts(sharedStrategyContexts);
BuildSharedActionContexts(sharedActionContexts);
BuildSharedTriggerContexts(sharedTriggerContexts);
BuildSharedValueContexts(sharedValueContexts);
}
void PriestAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
{
AiObjectContext::BuildSharedStrategyContexts(strategyContexts);
strategyContexts.Add(new PriestStrategyFactoryInternal()); strategyContexts.Add(new PriestStrategyFactoryInternal());
strategyContexts.Add(new PriestCombatStrategyFactoryInternal()); strategyContexts.Add(new PriestCombatStrategyFactoryInternal());
}
void PriestAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
{
AiObjectContext::BuildSharedActionContexts(actionContexts);
actionContexts.Add(new PriestAiObjectContextInternal()); actionContexts.Add(new PriestAiObjectContextInternal());
}
void PriestAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
{
AiObjectContext::BuildSharedTriggerContexts(triggerContexts);
triggerContexts.Add(new PriestTriggerFactoryInternal()); triggerContexts.Add(new PriestTriggerFactoryInternal());
} }
void PriestAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
{
AiObjectContext::BuildSharedValueContexts(valueContexts);
}

View File

@@ -14,6 +14,17 @@ class PriestAiObjectContext : public AiObjectContext
{ {
public: public:
PriestAiObjectContext(PlayerbotAI* botAI); PriestAiObjectContext(PlayerbotAI* botAI);
static void BuildSharedContexts();
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
static SharedNamedObjectContextList<Action> sharedActionContexts;
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
}; };
#endif #endif

View File

@@ -5,6 +5,7 @@
#include "RogueAiObjectContext.h" #include "RogueAiObjectContext.h"
#include "AiObjectContext.h"
#include "AssassinationRogueStrategy.h" #include "AssassinationRogueStrategy.h"
#include "DpsRogueStrategy.h" #include "DpsRogueStrategy.h"
#include "GenericRogueNonCombatStrategy.h" #include "GenericRogueNonCombatStrategy.h"
@@ -185,10 +186,45 @@ private:
static Action* killing_spree(PlayerbotAI* ai) { return new CastKillingSpreeAction(ai); } static Action* killing_spree(PlayerbotAI* ai) { return new CastKillingSpreeAction(ai); }
}; };
RogueAiObjectContext::RogueAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) SharedNamedObjectContextList<Strategy> RogueAiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> RogueAiObjectContext::sharedActionContexts;
SharedNamedObjectContextList<Trigger> RogueAiObjectContext::sharedTriggerContexts;
SharedNamedObjectContextList<UntypedValue> RogueAiObjectContext::sharedValueContexts;
RogueAiObjectContext::RogueAiObjectContext(PlayerbotAI* botAI)
: AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts,
sharedTriggerContexts, sharedValueContexts)
{ {
}
void RogueAiObjectContext::BuildSharedContexts()
{
BuildSharedStrategyContexts(sharedStrategyContexts);
BuildSharedActionContexts(sharedActionContexts);
BuildSharedTriggerContexts(sharedTriggerContexts);
BuildSharedValueContexts(sharedValueContexts);
}
void RogueAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
{
AiObjectContext::BuildSharedStrategyContexts(strategyContexts);
strategyContexts.Add(new RogueStrategyFactoryInternal()); strategyContexts.Add(new RogueStrategyFactoryInternal());
strategyContexts.Add(new RogueCombatStrategyFactoryInternal()); strategyContexts.Add(new RogueCombatStrategyFactoryInternal());
}
void RogueAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
{
AiObjectContext::BuildSharedActionContexts(actionContexts);
actionContexts.Add(new RogueAiObjectContextInternal()); actionContexts.Add(new RogueAiObjectContextInternal());
}
void RogueAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
{
AiObjectContext::BuildSharedTriggerContexts(triggerContexts);
triggerContexts.Add(new RogueTriggerFactoryInternal()); triggerContexts.Add(new RogueTriggerFactoryInternal());
} }
void RogueAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
{
AiObjectContext::BuildSharedValueContexts(valueContexts);
}

View File

@@ -7,6 +7,7 @@
#define _PLAYERBOT_ROGUEAIOBJECTCONTEXT_H #define _PLAYERBOT_ROGUEAIOBJECTCONTEXT_H
#include "AiObjectContext.h" #include "AiObjectContext.h"
#include "Strategy.h"
class PlayerbotAI; class PlayerbotAI;
@@ -14,6 +15,17 @@ class RogueAiObjectContext : public AiObjectContext
{ {
public: public:
RogueAiObjectContext(PlayerbotAI* botAI); RogueAiObjectContext(PlayerbotAI* botAI);
static void BuildSharedContexts();
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
static SharedNamedObjectContextList<Action> sharedActionContexts;
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
}; };
#endif #endif

View File

@@ -84,7 +84,7 @@ bool NewRpgBaseAction::MoveFarTo(WorldPosition dest)
float rx, ry, rz; float rx, ry, rz;
bool found = false; bool found = false;
int attempt = 3; int attempt = 3;
while (--attempt) while (attempt--)
{ {
float angle = bot->GetAngle(&dest); float angle = bot->GetAngle(&dest);
float delta = urand(1, 100) <= 75 ? (rand_norm() - 0.5) * M_PI * 0.5 : (rand_norm() - 0.5) * M_PI * 2; float delta = urand(1, 100) <= 75 ? (rand_norm() - 0.5) * M_PI * 0.5 : (rand_norm() - 0.5) * M_PI * 2;
@@ -163,8 +163,8 @@ bool NewRpgBaseAction::MoveRandomNear(float moveStep, MovementPriority priority)
const float x = bot->GetPositionX(); const float x = bot->GetPositionX();
const float y = bot->GetPositionY(); const float y = bot->GetPositionY();
const float z = bot->GetPositionZ(); const float z = bot->GetPositionZ();
int attempts = 5; int attempts = 1;
while (--attempts) while (attempts--)
{ {
float angle = (float)rand_norm() * 2 * static_cast<float>(M_PI); float angle = (float)rand_norm() * 2 * static_cast<float>(M_PI);
float dx = x + distance * cos(angle); float dx = x + distance * cos(angle);

View File

@@ -328,11 +328,45 @@ private:
static Action* feral_spirit(PlayerbotAI* ai) { return new CastFeralSpiritAction(ai); } static Action* feral_spirit(PlayerbotAI* ai) { return new CastFeralSpiritAction(ai); }
}; };
ShamanAiObjectContext::ShamanAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) SharedNamedObjectContextList<Strategy> ShamanAiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> ShamanAiObjectContext::sharedActionContexts;
SharedNamedObjectContextList<Trigger> ShamanAiObjectContext::sharedTriggerContexts;
SharedNamedObjectContextList<UntypedValue> ShamanAiObjectContext::sharedValueContexts;
ShamanAiObjectContext::ShamanAiObjectContext(PlayerbotAI* botAI)
: AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts)
{ {
}
void ShamanAiObjectContext::BuildSharedContexts()
{
BuildSharedStrategyContexts(sharedStrategyContexts);
BuildSharedActionContexts(sharedActionContexts);
BuildSharedTriggerContexts(sharedTriggerContexts);
BuildSharedValueContexts(sharedValueContexts);
}
void ShamanAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
{
AiObjectContext::BuildSharedStrategyContexts(strategyContexts);
strategyContexts.Add(new ShamanStrategyFactoryInternal()); strategyContexts.Add(new ShamanStrategyFactoryInternal());
strategyContexts.Add(new ShamanCombatStrategyFactoryInternal()); strategyContexts.Add(new ShamanCombatStrategyFactoryInternal());
strategyContexts.Add(new ShamanBuffStrategyFactoryInternal()); strategyContexts.Add(new ShamanBuffStrategyFactoryInternal());
}
void ShamanAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
{
AiObjectContext::BuildSharedActionContexts(actionContexts);
actionContexts.Add(new ShamanAiObjectContextInternal()); actionContexts.Add(new ShamanAiObjectContextInternal());
}
void ShamanAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
{
AiObjectContext::BuildSharedTriggerContexts(triggerContexts);
triggerContexts.Add(new ShamanATriggerFactoryInternal()); triggerContexts.Add(new ShamanATriggerFactoryInternal());
} }
void ShamanAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
{
AiObjectContext::BuildSharedValueContexts(valueContexts);
}

View File

@@ -14,6 +14,17 @@ class ShamanAiObjectContext : public AiObjectContext
{ {
public: public:
ShamanAiObjectContext(PlayerbotAI* botAI); ShamanAiObjectContext(PlayerbotAI* botAI);
static void BuildSharedContexts();
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
static SharedNamedObjectContextList<Action> sharedActionContexts;
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
}; };
#endif #endif

View File

@@ -192,16 +192,16 @@ bool GrindTargetValue::needForQuest(Unit* target)
return true; return true;
} }
} }
}
}
if (CreatureTemplate const* data = sObjectMgr->GetCreatureTemplate(target->GetEntry())) if (CreatureTemplate const* data = sObjectMgr->GetCreatureTemplate(target->GetEntry()))
{
if (uint32 lootId = data->lootid)
{
if (LootTemplates_Creature.HaveQuestLootForPlayer(lootId, bot))
{ {
if (uint32 lootId = data->lootid) return true;
{
if (LootTemplates_Creature.HaveQuestLootForPlayer(lootId, bot))
{
return true;
}
}
} }
} }
} }

View File

@@ -15,7 +15,7 @@ class NearestCorpsesValue : public NearestUnitsValue
{ {
public: public:
NearestCorpsesValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) NearestCorpsesValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance)
: NearestUnitsValue(botAI, "nearest corpses", range) : NearestUnitsValue(botAI, "nearest corpses", range, true)
{ {
} }

View File

@@ -50,9 +50,12 @@ public:
template <class T> template <class T>
Value<T>* getGlobalValue(std::string const name) Value<T>* getGlobalValue(std::string const name)
{ {
NamedObjectContextList<UntypedValue> valueContexts; // should never reach here
valueContexts.Add(this); SharedNamedObjectContextList<UntypedValue> sValueContexts;
sValueContexts.Add(this);
NamedObjectContextList<UntypedValue> valueContexts(sValueContexts);
PlayerbotAI* botAI = new PlayerbotAI(); PlayerbotAI* botAI = new PlayerbotAI();
UntypedValue* value = valueContexts.GetContextObject(name, botAI); UntypedValue* value = valueContexts.GetContextObject(name, botAI);
delete botAI; delete botAI;
return dynamic_cast<Value<T>*>(value); return dynamic_cast<Value<T>*>(value);

View File

@@ -98,6 +98,7 @@ SummonImpStrategy::SummonImpStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
void SummonImpStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void SummonImpStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon imp", 29.0f), NULL))); triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon imp", 29.0f), NULL)));
triggers.push_back(new TriggerNode("wrong pet", NextAction::array(0, new NextAction("summon imp", 29.0f), NULL)));
} }
// Non-combat strategy for summoning a Voidwalker // Non-combat strategy for summoning a Voidwalker
@@ -109,6 +110,7 @@ SummonVoidwalkerStrategy::SummonVoidwalkerStrategy(PlayerbotAI* ai) : NonCombatS
void SummonVoidwalkerStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void SummonVoidwalkerStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon voidwalker", 29.0f), NULL))); triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon voidwalker", 29.0f), NULL)));
triggers.push_back(new TriggerNode("wrong pet", NextAction::array(0, new NextAction("summon voidwalker", 29.0f), NULL)));
} }
// Non-combat strategy for summoning a Succubus // Non-combat strategy for summoning a Succubus
@@ -120,6 +122,7 @@ SummonSuccubusStrategy::SummonSuccubusStrategy(PlayerbotAI* ai) : NonCombatStrat
void SummonSuccubusStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void SummonSuccubusStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon succubus", 29.0f), NULL))); triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon succubus", 29.0f), NULL)));
triggers.push_back(new TriggerNode("wrong pet", NextAction::array(0, new NextAction("summon succubus", 29.0f), NULL)));
} }
// Non-combat strategy for summoning a Felhunter // Non-combat strategy for summoning a Felhunter
@@ -131,6 +134,7 @@ SummonFelhunterStrategy::SummonFelhunterStrategy(PlayerbotAI* ai) : NonCombatStr
void SummonFelhunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void SummonFelhunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon felhunter", 29.0f), NULL))); triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon felhunter", 29.0f), NULL)));
triggers.push_back(new TriggerNode("wrong pet", NextAction::array(0, new NextAction("summon felhunter", 29.0f), NULL)));
} }
// Non-combat strategy for summoning a Felguard // Non-combat strategy for summoning a Felguard
@@ -142,6 +146,7 @@ SummonFelguardStrategy::SummonFelguardStrategy(PlayerbotAI* ai) : NonCombatStrat
void SummonFelguardStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void SummonFelguardStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon felguard", 29.0f), NULL))); triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon felguard", 29.0f), NULL)));
triggers.push_back(new TriggerNode("wrong pet", NextAction::array(0, new NextAction("summon felguard", 29.0f), NULL)));
} }
// Non-combat strategy for selecting themselves to receive soulstone // Non-combat strategy for selecting themselves to receive soulstone

View File

@@ -145,9 +145,48 @@ bool CreateSoulShardAction::isUseful()
uint32 currentShards = bot->GetItemCount(ITEM_SOUL_SHARD, false); // false = only bags uint32 currentShards = bot->GetItemCount(ITEM_SOUL_SHARD, false); // false = only bags
const uint32 SHARD_CAP = 6; // adjust as needed const uint32 SHARD_CAP = 6; // adjust as needed
return currentShards < SHARD_CAP; // Only allow if under cap AND there is space for a new shard
ItemPosCountVec dest;
uint32 count = 1;
bool hasSpace = (bot->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_SOUL_SHARD, count) == EQUIP_ERR_OK);
return (currentShards < SHARD_CAP) && hasSpace;
} }
bool CastCreateSoulstoneAction::isUseful()
{
Player* bot = botAI->GetBot();
if (!bot)
return false;
// List of all Soulstone item IDs
static const std::vector<uint32> soulstoneIds = {
5232, // Minor Soulstone
16892, // Lesser Soulstone
16893, // Soulstone
16895, // Greater Soulstone
16896, // Major Soulstone
22116, // Master Soulstone
36895 // Demonic Soulstone
};
// Check if the bot already has any soulstone
for (uint32 id : soulstoneIds)
{
if (bot->GetItemCount(id, false) > 0)
return false; // Already has a soulstone
}
// Only need to check one soulstone type for bag space (usually the highest-tier)
ItemPosCountVec dest;
uint32 count = 1;
// Use the last in the list (highest tier)
uint32 soulstoneToCreate = soulstoneIds.back();
bool hasSpace = (bot->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, soulstoneToCreate, count) == EQUIP_ERR_OK);
return hasSpace;
}
bool DestroySoulShardAction::Execute(Event event) bool DestroySoulShardAction::Execute(Event event)
{ {

View File

@@ -84,6 +84,7 @@ class CastCreateSoulstoneAction : public CastBuffSpellAction
{ {
public: public:
CastCreateSoulstoneAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "create soulstone") {} CastCreateSoulstoneAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "create soulstone") {}
bool isUseful() override;
}; };
class UseSoulstoneSelfAction : public UseSpellItemAction class UseSoulstoneSelfAction : public UseSpellItemAction

View File

@@ -4,16 +4,17 @@
*/ */
#include "WarlockAiObjectContext.h" #include "WarlockAiObjectContext.h"
#include "AfflictionWarlockStrategy.h" #include "AfflictionWarlockStrategy.h"
#include "DemonologyWarlockStrategy.h" #include "DemonologyWarlockStrategy.h"
#include "DestructionWarlockStrategy.h" #include "DestructionWarlockStrategy.h"
#include "TankWarlockStrategy.h"
#include "GenericTriggers.h" #include "GenericTriggers.h"
#include "GenericWarlockNonCombatStrategy.h" #include "GenericWarlockNonCombatStrategy.h"
#include "NamedObjectContext.h" #include "NamedObjectContext.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "PullStrategy.h" #include "PullStrategy.h"
#include "Strategy.h" #include "Strategy.h"
#include "TankWarlockStrategy.h"
#include "UseItemAction.h" #include "UseItemAction.h"
#include "WarlockActions.h" #include "WarlockActions.h"
#include "WarlockTriggers.h" #include "WarlockTriggers.h"
@@ -22,14 +23,14 @@ class WarlockStrategyFactoryInternal : public NamedObjectContext<Strategy>
{ {
public: public:
WarlockStrategyFactoryInternal() WarlockStrategyFactoryInternal()
{ {
creators["nc"] = &WarlockStrategyFactoryInternal::nc; creators["nc"] = &WarlockStrategyFactoryInternal::nc;
creators["pull"] = &WarlockStrategyFactoryInternal::pull; creators["pull"] = &WarlockStrategyFactoryInternal::pull;
creators["boost"] = &WarlockStrategyFactoryInternal::boost; creators["boost"] = &WarlockStrategyFactoryInternal::boost;
creators["cc"] = &WarlockStrategyFactoryInternal::cc; creators["cc"] = &WarlockStrategyFactoryInternal::cc;
creators["pet"] = &WarlockStrategyFactoryInternal::pet; creators["pet"] = &WarlockStrategyFactoryInternal::pet;
creators["spellstone"] = &WarlockStrategyFactoryInternal::spellstone; creators["spellstone"] = &WarlockStrategyFactoryInternal::spellstone;
creators["firestone"] = &WarlockStrategyFactoryInternal::firestone; creators["firestone"] = &WarlockStrategyFactoryInternal::firestone;
creators["meta melee"] = &WarlockStrategyFactoryInternal::meta_melee_aoe; creators["meta melee"] = &WarlockStrategyFactoryInternal::meta_melee_aoe;
creators["tank"] = &WarlockStrategyFactoryInternal::tank; creators["tank"] = &WarlockStrategyFactoryInternal::tank;
creators["aoe"] = &WarlockStrategyFactoryInternal::aoe; creators["aoe"] = &WarlockStrategyFactoryInternal::aoe;
@@ -137,7 +138,7 @@ public:
creators["no healthstone"] = &WarlockTriggerFactoryInternal::HasHealthstone; creators["no healthstone"] = &WarlockTriggerFactoryInternal::HasHealthstone;
creators["no firestone"] = &WarlockTriggerFactoryInternal::HasFirestone; creators["no firestone"] = &WarlockTriggerFactoryInternal::HasFirestone;
creators["no spellstone"] = &WarlockTriggerFactoryInternal::HasSpellstone; creators["no spellstone"] = &WarlockTriggerFactoryInternal::HasSpellstone;
creators["no soulstone"] = &WarlockTriggerFactoryInternal::HasSoulstone; creators["no soulstone"] = &WarlockTriggerFactoryInternal::OutOfSoulstone;
creators["firestone"] = &WarlockTriggerFactoryInternal::firestone; creators["firestone"] = &WarlockTriggerFactoryInternal::firestone;
creators["spellstone"] = &WarlockTriggerFactoryInternal::spellstone; creators["spellstone"] = &WarlockTriggerFactoryInternal::spellstone;
creators["soulstone"] = &WarlockTriggerFactoryInternal::soulstone; creators["soulstone"] = &WarlockTriggerFactoryInternal::soulstone;
@@ -170,6 +171,7 @@ public:
creators["curse of exhaustion"] = &WarlockTriggerFactoryInternal::curse_of_exhaustion; creators["curse of exhaustion"] = &WarlockTriggerFactoryInternal::curse_of_exhaustion;
creators["curse of tongues"] = &WarlockTriggerFactoryInternal::curse_of_tongues; creators["curse of tongues"] = &WarlockTriggerFactoryInternal::curse_of_tongues;
creators["curse of weakness"] = &WarlockTriggerFactoryInternal::curse_of_weakness; creators["curse of weakness"] = &WarlockTriggerFactoryInternal::curse_of_weakness;
creators["wrong pet"] = &WarlockTriggerFactoryInternal::wrong_pet;
} }
private: private:
@@ -181,7 +183,7 @@ private:
static Trigger* HasHealthstone(PlayerbotAI* botAI) { return new HasHealthstoneTrigger(botAI); } static Trigger* HasHealthstone(PlayerbotAI* botAI) { return new HasHealthstoneTrigger(botAI); }
static Trigger* HasFirestone(PlayerbotAI* botAI) { return new HasFirestoneTrigger(botAI); } static Trigger* HasFirestone(PlayerbotAI* botAI) { return new HasFirestoneTrigger(botAI); }
static Trigger* HasSpellstone(PlayerbotAI* botAI) { return new HasSpellstoneTrigger(botAI); } static Trigger* HasSpellstone(PlayerbotAI* botAI) { return new HasSpellstoneTrigger(botAI); }
static Trigger* HasSoulstone(PlayerbotAI* botAI) { return new HasSoulstoneTrigger(botAI); } static Trigger* OutOfSoulstone(PlayerbotAI* botAI) { return new OutOfSoulstoneTrigger(botAI); }
static Trigger* firestone(PlayerbotAI* botAI) { return new FirestoneTrigger(botAI); } static Trigger* firestone(PlayerbotAI* botAI) { return new FirestoneTrigger(botAI); }
static Trigger* spellstone(PlayerbotAI* botAI) { return new SpellstoneTrigger(botAI); } static Trigger* spellstone(PlayerbotAI* botAI) { return new SpellstoneTrigger(botAI); }
static Trigger* soulstone(PlayerbotAI* botAI) { return new SoulstoneTrigger(botAI); } static Trigger* soulstone(PlayerbotAI* botAI) { return new SoulstoneTrigger(botAI); }
@@ -214,6 +216,7 @@ private:
static Trigger* curse_of_exhaustion(PlayerbotAI* ai) { return new CurseOfExhaustionTrigger(ai); } static Trigger* curse_of_exhaustion(PlayerbotAI* ai) { return new CurseOfExhaustionTrigger(ai); }
static Trigger* curse_of_tongues(PlayerbotAI* ai) { return new CurseOfTonguesTrigger(ai); } static Trigger* curse_of_tongues(PlayerbotAI* ai) { return new CurseOfTonguesTrigger(ai); }
static Trigger* curse_of_weakness(PlayerbotAI* ai) { return new CurseOfWeaknessTrigger(ai); } static Trigger* curse_of_weakness(PlayerbotAI* ai) { return new CurseOfWeaknessTrigger(ai); }
static Trigger* wrong_pet(PlayerbotAI* ai) { return new WrongPetTrigger(ai); }
}; };
class WarlockAiObjectContextInternal : public NamedObjectContext<Action> class WarlockAiObjectContextInternal : public NamedObjectContext<Action>
@@ -287,7 +290,7 @@ public:
creators["curse of exhaustion"] = &WarlockAiObjectContextInternal::curse_of_exhaustion; creators["curse of exhaustion"] = &WarlockAiObjectContextInternal::curse_of_exhaustion;
creators["curse of tongues"] = &WarlockAiObjectContextInternal::curse_of_tongues; creators["curse of tongues"] = &WarlockAiObjectContextInternal::curse_of_tongues;
creators["curse of weakness"] = &WarlockAiObjectContextInternal::curse_of_weakness; creators["curse of weakness"] = &WarlockAiObjectContextInternal::curse_of_weakness;
} }
private: private:
static Action* conflagrate(PlayerbotAI* botAI) { return new CastConflagrateAction(botAI); } static Action* conflagrate(PlayerbotAI* botAI) { return new CastConflagrateAction(botAI); }
@@ -328,13 +331,19 @@ private:
static Action* devour_magic_purge(PlayerbotAI* botAI) { return new CastDevourMagicPurgeAction(botAI); } static Action* devour_magic_purge(PlayerbotAI* botAI) { return new CastDevourMagicPurgeAction(botAI); }
static Action* devour_magic_cleanse(PlayerbotAI* botAI) { return new CastDevourMagicCleanseAction(botAI); } static Action* devour_magic_cleanse(PlayerbotAI* botAI) { return new CastDevourMagicCleanseAction(botAI); }
static Action* seed_of_corruption(PlayerbotAI* botAI) { return new CastSeedOfCorruptionAction(botAI); } static Action* seed_of_corruption(PlayerbotAI* botAI) { return new CastSeedOfCorruptionAction(botAI); }
static Action* seed_of_corruption_on_attacker(PlayerbotAI* botAI) { return new CastSeedOfCorruptionOnAttackerAction(botAI); } static Action* seed_of_corruption_on_attacker(PlayerbotAI* botAI)
{
return new CastSeedOfCorruptionOnAttackerAction(botAI);
}
static Action* rain_of_fire(PlayerbotAI* botAI) { return new CastRainOfFireAction(botAI); } static Action* rain_of_fire(PlayerbotAI* botAI) { return new CastRainOfFireAction(botAI); }
static Action* hellfire(PlayerbotAI* botAI) { return new CastHellfireAction(botAI); } static Action* hellfire(PlayerbotAI* botAI) { return new CastHellfireAction(botAI); }
static Action* shadowfury(PlayerbotAI* botAI) { return new CastShadowfuryAction(botAI); } static Action* shadowfury(PlayerbotAI* botAI) { return new CastShadowfuryAction(botAI); }
static Action* life_tap(PlayerbotAI* botAI) { return new CastLifeTapAction(botAI); } static Action* life_tap(PlayerbotAI* botAI) { return new CastLifeTapAction(botAI); }
static Action* unstable_affliction(PlayerbotAI* ai) { return new CastUnstableAfflictionAction(ai); } static Action* unstable_affliction(PlayerbotAI* ai) { return new CastUnstableAfflictionAction(ai); }
static Action* unstable_affliction_on_attacker(PlayerbotAI* ai) { return new CastUnstableAfflictionOnAttackerAction(ai); } static Action* unstable_affliction_on_attacker(PlayerbotAI* ai)
{
return new CastUnstableAfflictionOnAttackerAction(ai);
}
static Action* haunt(PlayerbotAI* ai) { return new CastHauntAction(ai); } static Action* haunt(PlayerbotAI* ai) { return new CastHauntAction(ai); }
static Action* demonic_empowerment(PlayerbotAI* ai) { return new CastDemonicEmpowermentAction(ai); } static Action* demonic_empowerment(PlayerbotAI* ai) { return new CastDemonicEmpowermentAction(ai); }
static Action* metamorphosis(PlayerbotAI* ai) { return new CastMetamorphosisAction(ai); } static Action* metamorphosis(PlayerbotAI* ai) { return new CastMetamorphosisAction(ai); }
@@ -345,11 +354,14 @@ private:
static Action* shadowflame(PlayerbotAI* botAI) { return new CastShadowflameAction(botAI); } static Action* shadowflame(PlayerbotAI* botAI) { return new CastShadowflameAction(botAI); }
static Action* immolation_aura(PlayerbotAI* botAI) { return new CastImmolationAuraAction(botAI); } static Action* immolation_aura(PlayerbotAI* botAI) { return new CastImmolationAuraAction(botAI); }
static Action* chaos_bolt(PlayerbotAI* botAI) { return new CastChaosBoltAction(botAI); } static Action* chaos_bolt(PlayerbotAI* botAI) { return new CastChaosBoltAction(botAI); }
static Action* soulshatter(PlayerbotAI* botAI) { return new CastSoulshatterAction(botAI);} static Action* soulshatter(PlayerbotAI* botAI) { return new CastSoulshatterAction(botAI); }
static Action* searing_pain(PlayerbotAI* botAI) { return new CastSearingPainAction(botAI); } static Action* searing_pain(PlayerbotAI* botAI) { return new CastSearingPainAction(botAI); }
static Action* shadow_ward(PlayerbotAI* botAI) { return new CastShadowWardAction(botAI); } static Action* shadow_ward(PlayerbotAI* botAI) { return new CastShadowWardAction(botAI); }
static Action* curse_of_agony(PlayerbotAI* botAI) { return new CastCurseOfAgonyAction(botAI); } static Action* curse_of_agony(PlayerbotAI* botAI) { return new CastCurseOfAgonyAction(botAI); }
static Action* curse_of_agony_on_attacker(PlayerbotAI* botAI) { return new CastCurseOfAgonyOnAttackerAction(botAI); } static Action* curse_of_agony_on_attacker(PlayerbotAI* botAI)
{
return new CastCurseOfAgonyOnAttackerAction(botAI);
}
static Action* curse_of_the_elements(PlayerbotAI* ai) { return new CastCurseOfTheElementsAction(ai); } static Action* curse_of_the_elements(PlayerbotAI* ai) { return new CastCurseOfTheElementsAction(ai); }
static Action* curse_of_doom(PlayerbotAI* ai) { return new CastCurseOfDoomAction(ai); } static Action* curse_of_doom(PlayerbotAI* ai) { return new CastCurseOfDoomAction(ai); }
static Action* curse_of_exhaustion(PlayerbotAI* ai) { return new CastCurseOfExhaustionAction(ai); } static Action* curse_of_exhaustion(PlayerbotAI* ai) { return new CastCurseOfExhaustionAction(ai); }
@@ -357,13 +369,47 @@ private:
static Action* curse_of_weakness(PlayerbotAI* ai) { return new CastCurseOfWeaknessAction(ai); } static Action* curse_of_weakness(PlayerbotAI* ai) { return new CastCurseOfWeaknessAction(ai); }
}; };
WarlockAiObjectContext::WarlockAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) SharedNamedObjectContextList<Strategy> WarlockAiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> WarlockAiObjectContext::sharedActionContexts;
SharedNamedObjectContextList<Trigger> WarlockAiObjectContext::sharedTriggerContexts;
SharedNamedObjectContextList<UntypedValue> WarlockAiObjectContext::sharedValueContexts;
WarlockAiObjectContext::WarlockAiObjectContext(PlayerbotAI* botAI)
: AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts)
{ {
}
void WarlockAiObjectContext::BuildSharedContexts()
{
BuildSharedStrategyContexts(sharedStrategyContexts);
BuildSharedActionContexts(sharedActionContexts);
BuildSharedTriggerContexts(sharedTriggerContexts);
BuildSharedValueContexts(sharedValueContexts);
}
void WarlockAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
{
AiObjectContext::BuildSharedStrategyContexts(strategyContexts);
strategyContexts.Add(new WarlockStrategyFactoryInternal()); strategyContexts.Add(new WarlockStrategyFactoryInternal());
strategyContexts.Add(new WarlockCombatStrategyFactoryInternal()); strategyContexts.Add(new WarlockCombatStrategyFactoryInternal());
strategyContexts.Add(new WarlockPetStrategyFactoryInternal()); strategyContexts.Add(new WarlockPetStrategyFactoryInternal());
strategyContexts.Add(new WarlockSoulstoneStrategyFactoryInternal()); strategyContexts.Add(new WarlockSoulstoneStrategyFactoryInternal());
strategyContexts.Add(new WarlockCurseStrategyFactoryInternal()); strategyContexts.Add(new WarlockCurseStrategyFactoryInternal());
}
void WarlockAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
{
AiObjectContext::BuildSharedActionContexts(actionContexts);
actionContexts.Add(new WarlockAiObjectContextInternal()); actionContexts.Add(new WarlockAiObjectContextInternal());
}
void WarlockAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
{
AiObjectContext::BuildSharedTriggerContexts(triggerContexts);
triggerContexts.Add(new WarlockTriggerFactoryInternal()); triggerContexts.Add(new WarlockTriggerFactoryInternal());
} }
void WarlockAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
{
AiObjectContext::BuildSharedValueContexts(valueContexts);
}

View File

@@ -14,6 +14,17 @@ class WarlockAiObjectContext : public AiObjectContext
{ {
public: public:
WarlockAiObjectContext(PlayerbotAI* botAI); WarlockAiObjectContext(PlayerbotAI* botAI);
static void BuildSharedContexts();
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
static SharedNamedObjectContextList<Action> sharedActionContexts;
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
}; };
#endif #endif

View File

@@ -7,6 +7,32 @@
#include "GenericTriggers.h" #include "GenericTriggers.h"
#include "Playerbots.h" #include "Playerbots.h"
static const uint32 SOUL_SHARD_ITEM_ID = 6265;
uint32 GetSoulShardCount(Player* bot)
{
return bot->GetItemCount(SOUL_SHARD_ITEM_ID, false); // false = only bags
}
// List of all Soulstone item IDs
static const std::vector<uint32> soulstoneItemIds = {
5232, // Minor Soulstone
16892, // Lesser Soulstone
16893, // Soulstone
16895, // Greater Soulstone
16896, // Major Soulstone
22116, // Master Soulstone
36895 // Demonic Soulstone
};
uint32 GetSoulstoneCount(Player* bot)
{
uint32 count = 0;
for (uint32 id : soulstoneItemIds)
count += bot->GetItemCount(id, false); // false = only bags
return count;
}
bool SpellstoneTrigger::IsActive() { return BuffTrigger::IsActive() && AI_VALUE2(uint32, "item count", getName()) > 0; } bool SpellstoneTrigger::IsActive() { return BuffTrigger::IsActive() && AI_VALUE2(uint32, "item count", getName()) > 0; }
bool FirestoneTrigger::IsActive() { return BuffTrigger::IsActive() && AI_VALUE2(uint32, "item count", getName()) > 0; } bool FirestoneTrigger::IsActive() { return BuffTrigger::IsActive() && AI_VALUE2(uint32, "item count", getName()) > 0; }
@@ -16,6 +42,12 @@ bool WarlockConjuredItemTrigger::IsActive()
return ItemCountTrigger::IsActive() && AI_VALUE2(uint32, "item count", "soul shard") > 0; return ItemCountTrigger::IsActive() && AI_VALUE2(uint32, "item count", "soul shard") > 0;
} }
bool OutOfSoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot()) == 0; }
bool TooManySoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot()) >= 6; }
bool OutOfSoulstoneTrigger::IsActive() { return GetSoulstoneCount(botAI->GetBot()) == 0; }
// Checks if the target marked with the moon icon can be banished // Checks if the target marked with the moon icon can be banished
bool BanishTrigger::IsActive() bool BanishTrigger::IsActive()
{ {
@@ -133,3 +165,66 @@ bool CurseOfWeaknessTrigger::IsActive()
// Use default BuffTrigger logic for the rest (only trigger if debuff is missing or expiring) // Use default BuffTrigger logic for the rest (only trigger if debuff is missing or expiring)
return BuffTrigger::IsActive(); return BuffTrigger::IsActive();
} }
struct WarlockPetDef
{
const char* strategy; // The strategy string as recognized by the AI (e.g., "imp", "voidwalker", etc.)
uint32 spellId; // The spell ID required to summon this pet
uint32 npcEntry; // The NPC entry ID for the summoned pet creature
};
// Static array with all relevant Warlock pets and their data
static const WarlockPetDef pets[] = {{"imp", 688, 416},
{"voidwalker", 697, 1860},
{"succubus", 712, 1863},
{"felhunter", 691, 417},
{"felguard", 30146, 17252}};
bool WrongPetTrigger::IsActive()
{
// Retrieve the bot player and its current pet (if any)
Player* bot = botAI->GetBot();
Pet* pet = bot->GetPet();
// Step 1: Count how many pet strategies are currently enabled for this bot.
// While doing so, also remember which pet strategy is the only enabled one (if that's the case).
int enabledCount = 0;
const WarlockPetDef* enabledPet =
nullptr; // Pointer to the pet definition of the enabled strategy, if only one is enabled
for (const WarlockPetDef& pd : pets)
{
if (botAI->HasStrategy(pd.strategy, BOT_STATE_NON_COMBAT))
{
enabledCount++;
enabledPet = &pd; // Save the pointer to last enabled pet
}
}
// Step 2: If not exactly one pet strategy is enabled, we should not trigger.
// This prevents ambiguous or conflicting situations.
if (enabledCount != 1)
return false;
// Step 3: At this point, we know only one pet strategy is enabled.
// We check if the currently summoned pet matches the enabled strategy.
bool correctPet = false;
if (pet)
{
CreatureTemplate const* ct = pet->GetCreatureTemplate();
// Check if the pet's NPC entry matches the expected one for the enabled strategy
if (ct && ct->Entry == enabledPet->npcEntry)
correctPet = true;
}
// Step 4: If the correct pet is already summoned, the trigger should not activate.
if (correctPet)
return false;
// Step 5: Finally, check if the bot actually knows the spell to summon the desired pet.
// If so, the trigger is active (bot should summon the correct pet).
if (bot->HasSpell(enabledPet->spellId))
return true;
// Step 6: If we get here, the bot doesn't know the spell required to support the active pet strategy
return false;
}

View File

@@ -34,14 +34,14 @@ class OutOfSoulShardsTrigger : public Trigger
{ {
public: public:
OutOfSoulShardsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soul shard", 2) {} OutOfSoulShardsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soul shard", 2) {}
bool IsActive() override { return AI_VALUE2(uint32, "item count", "soul shard") == 0; } bool IsActive() override;
}; };
class TooManySoulShardsTrigger : public Trigger class TooManySoulShardsTrigger : public Trigger
{ {
public: public:
TooManySoulShardsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "too many soul shards") {} TooManySoulShardsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "too many soul shards") {}
bool IsActive() override { return AI_VALUE2(uint32, "item count", "soul shard") >= 6; } bool IsActive() override;
}; };
class FirestoneTrigger : public BuffTrigger class FirestoneTrigger : public BuffTrigger
@@ -58,11 +58,11 @@ public:
bool IsActive() override; bool IsActive() override;
}; };
class HasSoulstoneTrigger : public Trigger class OutOfSoulstoneTrigger : public Trigger
{ {
public: public:
HasSoulstoneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soulstone") {} OutOfSoulstoneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soulstone") {}
bool IsActive() override { return AI_VALUE2(uint32, "item count", "soulstone") == 0; } bool IsActive() override;
}; };
class SoulstoneTrigger : public Trigger class SoulstoneTrigger : public Trigger
@@ -112,6 +112,14 @@ public:
HasHealthstoneTrigger(PlayerbotAI* botAI) : WarlockConjuredItemTrigger(botAI, "healthstone") {} HasHealthstoneTrigger(PlayerbotAI* botAI) : WarlockConjuredItemTrigger(botAI, "healthstone") {}
}; };
class WrongPetTrigger : public Trigger
{
public:
WrongPetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "wrong pet") {}
bool IsActive() override;
};
// CC and Pet Triggers // CC and Pet Triggers
class BanishTrigger : public HasCcTargetTrigger class BanishTrigger : public HasCcTargetTrigger

View File

@@ -318,10 +318,44 @@ private:
static Action* enraged_regeneration(PlayerbotAI* botAI) { return new CastEnragedRegenerationAction(botAI); } static Action* enraged_regeneration(PlayerbotAI* botAI) { return new CastEnragedRegenerationAction(botAI); }
}; };
WarriorAiObjectContext::WarriorAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) SharedNamedObjectContextList<Strategy> WarriorAiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> WarriorAiObjectContext::sharedActionContexts;
SharedNamedObjectContextList<Trigger> WarriorAiObjectContext::sharedTriggerContexts;
SharedNamedObjectContextList<UntypedValue> WarriorAiObjectContext::sharedValueContexts;
WarriorAiObjectContext::WarriorAiObjectContext(PlayerbotAI* botAI)
: AiObjectContext(botAI, sharedStrategyContexts, sharedActionContexts, sharedTriggerContexts, sharedValueContexts)
{ {
}
void WarriorAiObjectContext::BuildSharedContexts()
{
BuildSharedStrategyContexts(sharedStrategyContexts);
BuildSharedActionContexts(sharedActionContexts);
BuildSharedTriggerContexts(sharedTriggerContexts);
BuildSharedValueContexts(sharedValueContexts);
}
void WarriorAiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts)
{
AiObjectContext::BuildSharedStrategyContexts(strategyContexts);
strategyContexts.Add(new WarriorStrategyFactoryInternal()); strategyContexts.Add(new WarriorStrategyFactoryInternal());
strategyContexts.Add(new WarriorCombatStrategyFactoryInternal()); strategyContexts.Add(new WarriorCombatStrategyFactoryInternal());
}
void WarriorAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
{
AiObjectContext::BuildSharedActionContexts(actionContexts);
actionContexts.Add(new WarriorAiObjectContextInternal()); actionContexts.Add(new WarriorAiObjectContextInternal());
}
void WarriorAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts)
{
AiObjectContext::BuildSharedTriggerContexts(triggerContexts);
triggerContexts.Add(new WarriorTriggerFactoryInternal()); triggerContexts.Add(new WarriorTriggerFactoryInternal());
} }
void WarriorAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts)
{
AiObjectContext::BuildSharedValueContexts(valueContexts);
}

View File

@@ -14,6 +14,17 @@ class WarriorAiObjectContext : public AiObjectContext
{ {
public: public:
WarriorAiObjectContext(PlayerbotAI* botAI); WarriorAiObjectContext(PlayerbotAI* botAI);
static void BuildSharedContexts();
static void BuildSharedStrategyContexts(SharedNamedObjectContextList<Strategy>& strategyContexts);
static void BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts);
static void BuildSharedTriggerContexts(SharedNamedObjectContextList<Trigger>& triggerContexts);
static void BuildSharedValueContexts(SharedNamedObjectContextList<UntypedValue>& valueContexts);
static SharedNamedObjectContextList<Strategy> sharedStrategyContexts;
static SharedNamedObjectContextList<Action> sharedActionContexts;
static SharedNamedObjectContextList<Trigger> sharedTriggerContexts;
static SharedNamedObjectContextList<UntypedValue> sharedValueContexts;
}; };
#endif #endif