From 7d7edbd961a65dc0a568cc956dce7b58956b2440 Mon Sep 17 00:00:00 2001 From: ThePenguinMan96 Date: Wed, 23 Jul 2025 11:26:55 -0700 Subject: [PATCH 1/5] Warlock Soul Shard/Soulstone ID conversion Hello everyone, I'm still working on fixing issue #1439 , and I have a theory - it could be because the clients that are having the issue are not english, and the code currently checks for strings "soul shard" and "soulstone". This PR converts the check over to the item IDs, so it should work regardless of what client is being used. I tested it myself with the english client and there is functionally no difference than before - but I hope it solves the issue #1439 for the non-english clients and community. --- src/strategy/warlock/WarlockTriggers.cpp | 32 ++++++++++++++++++++++++ src/strategy/warlock/WarlockTriggers.h | 6 ++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/strategy/warlock/WarlockTriggers.cpp b/src/strategy/warlock/WarlockTriggers.cpp index 7f414f2eb..e0493e207 100644 --- a/src/strategy/warlock/WarlockTriggers.cpp +++ b/src/strategy/warlock/WarlockTriggers.cpp @@ -7,6 +7,32 @@ #include "GenericTriggers.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 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 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; } +bool OutOfSoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot()) == 0; } + +bool TooManySoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot()) >= 6; } + +bool HasSoulstoneTrigger::IsActive() { return GetSoulstoneCount(botAI->GetBot()) == 0; } + // Checks if the target marked with the moon icon can be banished bool BanishTrigger::IsActive() { diff --git a/src/strategy/warlock/WarlockTriggers.h b/src/strategy/warlock/WarlockTriggers.h index ca85a9997..3a4489737 100644 --- a/src/strategy/warlock/WarlockTriggers.h +++ b/src/strategy/warlock/WarlockTriggers.h @@ -34,14 +34,14 @@ class OutOfSoulShardsTrigger : public Trigger { public: 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 { public: 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 @@ -62,7 +62,7 @@ class HasSoulstoneTrigger : public Trigger { public: HasSoulstoneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soulstone") {} - bool IsActive() override { return AI_VALUE2(uint32, "item count", "soulstone") == 0; } + bool IsActive() override; }; class SoulstoneTrigger : public Trigger From 5ac6e8751cbfd0241f8a296b6d742b28d3006a39 Mon Sep 17 00:00:00 2001 From: ThePenguinMan96 Date: Wed, 23 Jul 2025 12:45:02 -0700 Subject: [PATCH 2/5] Bagspace checks This commit is adding checks to the createsoulshard and createsoulstone actions, to check and see if there is enough bagspace to create an item. --- src/strategy/warlock/WarlockActions.cpp | 44 ++++++++++++++++++++++++- src/strategy/warlock/WarlockActions.h | 1 + 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/strategy/warlock/WarlockActions.cpp b/src/strategy/warlock/WarlockActions.cpp index c57a21c22..69f1f3358 100644 --- a/src/strategy/warlock/WarlockActions.cpp +++ b/src/strategy/warlock/WarlockActions.cpp @@ -145,9 +145,51 @@ bool CreateSoulShardAction::isUseful() uint32 currentShards = bot->GetItemCount(ITEM_SOUL_SHARD, false); // false = only bags 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 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 + uint32 currentSoulstones = 0; + for (uint32 id : soulstoneIds) + currentSoulstones += bot->GetItemCount(id, false); // false = only bags + + // Allow only if the bot has no soulstone AND there is space for one + ItemPosCountVec dest; + uint32 count = 1; + bool hasSpace = false; + for (uint32 id : soulstoneIds) + { + if (bot->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count) == EQUIP_ERR_OK) + { + hasSpace = true; + break; + } + } + + return (currentSoulstones == 0) && hasSpace; +} bool DestroySoulShardAction::Execute(Event event) { diff --git a/src/strategy/warlock/WarlockActions.h b/src/strategy/warlock/WarlockActions.h index 695307752..b3b7a3e26 100644 --- a/src/strategy/warlock/WarlockActions.h +++ b/src/strategy/warlock/WarlockActions.h @@ -84,6 +84,7 @@ class CastCreateSoulstoneAction : public CastBuffSpellAction { public: CastCreateSoulstoneAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "create soulstone") {} + bool isUseful() override; }; class UseSoulstoneSelfAction : public UseSpellItemAction From feda619066eedfa610e0ab562c380c0e1c6643f6 Mon Sep 17 00:00:00 2001 From: Yunfan Li <56597220+liyunfan1223@users.noreply.github.com> Date: Fri, 25 Jul 2025 18:11:03 +0800 Subject: [PATCH 3/5] Engine optimization for better performance and mem usage (#1462) * Optimize loot * World channel talk * General improvement * Engine rebuild for performance and memory usage * Fix crash with AutoDoQuest = 0 --- src/LootObjectStack.cpp | 79 ++++--- src/LootObjectStack.h | 2 +- src/PlayerbotAI.cpp | 3 + src/PlayerbotAIConfig.cpp | 7 +- src/strategy/AiObjectContext.cpp | 121 +++++++---- src/strategy/AiObjectContext.h | 29 ++- src/strategy/Engine.cpp | 21 +- src/strategy/Engine.h | 1 + src/strategy/NamedObjectContext.h | 194 +++++++++++------- src/strategy/Strategy.h | 2 +- src/strategy/Trigger.cpp | 3 +- src/strategy/Trigger.h | 2 +- .../deathknight/DKAiObjectContext.cpp | 51 ++++- src/strategy/deathknight/DKAiObjectContext.h | 11 + src/strategy/druid/DruidAiObjectContext.cpp | 38 +++- src/strategy/druid/DruidAiObjectContext.h | 11 + src/strategy/hunter/HunterAiObjectContext.cpp | 46 ++++- src/strategy/hunter/HunterAiObjectContext.h | 11 + src/strategy/mage/MageAiObjectContext.cpp | 38 +++- src/strategy/mage/MageAiObjectContext.h | 11 + .../paladin/PaladinAiObjectContext.cpp | 68 +++++- src/strategy/paladin/PaladinAiObjectContext.h | 11 + src/strategy/priest/PriestAiObjectContext.cpp | 44 +++- src/strategy/priest/PriestAiObjectContext.h | 11 + src/strategy/rogue/RogueAiObjectContext.cpp | 38 +++- src/strategy/rogue/RogueAiObjectContext.h | 12 ++ src/strategy/rpg/NewRpgBaseAction.cpp | 6 +- src/strategy/shaman/ShamanAiObjectContext.cpp | 36 +++- src/strategy/shaman/ShamanAiObjectContext.h | 11 + src/strategy/values/GrindTargetValue.cpp | 16 +- src/strategy/values/NearestCorpsesValue.h | 2 +- src/strategy/values/SharedValueContext.h | 7 +- .../warlock/WarlockAiObjectContext.cpp | 67 +++++- src/strategy/warlock/WarlockAiObjectContext.h | 11 + .../warrior/WarriorAiObjectContext.cpp | 36 +++- src/strategy/warrior/WarriorAiObjectContext.h | 11 + 36 files changed, 831 insertions(+), 237 deletions(-) diff --git a/src/LootObjectStack.cpp b/src/LootObjectStack.cpp index e1d2bc462..adce7f397 100644 --- a/src/LootObjectStack.cpp +++ b/src/LootObjectStack.cpp @@ -6,6 +6,8 @@ #include "LootObjectStack.h" #include "LootMgr.h" +#include "Object.h" +#include "ObjectAccessor.h" #include "Playerbots.h" #include "Unit.h" @@ -287,7 +289,7 @@ bool LootObject::IsLootPossible(Player* bot) if (reqItem && !bot->HasItemCount(reqItem, 1)) return false; - if (abs(worldObj->GetPositionZ() - bot->GetPositionZ()) > INTERACTION_DISTANCE -2.0f) + if (abs(worldObj->GetPositionZ() - bot->GetPositionZ()) > INTERACTION_DISTANCE - 2.0f) return false; 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) 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; if (skillId == SKILL_NONE) @@ -317,29 +319,17 @@ bool LootObject::IsLootPossible(Player* bot) uint32 skillValue = uint32(bot->GetSkillValue(skillId)); if (reqSkillValue > skillValue) return false; - - if (skillId == SKILL_MINING && - !bot->HasItemCount(756, 1) && - !bot->HasItemCount(778, 1) && - !bot->HasItemCount(1819, 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)) + + if (skillId == SKILL_MINING && !bot->HasItemCount(756, 1) && !bot->HasItemCount(778, 1) && + !bot->HasItemCount(1819, 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 } - - if (skillId == SKILL_SKINNING && - !bot->HasItemCount(7005, 1) && - !bot->HasItemCount(40772, 1) && - !bot->HasItemCount(40893, 1) && - !bot->HasItemCount(12709, 1) && - !bot->HasItemCount(19901, 1)) + + if (skillId == SKILL_SKINNING && !bot->HasItemCount(7005, 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 } @@ -376,42 +366,45 @@ void LootObjectStack::Clear() { availableLoot.clear(); } bool LootObjectStack::CanLoot(float maxDistance) { - std::vector ordered = OrderByDistance(maxDistance); - return !ordered.empty(); + LootObject nearest = GetNearest(maxDistance); + return !nearest.IsEmpty(); } LootObject LootObjectStack::GetLoot(float maxDistance) { - std::vector ordered = OrderByDistance(maxDistance); - return ordered.empty() ? LootObject() : *ordered.begin(); + LootObject nearest = GetNearest(maxDistance); + return nearest.IsEmpty() ? LootObject() : nearest; } -std::vector LootObjectStack::OrderByDistance(float maxDistance) + +LootObject LootObjectStack::GetNearest(float maxDistance) { availableLoot.shrink(time(nullptr) - 30); - std::map sortedMap; + LootObject nearest; + float nearestDistance = std::numeric_limits::max(); + LootTargetList safeCopy(availableLoot); for (LootTargetList::iterator i = safeCopy.begin(); i != safeCopy.end(); i++) { ObjectGuid guid = i->guid; - LootObject lootObject(bot, guid); - if (!lootObject.IsLootPossible(bot)) // Ensure loot object is valid - continue; - WorldObject* worldObj = lootObject.GetWorldObject(bot); - if (!worldObj) // Prevent null pointer dereference - { + WorldObject* worldObj = ObjectAccessor::GetWorldObject(*bot, guid); + if (!worldObj) continue; - } 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 result; - for (auto& [_, lootObject] : sortedMap) - result.push_back(lootObject); - - return result; -} + return nearest; +} \ No newline at end of file diff --git a/src/LootObjectStack.h b/src/LootObjectStack.h index b17e7fcc9..9ff7dd997 100644 --- a/src/LootObjectStack.h +++ b/src/LootObjectStack.h @@ -78,7 +78,7 @@ public: LootObject GetLoot(float maxDistance = 0); private: - std::vector OrderByDistance(float maxDistance = 0); + LootObject GetNearest(float maxDistance = 0); Player* bot; LootTargetList availableLoot; diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 5b2b707f8..d2e0f2933 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -1049,6 +1049,9 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet) default: return; } + + if (chanName == "World") + return; // do not reply to self but always try to reply to real player if (guid1 != bot->GetGUID()) diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index cd03c7f1c..db1419a4e 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -627,12 +627,7 @@ bool PlayerbotAIConfig::Initialize() sPlayerbotTextMgr->LoadBotTextChance(); PlayerbotFactory::Init(); - if (!sPlayerbotAIConfig->autoDoQuests) - { - LOG_INFO("server.loading", "Loading Quest Detail Data..."); - sTravelMgr->LoadQuestTravelTable(); - } - + AiObjectContext::BuildAllSharedContexts(); if (sPlayerbotAIConfig->randomBotSuggestDungeons) { diff --git a/src/strategy/AiObjectContext.cpp b/src/strategy/AiObjectContext.cpp index c308a7cd6..dd025c2e8 100644 --- a/src/strategy/AiObjectContext.cpp +++ b/src/strategy/AiObjectContext.cpp @@ -8,39 +8,89 @@ #include "ActionContext.h" #include "ChatActionContext.h" #include "ChatTriggerContext.h" +#include "DKAiObjectContext.h" +#include "DruidAiObjectContext.h" +#include "HunterAiObjectContext.h" +#include "MageAiObjectContext.h" +#include "PaladinAiObjectContext.h" #include "Playerbots.h" -#include "RaidUlduarTriggerContext.h" +#include "PriestAiObjectContext.h" #include "RaidUlduarActionContext.h" +#include "RaidUlduarTriggerContext.h" +#include "RogueAiObjectContext.h" +#include "ShamanAiObjectContext.h" #include "SharedValueContext.h" #include "StrategyContext.h" #include "TriggerContext.h" #include "ValueContext.h" +#include "WarlockAiObjectContext.h" +#include "WarriorAiObjectContext.h" #include "WorldPacketActionContext.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/wotlk/WotlkDungeonActionContext.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 AiObjectContext::sharedStrategyContexts; +SharedNamedObjectContextList AiObjectContext::sharedActionContexts; +SharedNamedObjectContextList AiObjectContext::sharedTriggerContexts; +SharedNamedObjectContextList AiObjectContext::sharedValueContexts; + +AiObjectContext::AiObjectContext(PlayerbotAI* botAI, SharedNamedObjectContextList& sharedStrategyContext, + SharedNamedObjectContextList& sharedActionContext, + SharedNamedObjectContextList& sharedTriggerContext, + SharedNamedObjectContextList& 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& strategyContexts) { strategyContexts.Add(new StrategyContext()); strategyContexts.Add(new MovementStrategyContext()); @@ -48,7 +98,10 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) strategyContexts.Add(new QuestStrategyContext()); strategyContexts.Add(new RaidStrategyContext()); strategyContexts.Add(new DungeonStrategyContext()); +} +void AiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) +{ actionContexts.Add(new ActionContext()); actionContexts.Add(new ChatActionContext()); actionContexts.Add(new WorldPacketActionContext()); @@ -77,7 +130,10 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) actionContexts.Add(new WotlkDungeonFoSActionContext()); actionContexts.Add(new WotlkDungeonPoSActionContext()); actionContexts.Add(new WotlkDungeonToCActionContext()); +} +void AiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) +{ triggerContexts.Add(new TriggerContext()); triggerContexts.Add(new ChatTriggerContext()); triggerContexts.Add(new WorldPacketTriggerContext()); @@ -106,26 +162,11 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) triggerContexts.Add(new WotlkDungeonFoSTriggerContext()); triggerContexts.Add(new WotlkDungeonPoSTriggerContext()); triggerContexts.Add(new WotlkDungeonToCTriggerContext()); +} +void AiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) +{ 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 AiObjectContext::Save() @@ -218,5 +259,3 @@ std::string const AiObjectContext::FormatValues() return out.str(); } - -void AiObjectContext::AddShared(NamedObjectContext* sharedValues) { valueContexts.Add(sharedValues); } diff --git a/src/strategy/AiObjectContext.h b/src/strategy/AiObjectContext.h index 07fa78a6d..cfa7d4dbf 100644 --- a/src/strategy/AiObjectContext.h +++ b/src/strategy/AiObjectContext.h @@ -19,10 +19,19 @@ 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 { public: - AiObjectContext(PlayerbotAI* botAI); + AiObjectContext(PlayerbotAI* botAI, + SharedNamedObjectContextList& sharedStrategyContext = sharedStrategyContexts, + SharedNamedObjectContextList& sharedActionContext = sharedActionContexts, + SharedNamedObjectContextList& sharedTriggerContext = sharedTriggerContexts, + SharedNamedObjectContextList& sharedValueContext = sharedValueContexts); virtual ~AiObjectContext() {} virtual Strategy* GetStrategy(std::string const name); @@ -56,20 +65,30 @@ public: std::set GetSupportedActions(); std::string const FormatValues(); - virtual void Update(); - virtual void Reset(); - virtual void AddShared(NamedObjectContext* sharedValues); - std::vector Save(); void Load(std::vector data); std::vector performanceStack; + static void BuildAllSharedContexts(); + + static void BuildSharedContexts(); + static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); + static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); + static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); + static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); + protected: NamedObjectContextList strategyContexts; NamedObjectContextList actionContexts; NamedObjectContextList triggerContexts; NamedObjectContextList valueContexts; + +private: + static SharedNamedObjectContextList sharedStrategyContexts; + static SharedNamedObjectContextList sharedActionContexts; + static SharedNamedObjectContextList sharedTriggerContexts; + static SharedNamedObjectContextList sharedValueContexts; }; #endif diff --git a/src/strategy/Engine.cpp b/src/strategy/Engine.cpp index 39524596b..15055f0ef 100644 --- a/src/strategy/Engine.cpp +++ b/src/strategy/Engine.cpp @@ -11,6 +11,7 @@ #include "Playerbots.h" #include "Queue.h" #include "Strategy.h" +#include "Timer.h" Engine::Engine(PlayerbotAI* botAI, AiObjectContext* factory) : PlayerbotAIAware(botAI), aiObjectContext(factory) { @@ -108,6 +109,8 @@ void Engine::Reset() } multipliers.clear(); + + actionNodeFactories.creators.clear(); } void Engine::Init() @@ -120,9 +123,10 @@ void Engine::Init() strategyTypeMask |= strategy->GetType(); strategy->InitMultipliers(multipliers); strategy->InitTriggers(triggers); - - Event emptyEvent; - MultiplyAndPush(strategy->getDefaultActions(), 0.0f, false, emptyEvent, "default"); + for (auto &iter : strategy->actionNodeFactories.creators) + { + actionNodeFactories.creators[iter.first] = iter.second; + } } if (testMode) @@ -248,11 +252,9 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) ActionNode* Engine::CreateActionNode(std::string const name) { - for (std::map::iterator i = strategies.begin(); i != strategies.end(); i++) - { - if (ActionNode* node = i->second->GetAction(name)) - return node; - } + ActionNode* node = actionNodeFactories.GetContextObject(name, botAI); + if (node) + return node; return new ActionNode(name, /*P*/ nullptr, @@ -432,6 +434,7 @@ bool Engine::HasStrategy(std::string const name) { return strategies.find(name) void Engine::ProcessTriggers(bool minimal) { std::unordered_map fires; + uint32 now = getMSTime(); for (std::vector::iterator i = triggers.begin(); i != triggers.end(); i++) { TriggerNode* node = *i; @@ -451,7 +454,7 @@ void Engine::ProcessTriggers(bool minimal) if (fires.find(trigger) != fires.end()) continue; - if (testMode || trigger->needCheck()) + if (testMode || trigger->needCheck(now)) { if (minimal && node->getFirstRelevance() < 100) continue; diff --git a/src/strategy/Engine.h b/src/strategy/Engine.h index c3a5d7432..8a662997b 100644 --- a/src/strategy/Engine.h +++ b/src/strategy/Engine.h @@ -114,6 +114,7 @@ protected: float lastRelevance; std::string lastAction; uint32 strategyTypeMask; + NamedObjectFactoryList actionNodeFactories; }; #endif diff --git a/src/strategy/NamedObjectContext.h b/src/strategy/NamedObjectContext.h index 78797b0a7..c7ecffc6c 100644 --- a/src/strategy/NamedObjectContext.h +++ b/src/strategy/NamedObjectContext.h @@ -29,7 +29,8 @@ public: std::string const getQualifier() { return qualifier; } - static std::string const MultiQualify(std::vector qualifiers, const std::string& separator, const std::string_view brackets = "{}"); + static std::string const MultiQualify(std::vector qualifiers, const std::string& separator, + const std::string_view brackets = "{}"); static std::vector getMultiQualifiers(std::string const qualifier1); static int32 getMultiQualifier(std::string const qualifier1, uint32 pos); @@ -40,9 +41,9 @@ protected: template class NamedObjectFactory { -protected: - typedef T* (*ActionCreator)(PlayerbotAI* botAI); - std::unordered_map creators; +public: + typedef T* (*ObjectCreator)(PlayerbotAI* botAI); + std::unordered_map creators; public: T* create(std::string name, PlayerbotAI* botAI) @@ -58,7 +59,7 @@ public: if (creators.find(name) == creators.end()) return nullptr; - ActionCreator creator = creators[name]; + ObjectCreator creator = creators[name]; if (!creator) return nullptr; @@ -73,7 +74,7 @@ public: std::set supports() { std::set keys; - for (typename std::unordered_map::iterator it = creators.begin(); + for (typename std::unordered_map::iterator it = creators.begin(); it != creators.end(); it++) keys.insert(it->first); @@ -111,24 +112,6 @@ public: created.clear(); } - void Update() - { - for (typename std::unordered_map::iterator i = created.begin(); i != created.end(); i++) - { - if (i->second) - i->second->Update(); - } - } - - void Reset() - { - for (typename std::unordered_map::iterator i = created.begin(); i != created.end(); i++) - { - if (i->second) - i->second->Reset(); - } - } - bool IsShared() { return shared; } bool IsSupportsSiblings() { return supportsSiblings; } @@ -147,53 +130,93 @@ protected: bool supportsSiblings; }; +template +class SharedNamedObjectContextList +{ +public: + typedef T* (*ObjectCreator)(PlayerbotAI* botAI); + std::unordered_map creators; + std::vector*> contexts; + + ~SharedNamedObjectContextList() + { + for (typename std::vector*>::iterator i = contexts.begin(); i != contexts.end(); i++) + delete *i; + } + + void Add(NamedObjectContext* context) + { + contexts.push_back(context); + for (const auto& iter : context->creators) + { + creators[iter.first] = iter.second; + } + } +}; + template class NamedObjectContextList { public: - virtual ~NamedObjectContextList() + typedef T* (*ObjectCreator)(PlayerbotAI* botAI); + const std::unordered_map& creators; + const std::vector*>& contexts; + std::unordered_map created; + + NamedObjectContextList(const SharedNamedObjectContextList& shared) + : creators(shared.creators), contexts(shared.contexts) { - for (typename std::vector*>::iterator i = contexts.begin(); i != contexts.end(); i++) - { - NamedObjectContext* context = *i; - if (!context->IsShared()) - delete context; - } } - void Add(NamedObjectContext* context) { contexts.push_back(context); } + ~NamedObjectContextList() + { + for (typename std::unordered_map::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(object); + if (q && found != std::string::npos) + q->Qualify(qualifier); + + return object; + } T* GetContextObject(std::string const name, PlayerbotAI* botAI) { - for (typename std::vector*>::iterator i = contexts.begin(); i != contexts.end(); i++) + if (created.find(name) == created.end()) { - if (T* object = (*i)->create(name, botAI)) - return object; - } - - return nullptr; - } - - void Update() - { - for (typename std::vector*>::iterator i = contexts.begin(); i != contexts.end(); i++) - { - if (!(*i)->IsShared()) - (*i)->Update(); - } - } - - void Reset() - { - for (typename std::vector*>::iterator i = contexts.begin(); i != contexts.end(); i++) - { - (*i)->Reset(); + if (T* object = create(name, botAI)) + return created[name] = object; } + return created[name]; } std::set GetSiblings(std::string const name) { - for (typename std::vector*>::iterator i = contexts.begin(); i != contexts.end(); i++) + for (auto i = contexts.begin(); i != contexts.end(); i++) { if (!(*i)->IsSupportsSiblings()) continue; @@ -213,7 +236,7 @@ public: std::set supports() { std::set result; - for (typename std::vector*>::iterator i = contexts.begin(); i != contexts.end(); i++) + for (auto i = contexts.begin(); i != contexts.end(); i++) { std::set supported = (*i)->supports(); @@ -227,46 +250,69 @@ public: std::set GetCreated() { std::set result; - for (typename std::vector*>::iterator i = contexts.begin(); i != contexts.end(); i++) + for (typename std::unordered_map::iterator i = created.begin(); i != created.end(); i++) { - std::set createdKeys = (*i)->GetCreated(); - - for (std::set::iterator j = createdKeys.begin(); j != createdKeys.end(); j++) - result.insert(*j); + result.insert(i->first); } return result; } - -private: - std::vector*> contexts; }; template class NamedObjectFactoryList { public: + typedef T* (*ObjectCreator)(PlayerbotAI* botAI); + std::vector*> factories; + std::unordered_map creators; + virtual ~NamedObjectFactoryList() { - for (typename std::list*>::iterator i = factories.begin(); i != factories.end(); i++) + for (typename std::vector*>::iterator i = factories.begin(); i != factories.end(); i++) delete *i; } - void Add(NamedObjectFactory* context) { factories.push_front(context); } - - T* GetContextObject(std::string const& name, PlayerbotAI* botAI) + T* create(std::string name, PlayerbotAI* botAI) { - for (typename std::list*>::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)) - return object; + qualifier = name.substr(found + 2); + 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(object); + if (q && found != std::string::npos) + q->Qualify(qualifier); + + return object; } -private: - std::list*> factories; + void Add(NamedObjectFactory* context) + { + 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 diff --git a/src/strategy/Strategy.h b/src/strategy/Strategy.h index 47edd397c..1206490c5 100644 --- a/src/strategy/Strategy.h +++ b/src/strategy/Strategy.h @@ -69,7 +69,7 @@ public: void Update() {} void Reset() {} -protected: +public: NamedObjectFactoryList actionNodeFactories; }; diff --git a/src/strategy/Trigger.cpp b/src/strategy/Trigger.cpp index b2c974995..89f616968 100644 --- a/src/strategy/Trigger.cpp +++ b/src/strategy/Trigger.cpp @@ -32,12 +32,11 @@ Value* Trigger::GetTargetValue() { return context->GetValue(GetTar Unit* Trigger::GetTarget() { return GetTargetValue()->Get(); } -bool Trigger::needCheck() +bool Trigger::needCheck(uint32 now) { if (checkInterval < 2) return true; - uint32 now = getMSTime(); if (!lastCheckTime || now - lastCheckTime >= checkInterval) { lastCheckTime = now; diff --git a/src/strategy/Trigger.h b/src/strategy/Trigger.h index ce2dd06d3..af8d0528b 100644 --- a/src/strategy/Trigger.h +++ b/src/strategy/Trigger.h @@ -30,7 +30,7 @@ public: virtual Value* GetTargetValue(); virtual std::string const GetTargetName() { return "self target"; } - bool needCheck(); + bool needCheck(uint32 now); protected: int32 checkInterval; diff --git a/src/strategy/deathknight/DKAiObjectContext.cpp b/src/strategy/deathknight/DKAiObjectContext.cpp index c02ff82b0..a26f96c00 100644 --- a/src/strategy/deathknight/DKAiObjectContext.cpp +++ b/src/strategy/deathknight/DKAiObjectContext.cpp @@ -108,14 +108,20 @@ private: static Trigger* blood_strike(PlayerbotAI* botAI) { return new BloodStrikeTrigger(botAI); } static Trigger* plague_strike(PlayerbotAI* botAI) { return new PlagueStrikeDebuffTrigger(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) { return new PlagueStrikeDebuffOnAttackerTrigger(botAI); } static Trigger* icy_touch(PlayerbotAI* botAI) { return new IcyTouchDebuffTrigger(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* icy_touch_on_attacker(PlayerbotAI* botAI) { return new IcyTouchDebuffOnAttackerTrigger(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* freezing_fog(PlayerbotAI* botAI) { return new FreezingFogTrigger(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* army_of_the_dead(PlayerbotAI* botAI) { return new ArmyOfTheDeadTrigger(botAI); } }; @@ -265,11 +274,45 @@ private: } }; -DKAiObjectContext::DKAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) +SharedNamedObjectContextList DKAiObjectContext::sharedStrategyContexts; +SharedNamedObjectContextList DKAiObjectContext::sharedActionContexts; +SharedNamedObjectContextList DKAiObjectContext::sharedTriggerContexts; +SharedNamedObjectContextList 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& strategyContexts) +{ + AiObjectContext::BuildSharedStrategyContexts(strategyContexts); strategyContexts.Add(new DeathKnightStrategyFactoryInternal()); strategyContexts.Add(new DeathKnightCombatStrategyFactoryInternal()); strategyContexts.Add(new DeathKnightDKBuffStrategyFactoryInternal()); +} + +void DKAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) +{ + AiObjectContext::BuildSharedActionContexts(actionContexts); actionContexts.Add(new DeathKnightAiObjectContextInternal()); +} + +void DKAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) +{ + AiObjectContext::BuildSharedTriggerContexts(triggerContexts); triggerContexts.Add(new DeathKnightTriggerFactoryInternal()); } + +void DKAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) +{ + AiObjectContext::BuildSharedValueContexts(valueContexts); +} diff --git a/src/strategy/deathknight/DKAiObjectContext.h b/src/strategy/deathknight/DKAiObjectContext.h index 7729868b5..b45a778ad 100644 --- a/src/strategy/deathknight/DKAiObjectContext.h +++ b/src/strategy/deathknight/DKAiObjectContext.h @@ -14,6 +14,17 @@ class DKAiObjectContext : public AiObjectContext { public: DKAiObjectContext(PlayerbotAI* botAI); + + static void BuildSharedContexts(); + static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); + static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); + static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); + static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); + + static SharedNamedObjectContextList sharedStrategyContexts; + static SharedNamedObjectContextList sharedActionContexts; + static SharedNamedObjectContextList sharedTriggerContexts; + static SharedNamedObjectContextList sharedValueContexts; }; #endif diff --git a/src/strategy/druid/DruidAiObjectContext.cpp b/src/strategy/druid/DruidAiObjectContext.cpp index cec9eeb01..3866e1cd6 100644 --- a/src/strategy/druid/DruidAiObjectContext.cpp +++ b/src/strategy/druid/DruidAiObjectContext.cpp @@ -8,7 +8,6 @@ #include "BearTankDruidStrategy.h" #include "CasterDruidStrategy.h" #include "CatDpsDruidStrategy.h" -#include "OffhealDruidCatStrategy.h" #include "DruidActions.h" #include "DruidBearActions.h" #include "DruidCatActions.h" @@ -18,6 +17,7 @@ #include "GenericDruidStrategy.h" #include "HealDruidStrategy.h" #include "MeleeDruidStrategy.h" +#include "OffhealDruidCatStrategy.h" #include "Playerbots.h" class DruidStrategyFactoryInternal : public NamedObjectContext @@ -324,10 +324,44 @@ private: static Action* force_of_nature(PlayerbotAI* ai) { return new CastForceOfNatureAction(ai); } }; -DruidAiObjectContext::DruidAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) +SharedNamedObjectContextList DruidAiObjectContext::sharedStrategyContexts; +SharedNamedObjectContextList DruidAiObjectContext::sharedActionContexts; +SharedNamedObjectContextList DruidAiObjectContext::sharedTriggerContexts; +SharedNamedObjectContextList 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& strategyContexts) +{ + AiObjectContext::BuildSharedStrategyContexts(strategyContexts); strategyContexts.Add(new DruidStrategyFactoryInternal()); strategyContexts.Add(new DruidDruidStrategyFactoryInternal()); +} + +void DruidAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) +{ + AiObjectContext::BuildSharedActionContexts(actionContexts); actionContexts.Add(new DruidAiObjectContextInternal()); +} + +void DruidAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) +{ + AiObjectContext::BuildSharedTriggerContexts(triggerContexts); triggerContexts.Add(new DruidTriggerFactoryInternal()); } + +void DruidAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) +{ + AiObjectContext::BuildSharedValueContexts(valueContexts); +} diff --git a/src/strategy/druid/DruidAiObjectContext.h b/src/strategy/druid/DruidAiObjectContext.h index 22d00e183..7c1c7c8eb 100644 --- a/src/strategy/druid/DruidAiObjectContext.h +++ b/src/strategy/druid/DruidAiObjectContext.h @@ -14,6 +14,17 @@ class DruidAiObjectContext : public AiObjectContext { public: DruidAiObjectContext(PlayerbotAI* botAI); + + static void BuildSharedContexts(); + static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); + static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); + static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); + static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); + + static SharedNamedObjectContextList sharedStrategyContexts; + static SharedNamedObjectContextList sharedActionContexts; + static SharedNamedObjectContextList sharedTriggerContexts; + static SharedNamedObjectContextList sharedValueContexts; }; #endif diff --git a/src/strategy/hunter/HunterAiObjectContext.cpp b/src/strategy/hunter/HunterAiObjectContext.cpp index b8e2e41ff..904e7a9f1 100644 --- a/src/strategy/hunter/HunterAiObjectContext.cpp +++ b/src/strategy/hunter/HunterAiObjectContext.cpp @@ -4,16 +4,17 @@ */ #include "HunterAiObjectContext.h" + #include "BeastMasteryHunterStrategy.h" -#include "MarksmanshipHunterStrategy.h" -#include "SurvivalHunterStrategy.h" #include "GenericHunterNonCombatStrategy.h" #include "GenericHunterStrategy.h" #include "HunterActions.h" #include "HunterBuffStrategies.h" #include "HunterTriggers.h" +#include "MarksmanshipHunterStrategy.h" #include "NamedObjectContext.h" #include "Playerbots.h" +#include "SurvivalHunterStrategy.h" class HunterStrategyFactoryInternal : public NamedObjectContext { @@ -105,7 +106,10 @@ public: private: static Trigger* auto_shot(PlayerbotAI* botAI) { return new AutoShotTrigger(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* serpent_sting_on_attacker(PlayerbotAI* botAI) { return new SerpentStingOnAttackerTrigger(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); } }; -HunterAiObjectContext::HunterAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) +SharedNamedObjectContextList HunterAiObjectContext::sharedStrategyContexts; +SharedNamedObjectContextList HunterAiObjectContext::sharedActionContexts; +SharedNamedObjectContextList HunterAiObjectContext::sharedTriggerContexts; +SharedNamedObjectContextList 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& strategyContexts) +{ + AiObjectContext::BuildSharedStrategyContexts(strategyContexts); strategyContexts.Add(new HunterStrategyFactoryInternal()); strategyContexts.Add(new HunterBuffStrategyFactoryInternal()); +} + +void HunterAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) +{ + AiObjectContext::BuildSharedActionContexts(actionContexts); actionContexts.Add(new HunterAiObjectContextInternal()); +} + +void HunterAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) +{ + AiObjectContext::BuildSharedTriggerContexts(triggerContexts); triggerContexts.Add(new HunterTriggerFactoryInternal()); } + +void HunterAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) +{ + AiObjectContext::BuildSharedValueContexts(valueContexts); +} diff --git a/src/strategy/hunter/HunterAiObjectContext.h b/src/strategy/hunter/HunterAiObjectContext.h index e06e8f54a..5acd3ba2b 100644 --- a/src/strategy/hunter/HunterAiObjectContext.h +++ b/src/strategy/hunter/HunterAiObjectContext.h @@ -14,6 +14,17 @@ class HunterAiObjectContext : public AiObjectContext { public: HunterAiObjectContext(PlayerbotAI* botAI); + + static void BuildSharedContexts(); + static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); + static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); + static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); + static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); + + static SharedNamedObjectContextList sharedStrategyContexts; + static SharedNamedObjectContextList sharedActionContexts; + static SharedNamedObjectContextList sharedTriggerContexts; + static SharedNamedObjectContextList sharedValueContexts; }; #endif diff --git a/src/strategy/mage/MageAiObjectContext.cpp b/src/strategy/mage/MageAiObjectContext.cpp index 2d09f1a0f..ba1e4e2dd 100644 --- a/src/strategy/mage/MageAiObjectContext.cpp +++ b/src/strategy/mage/MageAiObjectContext.cpp @@ -24,7 +24,7 @@ public: creators["nc"] = &MageStrategyFactoryInternal::nc; creators["pull"] = &MageStrategyFactoryInternal::pull; 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["arcane aoe"] = &MageStrategyFactoryInternal::arcane_aoe; creators["cure"] = &MageStrategyFactoryInternal::cure; @@ -268,11 +268,45 @@ private: static Action* blink_back(PlayerbotAI* botAI) { return new CastBlinkBackAction(botAI); } }; -MageAiObjectContext::MageAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) +SharedNamedObjectContextList MageAiObjectContext::sharedStrategyContexts; +SharedNamedObjectContextList MageAiObjectContext::sharedActionContexts; +SharedNamedObjectContextList MageAiObjectContext::sharedTriggerContexts; +SharedNamedObjectContextList 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& strategyContexts) +{ + AiObjectContext::BuildSharedStrategyContexts(strategyContexts); strategyContexts.Add(new MageStrategyFactoryInternal()); strategyContexts.Add(new MageCombatStrategyFactoryInternal()); strategyContexts.Add(new MageBuffStrategyFactoryInternal()); +} + +void MageAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) +{ + AiObjectContext::BuildSharedActionContexts(actionContexts); actionContexts.Add(new MageAiObjectContextInternal()); +} + +void MageAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) +{ + AiObjectContext::BuildSharedTriggerContexts(triggerContexts); triggerContexts.Add(new MageTriggerFactoryInternal()); } + +void MageAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) +{ + AiObjectContext::BuildSharedValueContexts(valueContexts); +} \ No newline at end of file diff --git a/src/strategy/mage/MageAiObjectContext.h b/src/strategy/mage/MageAiObjectContext.h index 3388faf9c..435b43d0f 100644 --- a/src/strategy/mage/MageAiObjectContext.h +++ b/src/strategy/mage/MageAiObjectContext.h @@ -14,6 +14,17 @@ class MageAiObjectContext : public AiObjectContext { public: MageAiObjectContext(PlayerbotAI* botAI); + + static void BuildSharedContexts(); + static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); + static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); + static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); + static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); + + static SharedNamedObjectContextList sharedStrategyContexts; + static SharedNamedObjectContextList sharedActionContexts; + static SharedNamedObjectContextList sharedTriggerContexts; + static SharedNamedObjectContextList sharedValueContexts; }; #endif diff --git a/src/strategy/paladin/PaladinAiObjectContext.cpp b/src/strategy/paladin/PaladinAiObjectContext.cpp index 4dbcb0afb..74869bb13 100644 --- a/src/strategy/paladin/PaladinAiObjectContext.cpp +++ b/src/strategy/paladin/PaladinAiObjectContext.cpp @@ -8,8 +8,8 @@ #include "DpsPaladinStrategy.h" #include "GenericPaladinNonCombatStrategy.h" #include "HealPaladinStrategy.h" -#include "OffhealRetPaladinStrategy.h" #include "NamedObjectContext.h" +#include "OffhealRetPaladinStrategy.h" #include "PaladinActions.h" #include "PaladinBuffStrategies.h" #include "PaladinTriggers.h" @@ -207,9 +207,15 @@ private: 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_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_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); } }; @@ -317,10 +323,22 @@ private: static Action* blessing_of_wisdom(PlayerbotAI* botAI) { return new CastBlessingOfWisdomAction(botAI); } static Action* blessing_of_kings(PlayerbotAI* botAI) { return new CastBlessingOfKingsAction(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_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* blessing_of_kings_on_party(PlayerbotAI* botAI) + { + return new CastBlessingOfKingsOnPartyAction(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* crusader_strike(PlayerbotAI* botAI) { return new CastCrusaderStrikeAction(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); } }; -PaladinAiObjectContext::PaladinAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) +SharedNamedObjectContextList PaladinAiObjectContext::sharedStrategyContexts; +SharedNamedObjectContextList PaladinAiObjectContext::sharedActionContexts; +SharedNamedObjectContextList PaladinAiObjectContext::sharedTriggerContexts; +SharedNamedObjectContextList 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& strategyContexts) +{ + AiObjectContext::BuildSharedStrategyContexts(strategyContexts); strategyContexts.Add(new PaladinStrategyFactoryInternal()); strategyContexts.Add(new PaladinCombatStrategyFactoryInternal()); strategyContexts.Add(new PaladinBuffStrategyFactoryInternal()); strategyContexts.Add(new PaladinResistanceStrategyFactoryInternal()); +} + +void PaladinAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) +{ + AiObjectContext::BuildSharedActionContexts(actionContexts); actionContexts.Add(new PaladinAiObjectContextInternal()); +} + +void PaladinAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) +{ + AiObjectContext::BuildSharedTriggerContexts(triggerContexts); triggerContexts.Add(new PaladinTriggerFactoryInternal()); } + +void PaladinAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) +{ + AiObjectContext::BuildSharedValueContexts(valueContexts); +} \ No newline at end of file diff --git a/src/strategy/paladin/PaladinAiObjectContext.h b/src/strategy/paladin/PaladinAiObjectContext.h index c865a8fc0..e8b867ae9 100644 --- a/src/strategy/paladin/PaladinAiObjectContext.h +++ b/src/strategy/paladin/PaladinAiObjectContext.h @@ -14,6 +14,17 @@ class PaladinAiObjectContext : public AiObjectContext { public: PaladinAiObjectContext(PlayerbotAI* botAI); + + static void BuildSharedContexts(); + static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); + static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); + static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); + static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); + + static SharedNamedObjectContextList sharedStrategyContexts; + static SharedNamedObjectContextList sharedActionContexts; + static SharedNamedObjectContextList sharedTriggerContexts; + static SharedNamedObjectContextList sharedValueContexts; }; #endif diff --git a/src/strategy/priest/PriestAiObjectContext.cpp b/src/strategy/priest/PriestAiObjectContext.cpp index 4f0577183..444ed3a1f 100644 --- a/src/strategy/priest/PriestAiObjectContext.cpp +++ b/src/strategy/priest/PriestAiObjectContext.cpp @@ -175,8 +175,7 @@ public: creators["power word: shield on party"] = &PriestAiObjectContextInternal::power_word_shield_on_party; creators["power word: shield on almost full health below"] = &PriestAiObjectContextInternal::power_word_shield_on_almost_full_health_below; - creators["power word: shield on not full"] = - &PriestAiObjectContextInternal::power_word_shield_on_not_full; + creators["power word: shield on not full"] = &PriestAiObjectContextInternal::power_word_shield_on_not_full; creators["renew"] = &PriestAiObjectContextInternal::renew; creators["renew on party"] = &PriestAiObjectContextInternal::renew_on_party; creators["greater heal"] = &PriestAiObjectContextInternal::greater_heal; @@ -289,10 +288,7 @@ private: { return new CastPowerWordShieldOnAlmostFullHealthBelowAction(ai); } - static Action* power_word_shield_on_not_full(PlayerbotAI* ai) - { - return new CastPowerWordShieldOnNotFullAction(ai); - } + static Action* power_word_shield_on_not_full(PlayerbotAI* ai) { return new CastPowerWordShieldOnNotFullAction(ai); } static Action* renew(PlayerbotAI* botAI) { return new CastRenewAction(botAI); } static Action* renew_on_party(PlayerbotAI* botAI) { return new CastRenewOnPartyAction(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); } }; -PriestAiObjectContext::PriestAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) +SharedNamedObjectContextList PriestAiObjectContext::sharedStrategyContexts; +SharedNamedObjectContextList PriestAiObjectContext::sharedActionContexts; +SharedNamedObjectContextList PriestAiObjectContext::sharedTriggerContexts; +SharedNamedObjectContextList 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& strategyContexts) +{ + AiObjectContext::BuildSharedStrategyContexts(strategyContexts); strategyContexts.Add(new PriestStrategyFactoryInternal()); strategyContexts.Add(new PriestCombatStrategyFactoryInternal()); +} + +void PriestAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) +{ + AiObjectContext::BuildSharedActionContexts(actionContexts); actionContexts.Add(new PriestAiObjectContextInternal()); +} + +void PriestAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) +{ + AiObjectContext::BuildSharedTriggerContexts(triggerContexts); triggerContexts.Add(new PriestTriggerFactoryInternal()); } + +void PriestAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) +{ + AiObjectContext::BuildSharedValueContexts(valueContexts); +} \ No newline at end of file diff --git a/src/strategy/priest/PriestAiObjectContext.h b/src/strategy/priest/PriestAiObjectContext.h index 81c491b73..bb6efb4e7 100644 --- a/src/strategy/priest/PriestAiObjectContext.h +++ b/src/strategy/priest/PriestAiObjectContext.h @@ -14,6 +14,17 @@ class PriestAiObjectContext : public AiObjectContext { public: PriestAiObjectContext(PlayerbotAI* botAI); + + static void BuildSharedContexts(); + static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); + static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); + static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); + static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); + + static SharedNamedObjectContextList sharedStrategyContexts; + static SharedNamedObjectContextList sharedActionContexts; + static SharedNamedObjectContextList sharedTriggerContexts; + static SharedNamedObjectContextList sharedValueContexts; }; #endif diff --git a/src/strategy/rogue/RogueAiObjectContext.cpp b/src/strategy/rogue/RogueAiObjectContext.cpp index a63b97e11..39941bed4 100644 --- a/src/strategy/rogue/RogueAiObjectContext.cpp +++ b/src/strategy/rogue/RogueAiObjectContext.cpp @@ -5,6 +5,7 @@ #include "RogueAiObjectContext.h" +#include "AiObjectContext.h" #include "AssassinationRogueStrategy.h" #include "DpsRogueStrategy.h" #include "GenericRogueNonCombatStrategy.h" @@ -185,10 +186,45 @@ private: static Action* killing_spree(PlayerbotAI* ai) { return new CastKillingSpreeAction(ai); } }; -RogueAiObjectContext::RogueAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) +SharedNamedObjectContextList RogueAiObjectContext::sharedStrategyContexts; +SharedNamedObjectContextList RogueAiObjectContext::sharedActionContexts; +SharedNamedObjectContextList RogueAiObjectContext::sharedTriggerContexts; +SharedNamedObjectContextList 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& strategyContexts) +{ + AiObjectContext::BuildSharedStrategyContexts(strategyContexts); strategyContexts.Add(new RogueStrategyFactoryInternal()); strategyContexts.Add(new RogueCombatStrategyFactoryInternal()); +} + +void RogueAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) +{ + AiObjectContext::BuildSharedActionContexts(actionContexts); actionContexts.Add(new RogueAiObjectContextInternal()); +} + +void RogueAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) +{ + AiObjectContext::BuildSharedTriggerContexts(triggerContexts); triggerContexts.Add(new RogueTriggerFactoryInternal()); } + +void RogueAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) +{ + AiObjectContext::BuildSharedValueContexts(valueContexts); +} \ No newline at end of file diff --git a/src/strategy/rogue/RogueAiObjectContext.h b/src/strategy/rogue/RogueAiObjectContext.h index e641623fe..f1b3f98b2 100644 --- a/src/strategy/rogue/RogueAiObjectContext.h +++ b/src/strategy/rogue/RogueAiObjectContext.h @@ -7,6 +7,7 @@ #define _PLAYERBOT_ROGUEAIOBJECTCONTEXT_H #include "AiObjectContext.h" +#include "Strategy.h" class PlayerbotAI; @@ -14,6 +15,17 @@ class RogueAiObjectContext : public AiObjectContext { public: RogueAiObjectContext(PlayerbotAI* botAI); + + static void BuildSharedContexts(); + static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); + static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); + static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); + static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); + + static SharedNamedObjectContextList sharedStrategyContexts; + static SharedNamedObjectContextList sharedActionContexts; + static SharedNamedObjectContextList sharedTriggerContexts; + static SharedNamedObjectContextList sharedValueContexts; }; #endif diff --git a/src/strategy/rpg/NewRpgBaseAction.cpp b/src/strategy/rpg/NewRpgBaseAction.cpp index bd2a8221b..5e71c5c54 100644 --- a/src/strategy/rpg/NewRpgBaseAction.cpp +++ b/src/strategy/rpg/NewRpgBaseAction.cpp @@ -84,7 +84,7 @@ bool NewRpgBaseAction::MoveFarTo(WorldPosition dest) float rx, ry, rz; bool found = false; int attempt = 3; - while (--attempt) + while (attempt--) { 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; @@ -163,8 +163,8 @@ bool NewRpgBaseAction::MoveRandomNear(float moveStep, MovementPriority priority) const float x = bot->GetPositionX(); const float y = bot->GetPositionY(); const float z = bot->GetPositionZ(); - int attempts = 5; - while (--attempts) + int attempts = 1; + while (attempts--) { float angle = (float)rand_norm() * 2 * static_cast(M_PI); float dx = x + distance * cos(angle); diff --git a/src/strategy/shaman/ShamanAiObjectContext.cpp b/src/strategy/shaman/ShamanAiObjectContext.cpp index 9e79f7920..182251d1a 100644 --- a/src/strategy/shaman/ShamanAiObjectContext.cpp +++ b/src/strategy/shaman/ShamanAiObjectContext.cpp @@ -328,11 +328,45 @@ private: static Action* feral_spirit(PlayerbotAI* ai) { return new CastFeralSpiritAction(ai); } }; -ShamanAiObjectContext::ShamanAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) +SharedNamedObjectContextList ShamanAiObjectContext::sharedStrategyContexts; +SharedNamedObjectContextList ShamanAiObjectContext::sharedActionContexts; +SharedNamedObjectContextList ShamanAiObjectContext::sharedTriggerContexts; +SharedNamedObjectContextList 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& strategyContexts) +{ + AiObjectContext::BuildSharedStrategyContexts(strategyContexts); strategyContexts.Add(new ShamanStrategyFactoryInternal()); strategyContexts.Add(new ShamanCombatStrategyFactoryInternal()); strategyContexts.Add(new ShamanBuffStrategyFactoryInternal()); +} + +void ShamanAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) +{ + AiObjectContext::BuildSharedActionContexts(actionContexts); actionContexts.Add(new ShamanAiObjectContextInternal()); +} + +void ShamanAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) +{ + AiObjectContext::BuildSharedTriggerContexts(triggerContexts); triggerContexts.Add(new ShamanATriggerFactoryInternal()); } + +void ShamanAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) +{ + AiObjectContext::BuildSharedValueContexts(valueContexts); +} \ No newline at end of file diff --git a/src/strategy/shaman/ShamanAiObjectContext.h b/src/strategy/shaman/ShamanAiObjectContext.h index ad1c0af4c..d168f7afa 100644 --- a/src/strategy/shaman/ShamanAiObjectContext.h +++ b/src/strategy/shaman/ShamanAiObjectContext.h @@ -14,6 +14,17 @@ class ShamanAiObjectContext : public AiObjectContext { public: ShamanAiObjectContext(PlayerbotAI* botAI); + + static void BuildSharedContexts(); + static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); + static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); + static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); + static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); + + static SharedNamedObjectContextList sharedStrategyContexts; + static SharedNamedObjectContextList sharedActionContexts; + static SharedNamedObjectContextList sharedTriggerContexts; + static SharedNamedObjectContextList sharedValueContexts; }; #endif diff --git a/src/strategy/values/GrindTargetValue.cpp b/src/strategy/values/GrindTargetValue.cpp index 1737b7a7b..cd368741a 100644 --- a/src/strategy/values/GrindTargetValue.cpp +++ b/src/strategy/values/GrindTargetValue.cpp @@ -192,16 +192,16 @@ bool GrindTargetValue::needForQuest(Unit* target) 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) - { - if (LootTemplates_Creature.HaveQuestLootForPlayer(lootId, bot)) - { - return true; - } - } + return true; } } } diff --git a/src/strategy/values/NearestCorpsesValue.h b/src/strategy/values/NearestCorpsesValue.h index 9bda863bd..6453bb09f 100644 --- a/src/strategy/values/NearestCorpsesValue.h +++ b/src/strategy/values/NearestCorpsesValue.h @@ -15,7 +15,7 @@ class NearestCorpsesValue : public NearestUnitsValue { public: NearestCorpsesValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) - : NearestUnitsValue(botAI, "nearest corpses", range) + : NearestUnitsValue(botAI, "nearest corpses", range, true) { } diff --git a/src/strategy/values/SharedValueContext.h b/src/strategy/values/SharedValueContext.h index 5edb41f4c..54c3f3091 100644 --- a/src/strategy/values/SharedValueContext.h +++ b/src/strategy/values/SharedValueContext.h @@ -50,9 +50,12 @@ public: template Value* getGlobalValue(std::string const name) { - NamedObjectContextList valueContexts; - valueContexts.Add(this); + // should never reach here + SharedNamedObjectContextList sValueContexts; + sValueContexts.Add(this); + NamedObjectContextList valueContexts(sValueContexts); PlayerbotAI* botAI = new PlayerbotAI(); + UntypedValue* value = valueContexts.GetContextObject(name, botAI); delete botAI; return dynamic_cast*>(value); diff --git a/src/strategy/warlock/WarlockAiObjectContext.cpp b/src/strategy/warlock/WarlockAiObjectContext.cpp index 155ded9f3..acd92a6d1 100644 --- a/src/strategy/warlock/WarlockAiObjectContext.cpp +++ b/src/strategy/warlock/WarlockAiObjectContext.cpp @@ -4,16 +4,17 @@ */ #include "WarlockAiObjectContext.h" + #include "AfflictionWarlockStrategy.h" #include "DemonologyWarlockStrategy.h" #include "DestructionWarlockStrategy.h" -#include "TankWarlockStrategy.h" #include "GenericTriggers.h" #include "GenericWarlockNonCombatStrategy.h" #include "NamedObjectContext.h" #include "Playerbots.h" #include "PullStrategy.h" #include "Strategy.h" +#include "TankWarlockStrategy.h" #include "UseItemAction.h" #include "WarlockActions.h" #include "WarlockTriggers.h" @@ -22,14 +23,14 @@ class WarlockStrategyFactoryInternal : public NamedObjectContext { public: WarlockStrategyFactoryInternal() - { + { creators["nc"] = &WarlockStrategyFactoryInternal::nc; creators["pull"] = &WarlockStrategyFactoryInternal::pull; creators["boost"] = &WarlockStrategyFactoryInternal::boost; creators["cc"] = &WarlockStrategyFactoryInternal::cc; creators["pet"] = &WarlockStrategyFactoryInternal::pet; creators["spellstone"] = &WarlockStrategyFactoryInternal::spellstone; - creators["firestone"] = &WarlockStrategyFactoryInternal::firestone; + creators["firestone"] = &WarlockStrategyFactoryInternal::firestone; creators["meta melee"] = &WarlockStrategyFactoryInternal::meta_melee_aoe; creators["tank"] = &WarlockStrategyFactoryInternal::tank; creators["aoe"] = &WarlockStrategyFactoryInternal::aoe; @@ -196,7 +197,10 @@ private: static Trigger* immolate(PlayerbotAI* botAI) { return new ImmolateTrigger(botAI); } static Trigger* immolate_on_attacker(PlayerbotAI* ai) { return new ImmolateOnAttackerTrigger(ai); } static Trigger* unstable_affliction(PlayerbotAI* ai) { return new UnstableAfflictionTrigger(ai); } - static Trigger* unstable_affliction_on_attacker(PlayerbotAI* ai) { return new UnstableAfflictionOnAttackerTrigger(ai); } + static Trigger* unstable_affliction_on_attacker(PlayerbotAI* ai) + { + return new UnstableAfflictionOnAttackerTrigger(ai); + } static Trigger* haunt(PlayerbotAI* ai) { return new HauntTrigger(ai); } static Trigger* decimation(PlayerbotAI* ai) { return new DecimationTrigger(ai); } static Trigger* life_tap(PlayerbotAI* ai) { return new LifeTapTrigger(ai); } @@ -287,7 +291,7 @@ public: creators["curse of exhaustion"] = &WarlockAiObjectContextInternal::curse_of_exhaustion; creators["curse of tongues"] = &WarlockAiObjectContextInternal::curse_of_tongues; creators["curse of weakness"] = &WarlockAiObjectContextInternal::curse_of_weakness; - } + } private: static Action* conflagrate(PlayerbotAI* botAI) { return new CastConflagrateAction(botAI); } @@ -328,13 +332,19 @@ private: static Action* devour_magic_purge(PlayerbotAI* botAI) { return new CastDevourMagicPurgeAction(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_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* hellfire(PlayerbotAI* botAI) { return new CastHellfireAction(botAI); } static Action* shadowfury(PlayerbotAI* botAI) { return new CastShadowfuryAction(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_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* demonic_empowerment(PlayerbotAI* ai) { return new CastDemonicEmpowermentAction(ai); } static Action* metamorphosis(PlayerbotAI* ai) { return new CastMetamorphosisAction(ai); } @@ -345,11 +355,14 @@ private: static Action* shadowflame(PlayerbotAI* botAI) { return new CastShadowflameAction(botAI); } static Action* immolation_aura(PlayerbotAI* botAI) { return new CastImmolationAuraAction(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* shadow_ward(PlayerbotAI* botAI) { return new CastShadowWardAction(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_doom(PlayerbotAI* ai) { return new CastCurseOfDoomAction(ai); } static Action* curse_of_exhaustion(PlayerbotAI* ai) { return new CastCurseOfExhaustionAction(ai); } @@ -357,13 +370,47 @@ private: static Action* curse_of_weakness(PlayerbotAI* ai) { return new CastCurseOfWeaknessAction(ai); } }; -WarlockAiObjectContext::WarlockAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) +SharedNamedObjectContextList WarlockAiObjectContext::sharedStrategyContexts; +SharedNamedObjectContextList WarlockAiObjectContext::sharedActionContexts; +SharedNamedObjectContextList WarlockAiObjectContext::sharedTriggerContexts; +SharedNamedObjectContextList 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& strategyContexts) +{ + AiObjectContext::BuildSharedStrategyContexts(strategyContexts); strategyContexts.Add(new WarlockStrategyFactoryInternal()); strategyContexts.Add(new WarlockCombatStrategyFactoryInternal()); strategyContexts.Add(new WarlockPetStrategyFactoryInternal()); strategyContexts.Add(new WarlockSoulstoneStrategyFactoryInternal()); strategyContexts.Add(new WarlockCurseStrategyFactoryInternal()); +} + +void WarlockAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) +{ + AiObjectContext::BuildSharedActionContexts(actionContexts); actionContexts.Add(new WarlockAiObjectContextInternal()); +} + +void WarlockAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) +{ + AiObjectContext::BuildSharedTriggerContexts(triggerContexts); triggerContexts.Add(new WarlockTriggerFactoryInternal()); } + +void WarlockAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) +{ + AiObjectContext::BuildSharedValueContexts(valueContexts); +} \ No newline at end of file diff --git a/src/strategy/warlock/WarlockAiObjectContext.h b/src/strategy/warlock/WarlockAiObjectContext.h index c1feb9128..08e6d0f59 100644 --- a/src/strategy/warlock/WarlockAiObjectContext.h +++ b/src/strategy/warlock/WarlockAiObjectContext.h @@ -14,6 +14,17 @@ class WarlockAiObjectContext : public AiObjectContext { public: WarlockAiObjectContext(PlayerbotAI* botAI); + + static void BuildSharedContexts(); + static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); + static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); + static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); + static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); + + static SharedNamedObjectContextList sharedStrategyContexts; + static SharedNamedObjectContextList sharedActionContexts; + static SharedNamedObjectContextList sharedTriggerContexts; + static SharedNamedObjectContextList sharedValueContexts; }; #endif diff --git a/src/strategy/warrior/WarriorAiObjectContext.cpp b/src/strategy/warrior/WarriorAiObjectContext.cpp index 0a761c564..bcec922cf 100644 --- a/src/strategy/warrior/WarriorAiObjectContext.cpp +++ b/src/strategy/warrior/WarriorAiObjectContext.cpp @@ -318,10 +318,44 @@ private: static Action* enraged_regeneration(PlayerbotAI* botAI) { return new CastEnragedRegenerationAction(botAI); } }; -WarriorAiObjectContext::WarriorAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) +SharedNamedObjectContextList WarriorAiObjectContext::sharedStrategyContexts; +SharedNamedObjectContextList WarriorAiObjectContext::sharedActionContexts; +SharedNamedObjectContextList WarriorAiObjectContext::sharedTriggerContexts; +SharedNamedObjectContextList 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& strategyContexts) +{ + AiObjectContext::BuildSharedStrategyContexts(strategyContexts); strategyContexts.Add(new WarriorStrategyFactoryInternal()); strategyContexts.Add(new WarriorCombatStrategyFactoryInternal()); +} + +void WarriorAiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) +{ + AiObjectContext::BuildSharedActionContexts(actionContexts); actionContexts.Add(new WarriorAiObjectContextInternal()); +} + +void WarriorAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts) +{ + AiObjectContext::BuildSharedTriggerContexts(triggerContexts); triggerContexts.Add(new WarriorTriggerFactoryInternal()); } + +void WarriorAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) +{ + AiObjectContext::BuildSharedValueContexts(valueContexts); +} \ No newline at end of file diff --git a/src/strategy/warrior/WarriorAiObjectContext.h b/src/strategy/warrior/WarriorAiObjectContext.h index ab5229223..2c9bab973 100644 --- a/src/strategy/warrior/WarriorAiObjectContext.h +++ b/src/strategy/warrior/WarriorAiObjectContext.h @@ -14,6 +14,17 @@ class WarriorAiObjectContext : public AiObjectContext { public: WarriorAiObjectContext(PlayerbotAI* botAI); + + static void BuildSharedContexts(); + static void BuildSharedStrategyContexts(SharedNamedObjectContextList& strategyContexts); + static void BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts); + static void BuildSharedTriggerContexts(SharedNamedObjectContextList& triggerContexts); + static void BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts); + + static SharedNamedObjectContextList sharedStrategyContexts; + static SharedNamedObjectContextList sharedActionContexts; + static SharedNamedObjectContextList sharedTriggerContexts; + static SharedNamedObjectContextList sharedValueContexts; }; #endif From a33bb3b51effd0e311c71e17981b747eab9b9458 Mon Sep 17 00:00:00 2001 From: ThePenguinMan96 Date: Fri, 25 Jul 2025 14:02:20 -0700 Subject: [PATCH 4/5] Changes requested Updating based on changes requested for commit --- src/strategy/warlock/WarlockActions.cpp | 25 ++++++++----------- .../warlock/WarlockAiObjectContext.cpp | 4 +-- src/strategy/warlock/WarlockTriggers.cpp | 2 +- src/strategy/warlock/WarlockTriggers.h | 4 +-- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/strategy/warlock/WarlockActions.cpp b/src/strategy/warlock/WarlockActions.cpp index 69f1f3358..b3b57871d 100644 --- a/src/strategy/warlock/WarlockActions.cpp +++ b/src/strategy/warlock/WarlockActions.cpp @@ -171,24 +171,21 @@ bool CastCreateSoulstoneAction::isUseful() }; // Check if the bot already has any soulstone - uint32 currentSoulstones = 0; - for (uint32 id : soulstoneIds) - currentSoulstones += bot->GetItemCount(id, false); // false = only bags - - // Allow only if the bot has no soulstone AND there is space for one - ItemPosCountVec dest; - uint32 count = 1; - bool hasSpace = false; for (uint32 id : soulstoneIds) { - if (bot->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count) == EQUIP_ERR_OK) - { - hasSpace = true; - break; - } + if (bot->GetItemCount(id, false) > 0) + return false; // Already has a soulstone } - return (currentSoulstones == 0) && hasSpace; + // 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) diff --git a/src/strategy/warlock/WarlockAiObjectContext.cpp b/src/strategy/warlock/WarlockAiObjectContext.cpp index 155ded9f3..840ee8cd7 100644 --- a/src/strategy/warlock/WarlockAiObjectContext.cpp +++ b/src/strategy/warlock/WarlockAiObjectContext.cpp @@ -137,7 +137,7 @@ public: creators["no healthstone"] = &WarlockTriggerFactoryInternal::HasHealthstone; creators["no firestone"] = &WarlockTriggerFactoryInternal::HasFirestone; creators["no spellstone"] = &WarlockTriggerFactoryInternal::HasSpellstone; - creators["no soulstone"] = &WarlockTriggerFactoryInternal::HasSoulstone; + creators["no soulstone"] = &WarlockTriggerFactoryInternal::OutOfSoulstone; creators["firestone"] = &WarlockTriggerFactoryInternal::firestone; creators["spellstone"] = &WarlockTriggerFactoryInternal::spellstone; creators["soulstone"] = &WarlockTriggerFactoryInternal::soulstone; @@ -181,7 +181,7 @@ private: static Trigger* HasHealthstone(PlayerbotAI* botAI) { return new HasHealthstoneTrigger(botAI); } static Trigger* HasFirestone(PlayerbotAI* botAI) { return new HasFirestoneTrigger(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* spellstone(PlayerbotAI* botAI) { return new SpellstoneTrigger(botAI); } static Trigger* soulstone(PlayerbotAI* botAI) { return new SoulstoneTrigger(botAI); } diff --git a/src/strategy/warlock/WarlockTriggers.cpp b/src/strategy/warlock/WarlockTriggers.cpp index e0493e207..b97949356 100644 --- a/src/strategy/warlock/WarlockTriggers.cpp +++ b/src/strategy/warlock/WarlockTriggers.cpp @@ -46,7 +46,7 @@ bool OutOfSoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot bool TooManySoulShardsTrigger::IsActive() { return GetSoulShardCount(botAI->GetBot()) >= 6; } -bool HasSoulstoneTrigger::IsActive() { return GetSoulstoneCount(botAI->GetBot()) == 0; } +bool OutOfSoulstoneTrigger::IsActive() { return GetSoulstoneCount(botAI->GetBot()) == 0; } // Checks if the target marked with the moon icon can be banished bool BanishTrigger::IsActive() diff --git a/src/strategy/warlock/WarlockTriggers.h b/src/strategy/warlock/WarlockTriggers.h index 3a4489737..e5ce9ad12 100644 --- a/src/strategy/warlock/WarlockTriggers.h +++ b/src/strategy/warlock/WarlockTriggers.h @@ -58,10 +58,10 @@ public: bool IsActive() override; }; -class HasSoulstoneTrigger : public Trigger +class OutOfSoulstoneTrigger : public Trigger { public: - HasSoulstoneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soulstone") {} + OutOfSoulstoneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no soulstone") {} bool IsActive() override; }; From c04477b54db2a5b81cb0f52f99c035973abe39fd Mon Sep 17 00:00:00 2001 From: ThePenguinMan96 Date: Fri, 25 Jul 2025 19:00:37 -0700 Subject: [PATCH 5/5] Warlock Pet Re-Summon on Strategy Change Hello everyone, This PR addresses issue #1464 - Now, when you change a strategy, the new pet will be summoned accordingly - as long as the warlock knows the pet. I tested this myself with level 80 warlocks, then moved to lower level warlocks. It was nice to see that when my affliction warlock went from level 29 to 30, it automatically summoned the felhunter (while having the succubus out prior). List of changes per file: src\AiFactory.cpp: Set default level 1 spec to demonology for altbots - it was affliction prior. This will allow them to use Curse of agony, corruption, and immolate between levels 1-10. src\strategy\warlock\GenericWarlockNonCombatStrategy.cpp: Added the "wrong pet" trigger to each of the 5 pet strategies, coupled with the appropriate summon action. src\strategy\warlock\WarlockAiObjectContext.cpp: Registered the "wrong pet" trigger and moved the unstable affliction static trigger all to 1 line, cleaning it up a bit. src\strategy\warlock\WarlockTriggers.cpp: Added the logic for the wrong pet trigger here. I tried to leave detailed comments as much as possible explaining it's thought process. src\strategy\warlock\WarlockTriggers.h: Added the WrongPetTrigger. --- src/AiFactory.cpp | 3 + .../GenericWarlockNonCombatStrategy.cpp | 5 ++ .../warlock/WarlockAiObjectContext.cpp | 9 ++- src/strategy/warlock/WarlockTriggers.cpp | 63 +++++++++++++++++++ src/strategy/warlock/WarlockTriggers.h | 8 +++ 5 files changed, 83 insertions(+), 5 deletions(-) diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index 7c18070b2..722e46b53 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -88,6 +88,9 @@ uint8 AiFactory::GetPlayerSpecTab(Player* bot) case CLASS_PRIEST: tab = PRIEST_TAB_HOLY; break; + case CLASS_WARLOCK: + tab = WARLOCK_TAB_DEMONOLOGY; + break; } return tab; diff --git a/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp b/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp index 1e2b89af2..2fd3c78cd 100644 --- a/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp +++ b/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp @@ -98,6 +98,7 @@ SummonImpStrategy::SummonImpStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {} void SummonImpStrategy::InitTriggers(std::vector& triggers) { triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon imp", 29.0f), NULL))); + triggers.push_back(new TriggerNode("wrong pet", NextAction::array(0, new NextAction("summon imp", 29.0f), NULL))); } // Non-combat strategy for summoning a Voidwalker @@ -109,6 +110,7 @@ SummonVoidwalkerStrategy::SummonVoidwalkerStrategy(PlayerbotAI* ai) : NonCombatS void SummonVoidwalkerStrategy::InitTriggers(std::vector& triggers) { 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 @@ -120,6 +122,7 @@ SummonSuccubusStrategy::SummonSuccubusStrategy(PlayerbotAI* ai) : NonCombatStrat void SummonSuccubusStrategy::InitTriggers(std::vector& triggers) { 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 @@ -131,6 +134,7 @@ SummonFelhunterStrategy::SummonFelhunterStrategy(PlayerbotAI* ai) : NonCombatStr void SummonFelhunterStrategy::InitTriggers(std::vector& triggers) { 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 @@ -142,6 +146,7 @@ SummonFelguardStrategy::SummonFelguardStrategy(PlayerbotAI* ai) : NonCombatStrat void SummonFelguardStrategy::InitTriggers(std::vector& triggers) { 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 diff --git a/src/strategy/warlock/WarlockAiObjectContext.cpp b/src/strategy/warlock/WarlockAiObjectContext.cpp index 7603a5e24..8a87a8239 100644 --- a/src/strategy/warlock/WarlockAiObjectContext.cpp +++ b/src/strategy/warlock/WarlockAiObjectContext.cpp @@ -171,6 +171,7 @@ public: creators["curse of exhaustion"] = &WarlockTriggerFactoryInternal::curse_of_exhaustion; creators["curse of tongues"] = &WarlockTriggerFactoryInternal::curse_of_tongues; creators["curse of weakness"] = &WarlockTriggerFactoryInternal::curse_of_weakness; + creators["wrong pet"] = &WarlockTriggerFactoryInternal::wrong_pet; } private: @@ -197,10 +198,7 @@ private: static Trigger* immolate(PlayerbotAI* botAI) { return new ImmolateTrigger(botAI); } static Trigger* immolate_on_attacker(PlayerbotAI* ai) { return new ImmolateOnAttackerTrigger(ai); } static Trigger* unstable_affliction(PlayerbotAI* ai) { return new UnstableAfflictionTrigger(ai); } - static Trigger* unstable_affliction_on_attacker(PlayerbotAI* ai) - { - return new UnstableAfflictionOnAttackerTrigger(ai); - } + static Trigger* unstable_affliction_on_attacker(PlayerbotAI* ai) { return new UnstableAfflictionOnAttackerTrigger(ai); } static Trigger* haunt(PlayerbotAI* ai) { return new HauntTrigger(ai); } static Trigger* decimation(PlayerbotAI* ai) { return new DecimationTrigger(ai); } static Trigger* life_tap(PlayerbotAI* ai) { return new LifeTapTrigger(ai); } @@ -218,6 +216,7 @@ private: 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_weakness(PlayerbotAI* ai) { return new CurseOfWeaknessTrigger(ai); } + static Trigger* wrong_pet(PlayerbotAI* ai) { return new WrongPetTrigger(ai); } }; class WarlockAiObjectContextInternal : public NamedObjectContext @@ -413,4 +412,4 @@ void WarlockAiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContext void WarlockAiObjectContext::BuildSharedValueContexts(SharedNamedObjectContextList& valueContexts) { AiObjectContext::BuildSharedValueContexts(valueContexts); -} \ No newline at end of file +} diff --git a/src/strategy/warlock/WarlockTriggers.cpp b/src/strategy/warlock/WarlockTriggers.cpp index b97949356..e8198c1a3 100644 --- a/src/strategy/warlock/WarlockTriggers.cpp +++ b/src/strategy/warlock/WarlockTriggers.cpp @@ -165,3 +165,66 @@ bool CurseOfWeaknessTrigger::IsActive() // Use default BuffTrigger logic for the rest (only trigger if debuff is missing or expiring) 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; +} diff --git a/src/strategy/warlock/WarlockTriggers.h b/src/strategy/warlock/WarlockTriggers.h index e5ce9ad12..e886635a1 100644 --- a/src/strategy/warlock/WarlockTriggers.h +++ b/src/strategy/warlock/WarlockTriggers.h @@ -112,6 +112,14 @@ public: 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 class BanishTrigger : public HasCcTargetTrigger