From 8f7d352f7e7de7416fdcddac20f36aa9bc26f7c5 Mon Sep 17 00:00:00 2001 From: Flashtate98 <106729837+flashtate98@users.noreply.github.com> Date: Fri, 17 Apr 2026 13:26:08 -0500 Subject: [PATCH] Implement Auchenai Crypts Strategies and TBC Dungeon Contexts (#2229) ## Pull Request Description This PR aims to add bot strategies to the Auchenai Crypts dungeon, specifically for the boss Shirrak the Dead Watcher, as his focus fire mechanic is really annoying to deal with. Additionally I have added TbcDungeonActionContext.h and TbcDungeonTriggerContext.h for future reference as I add more strategies to TBC dungeons that need it. A HUGE thank you to @brighton-chi for all his help. This has been a fun learning experience! ## Feature Evaluation - Describe the **minimum logic** required to achieve the intended behavior. Trigger: A 20 yard radius grid search is performed to locate the focus fire trigger NPC Action: Bots will flee from the trigger NPC using MoveAway with a 5 yard safety buffer Multiplier: A for loop that prevents bots from running back into the focus fire mechanic while its active. Tanking: Tanks have a set coordinate to drag the boss to for the duration of the fight. - Describe the **processing cost** when this logic executes across many bots. Minimal, these scripts only execute when Shirrak has been engaged. ## How to Test the Changes Go into Auchenai Crypts (Normal or Heroic) and engage Shirrak the Dead Watcher ## Impact Assessment - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - - [ ] No, not at all - - [X] Minimal impact (**explain below**) - - [ ] Moderate impact (**explain below**) This logic is only applied to Auchenai Crypts and activates during Shirrak's encounter. - Does this change modify default bot behavior? - - [ ] No - - [X] Yes (**explain why**) Behavior only applies when in the instance and when engaged with Shirrak. - Does this change add new decision branches or increase maintenance complexity? - - [ ] No - - [X] Yes (**explain below**) New dungeon contexts were added (TbcDungeonActionContext and TbcDungeonTriggerContext) to provide a clean and dedicated structure for future TBC dungeon strategies that will be developed. This was done to be in alignment with the existing WOTLK contexts that already exist. ## Messages to Translate Does this change add bot messages to translate? - - [X] No - - [ ] Yes (**list messages in the table**) | Message key | Default message | | --------------- | ------------------ | | | | | | | ## AI Assistance Was AI assistance used while working on this change? - - [ ] No - - [X] Yes (**explain below**) Gemini was used to help me understand existing code in the module I was referencing and reusing to develop this strategy as I am not a programmer and hardly know anything about C++. ## Final Checklist - - [X] Stability is not compromised. - - [ ] Performance impact is understood, tested, and acceptable. - - [ ] Added logic complexity is justified and explained. - - [ ] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers If there are any better alternatives that could be used to help improve the strategy in any way, please suggest it. I am very new to this and want to learn and improve. --------- Co-authored-by: Keleborn <22352763+Celandriel@users.noreply.github.com> Co-authored-by: bash Co-authored-by: Revision Co-authored-by: kadeshar --- .../Action/AuchenaiCryptsActions.cpp | 117 ++++++++++++++++++ .../Action/AuchenaiCryptsActions.h | 31 +++++ .../AuchenaiCryptsActionContext.h | 34 +++++ .../AuchenaiCryptsTriggerContext.h | 35 ++++++ .../Multiplier/AuchenaiCryptsMultipliers.cpp | 45 +++++++ .../Multiplier/AuchenaiCryptsMultipliers.h | 13 ++ .../Strategy/AuchenaiCryptsStrategy.cpp | 21 ++++ .../Strategy/AuchenaiCryptsStrategy.h | 19 +++ .../Trigger/AuchenaiCryptsTriggers.cpp | 34 +++++ .../Trigger/AuchenaiCryptsTriggers.h | 38 ++++++ src/Ai/Dungeon/DungeonStrategyContext.h | 4 +- src/Ai/Dungeon/TbcDungeonActionContext.h | 6 + src/Ai/Dungeon/TbcDungeonTriggerContext.h | 6 + src/Bot/Engine/BuildSharedActionContexts.cpp | 2 + src/Bot/Engine/BuildSharedTriggerContexts.cpp | 2 + src/Bot/PlayerbotAI.cpp | 5 +- 16 files changed, 410 insertions(+), 2 deletions(-) create mode 100644 src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.cpp create mode 100644 src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.h create mode 100644 src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsActionContext.h create mode 100644 src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsTriggerContext.h create mode 100644 src/Ai/Dungeon/AuchenaiCrypts/Multiplier/AuchenaiCryptsMultipliers.cpp create mode 100644 src/Ai/Dungeon/AuchenaiCrypts/Multiplier/AuchenaiCryptsMultipliers.h create mode 100644 src/Ai/Dungeon/AuchenaiCrypts/Strategy/AuchenaiCryptsStrategy.cpp create mode 100644 src/Ai/Dungeon/AuchenaiCrypts/Strategy/AuchenaiCryptsStrategy.h create mode 100644 src/Ai/Dungeon/AuchenaiCrypts/Trigger/AuchenaiCryptsTriggers.cpp create mode 100644 src/Ai/Dungeon/AuchenaiCrypts/Trigger/AuchenaiCryptsTriggers.h create mode 100644 src/Ai/Dungeon/TbcDungeonActionContext.h create mode 100644 src/Ai/Dungeon/TbcDungeonTriggerContext.h diff --git a/src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.cpp b/src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.cpp new file mode 100644 index 000000000..2ec7907c7 --- /dev/null +++ b/src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.cpp @@ -0,0 +1,117 @@ +#include "Playerbots.h" +#include "AiFactory.h" +#include "AuchenaiCryptsTriggers.h" +#include "AuchenaiCryptsActions.h" + +// Shirrak the Dead Watcher + +static const Position SHIRRAK_RANGED_POSITION = { -21.777f, -162.700f, 26.062f }; +static const Position SHIRRAK_TANK_POSITION = { -65.171f, -162.920f, 26.504f }; + +// Tank will position Shirrak at the specified coordinates, further down the corridor past the stairs + +bool ShirrakTankPositionBossAction::Execute(Event /*event*/) +{ + Unit* shirrak = AI_VALUE2(Unit*, "find target", "shirrak the dead watcher"); + if (!shirrak) + return false; + + if (bot->GetVictim() != shirrak) + return Attack(shirrak); + + if (shirrak->GetVictim() == bot && bot->IsWithinMeleeRange(shirrak) && + bot->GetHealthPct()>30.0f) + { + const Position& position = SHIRRAK_TANK_POSITION; + float distToPosition = bot->GetExactDist2d(position.GetPositionX(), + position.GetPositionY()); + if (distToPosition > 6.0f) + { + float dX = position.GetPositionX() - bot->GetPositionX(); + float dY = position.GetPositionY() - bot->GetPositionY(); + float moveDist = std::min(2.0f, distToPosition); + float moveX = bot->GetPositionX() + (dX / distToPosition) * moveDist; + float moveY = bot->GetPositionY() + (dY / distToPosition) * moveDist; + + return MoveTo(bot->GetMapId(), moveX, moveY, bot->GetPositionZ(), false, false, + false, false, MovementPriority::MOVEMENT_COMBAT, true, true); + } + } + + return false; +} + +// Flee from Shirrak's Focus Fire + +bool ShirrakFleeFocusFireAction::Execute(Event /*event*/) +{ + std::list creatureList; + bot->GetCreatureListWithEntryInGrid(creatureList, static_cast(AuchenaiCryptsIDs::NPC_FOCUS_FIRE), 20.0f); + + for (Creature* flare : creatureList) + { + if (flare && flare->IsAlive()) + { + float currentDistance = bot->GetDistance2d(flare); + constexpr float safeDistance = 12.0f; + constexpr float buffer = 5.0f; + + if (currentDistance < safeDistance) + { + bot->AttackStop(); + + float distanceToMove = safeDistance - currentDistance + buffer; + + return MoveAway(flare, distanceToMove); + } + } + } + return false; +} + +// Ranged should keep distance from Shirrak, staying at the edge of the stairs + +bool ShirrakRangedKeepDistanceAction::Execute(Event /*event*/) +{ + + std::vector rangedBots; + if (Group* group = bot->GetGroup()) + { + for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) + { + Player* member = ref->GetSource(); + if (member && botAI->IsRanged(member)) + rangedBots.push_back(member); + } + } + + auto findIt = std::find(rangedBots.begin(), rangedBots.end(), bot); + size_t botIndex = (findIt != rangedBots.end()) ? std::distance(rangedBots.begin(), findIt) : 0; + size_t count = rangedBots.size(); + + constexpr float arcSpan = M_PI / 2.0f; + float arcCenter = M_PI; + float arcStart = arcCenter - (arcSpan / 2.0f); + + float angle = (count <= 1) ? arcCenter : (arcStart + (arcSpan * (float)botIndex / (float)(count - 1))); + + constexpr float spreadRadius = 3.0f; + float targetX = SHIRRAK_RANGED_POSITION.GetPositionX() + cos(angle) * spreadRadius; + float targetY = SHIRRAK_RANGED_POSITION.GetPositionY() + sin(angle) * spreadRadius; + + float distToSpot = bot->GetExactDist2d(targetX, targetY); + + if (distToSpot > 4.0f) + { + float dX = targetX - bot->GetPositionX(); + float dY = targetY - bot->GetPositionY(); + + float moveDist = std::min(2.0f, distToSpot); + float moveX = bot->GetPositionX() + (dX / distToSpot) * moveDist; + float moveY = bot->GetPositionY() + (dY / distToSpot) * moveDist; + + return MoveTo(bot->GetMapId(), moveX, moveY, bot->GetPositionZ(), false, false, + false, false, MovementPriority::MOVEMENT_COMBAT, true, false); + } + return false; +} diff --git a/src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.h b/src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.h new file mode 100644 index 000000000..4764efb65 --- /dev/null +++ b/src/Ai/Dungeon/AuchenaiCrypts/Action/AuchenaiCryptsActions.h @@ -0,0 +1,31 @@ +#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSACTIONS_H +#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSACTIONS_H + +#include "AttackAction.h" +#include "MovementActions.h" +#include "AuchenaiCryptsTriggers.h" + +// Shirrak the Dead Watcher + +class ShirrakTankPositionBossAction : public AttackAction +{ +public: + ShirrakTankPositionBossAction(PlayerbotAI* botAI) : AttackAction(botAI, "shirrak tank position boss") {} + bool Execute(Event event) override; +}; + +class ShirrakFleeFocusFireAction : public MovementAction +{ +public: + ShirrakFleeFocusFireAction(PlayerbotAI* botAI) : MovementAction(botAI, "shirrak flee focus fire") {} + bool Execute(Event event) override; +}; + +class ShirrakRangedKeepDistanceAction : public MovementAction +{ +public: + ShirrakRangedKeepDistanceAction(PlayerbotAI* botAI) : MovementAction(botAI, "shirrak ranged keep distance") {} + bool Execute(Event event) override; +}; + +#endif diff --git a/src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsActionContext.h b/src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsActionContext.h new file mode 100644 index 000000000..4eea58716 --- /dev/null +++ b/src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsActionContext.h @@ -0,0 +1,34 @@ +#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSACTIONCONTEXT_H +#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSACTIONCONTEXT_H + +#include "AiObjectContext.h" +#include "Action.h" +#include "AuchenaiCryptsActions.h" + +class TbcDungeonAuchenaiCryptsActionContext : public NamedObjectContext +{ +public: + TbcDungeonAuchenaiCryptsActionContext() : NamedObjectContext(false, true) + { + creators["shirrak tank position boss"] = + &TbcDungeonAuchenaiCryptsActionContext::shirrak_tank_position_boss; + + creators["shirrak flee focus fire"] = + &TbcDungeonAuchenaiCryptsActionContext::shirrak_flee_focus_fire; + + creators["shirrak ranged keep distance"] = + &TbcDungeonAuchenaiCryptsActionContext::shirrak_ranged_keep_distance; + } +private: + + static Action* shirrak_tank_position_boss( + PlayerbotAI* botAI) { return new ShirrakTankPositionBossAction(botAI); } + + static Action* shirrak_flee_focus_fire( + PlayerbotAI* botAI) { return new ShirrakFleeFocusFireAction(botAI); } + + static Action* shirrak_ranged_keep_distance( + PlayerbotAI* botAI) { return new ShirrakRangedKeepDistanceAction(botAI); } +}; + +#endif diff --git a/src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsTriggerContext.h b/src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsTriggerContext.h new file mode 100644 index 000000000..95f15f16a --- /dev/null +++ b/src/Ai/Dungeon/AuchenaiCrypts/AuchenaiCryptsTriggerContext.h @@ -0,0 +1,35 @@ +#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSTRIGGERCONTEXT_H +#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSTRIGGERCONTEXT_H + +#include "AiObjectContext.h" +#include "TriggerContext.h" +#include "AuchenaiCryptsTriggers.h" + +class TbcDungeonAuchenaiCryptsTriggerContext : public NamedObjectContext +{ +public: + // Shirrak the Dead Watcher + TbcDungeonAuchenaiCryptsTriggerContext() + { + creators["shirrak tank position boss"] = + &TbcDungeonAuchenaiCryptsTriggerContext::shirrak_tank_position_boss; + + creators["shirrak flee focus fire"] = + &TbcDungeonAuchenaiCryptsTriggerContext::shirrak_flee_focus_fire; + + creators["shirrak ranged keep distance"] = + &TbcDungeonAuchenaiCryptsTriggerContext::shirrak_ranged_keep_distance; + } +private: + // Shirrak the Dead Watcher + static Trigger* shirrak_tank_position_boss( + PlayerbotAI* botAI) { return new ShirrakTankPositionBossTrigger(botAI); } + + static Trigger* shirrak_flee_focus_fire( + PlayerbotAI* botAI) { return new ShirrakFleeFocusFireTrigger(botAI); } + + static Trigger* shirrak_ranged_keep_distance( + PlayerbotAI* botAI) { return new ShirrakRangedKeepDistanceTrigger(botAI); } +}; + +#endif diff --git a/src/Ai/Dungeon/AuchenaiCrypts/Multiplier/AuchenaiCryptsMultipliers.cpp b/src/Ai/Dungeon/AuchenaiCrypts/Multiplier/AuchenaiCryptsMultipliers.cpp new file mode 100644 index 000000000..2f74a5a58 --- /dev/null +++ b/src/Ai/Dungeon/AuchenaiCrypts/Multiplier/AuchenaiCryptsMultipliers.cpp @@ -0,0 +1,45 @@ +#include "AuchenaiCryptsMultipliers.h" +#include "AuchenaiCryptsActions.h" +#include "AuchenaiCryptsTriggers.h" +#include "MovementActions.h" +#include "ReachTargetActions.h" +#include "FollowActions.h" +#include "AiObjectContext.h" +#include "Playerbots.h" + +// Shirrak the Dead Watcher + +// Flee from Focus Fire and dont run back in +float ShirrakFleeFocusFireMultiplier::GetValue(Action* action) +{ + if (!AI_VALUE2(Unit*, "find target", "shirrak the dead watcher")) + return 1.0f; + + std::list creatureList; + bot->GetCreatureListWithEntryInGrid(creatureList, static_cast(AuchenaiCryptsIDs::NPC_FOCUS_FIRE), 20.0f); + + for (Creature* flare : creatureList) + { + if (flare && flare->IsAlive()) + { + if (dynamic_cast(action)) + return 0.0f; + + float currentDistance = bot->GetDistance2d(flare); + constexpr float safeDistance = 12.0f; + constexpr float buffer = 5.0f; + + if (currentDistance < safeDistance + buffer && ( + dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action))) + { + return 0.0f; + } + } + } + return 1.0f; +} diff --git a/src/Ai/Dungeon/AuchenaiCrypts/Multiplier/AuchenaiCryptsMultipliers.h b/src/Ai/Dungeon/AuchenaiCrypts/Multiplier/AuchenaiCryptsMultipliers.h new file mode 100644 index 000000000..df5de2318 --- /dev/null +++ b/src/Ai/Dungeon/AuchenaiCrypts/Multiplier/AuchenaiCryptsMultipliers.h @@ -0,0 +1,13 @@ +#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSMULTIPLIERS_H +#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSMULTIPLIERS_H + +#include "Multiplier.h" + +class ShirrakFleeFocusFireMultiplier : public Multiplier +{ +public: + ShirrakFleeFocusFireMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "shirrak flee focus fire") {} + float GetValue(Action* action) override; +}; + +#endif diff --git a/src/Ai/Dungeon/AuchenaiCrypts/Strategy/AuchenaiCryptsStrategy.cpp b/src/Ai/Dungeon/AuchenaiCrypts/Strategy/AuchenaiCryptsStrategy.cpp new file mode 100644 index 000000000..f975d46bb --- /dev/null +++ b/src/Ai/Dungeon/AuchenaiCrypts/Strategy/AuchenaiCryptsStrategy.cpp @@ -0,0 +1,21 @@ +#include "AuchenaiCryptsTriggers.h" +#include "AuchenaiCryptsStrategy.h" +#include "AuchenaiCryptsMultipliers.h" + +void TbcDungeonAuchenaiCryptsStrategy::InitTriggers(std::vector& triggers) +{ + // Shirrak The Dead Watcher + triggers.push_back(new TriggerNode("shirrak tank position boss", { + NextAction("shirrak tank position boss", ACTION_RAID + 1) })); + + triggers.push_back(new TriggerNode("shirrak flee focus fire", { + NextAction("shirrak flee focus fire", ACTION_EMERGENCY + 10) })); + + triggers.push_back(new TriggerNode("shirrak ranged keep distance", { + NextAction("shirrak ranged keep distance", ACTION_RAID + 1) })); +} + +void TbcDungeonAuchenaiCryptsStrategy::InitMultipliers(std::vector& multipliers) +{ + multipliers.push_back(new ShirrakFleeFocusFireMultiplier(botAI)); +} diff --git a/src/Ai/Dungeon/AuchenaiCrypts/Strategy/AuchenaiCryptsStrategy.h b/src/Ai/Dungeon/AuchenaiCrypts/Strategy/AuchenaiCryptsStrategy.h new file mode 100644 index 000000000..ff82a0266 --- /dev/null +++ b/src/Ai/Dungeon/AuchenaiCrypts/Strategy/AuchenaiCryptsStrategy.h @@ -0,0 +1,19 @@ +#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSSTRATEGY_H +#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSSTRATEGY_H + +#include "AiObjectContext.h" +#include "Strategy.h" +#include "Multiplier.h" + +class TbcDungeonAuchenaiCryptsStrategy : public Strategy +{ +public: + TbcDungeonAuchenaiCryptsStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} + + virtual std::string const getName() override { return "tbc-ac"; } + + virtual void InitTriggers(std::vector &triggers) override; + virtual void InitMultipliers(std::vector &multipliers) override; +}; + +#endif diff --git a/src/Ai/Dungeon/AuchenaiCrypts/Trigger/AuchenaiCryptsTriggers.cpp b/src/Ai/Dungeon/AuchenaiCrypts/Trigger/AuchenaiCryptsTriggers.cpp new file mode 100644 index 000000000..372614d2f --- /dev/null +++ b/src/Ai/Dungeon/AuchenaiCrypts/Trigger/AuchenaiCryptsTriggers.cpp @@ -0,0 +1,34 @@ +#include "Playerbots.h" +#include "AuchenaiCryptsTriggers.h" +#include "AiObject.h" +#include "AiObjectContext.h" + +// Shirrak the Dead Watcher + +bool ShirrakTankPositionBossTrigger::IsActive() +{ + return botAI->IsTank(bot) && + AI_VALUE2(Unit*, "find target", "shirrak the dead watcher"); +} + +bool ShirrakFleeFocusFireTrigger::IsActive() +{ + if (!AI_VALUE2(Unit*, "find target", "shirrak the dead watcher")) + return false; + + std::list creatureList; + bot->GetCreatureListWithEntryInGrid(creatureList, static_cast(AuchenaiCryptsIDs::NPC_FOCUS_FIRE), 20.0f); + + for (Creature* flare : creatureList) + { + if (flare && flare->IsAlive()) + return true; + } + return false; +} + +bool ShirrakRangedKeepDistanceTrigger::IsActive() +{ + return botAI->IsRanged(bot) && + AI_VALUE2(Unit*, "find target", "shirrak the dead watcher"); +} diff --git a/src/Ai/Dungeon/AuchenaiCrypts/Trigger/AuchenaiCryptsTriggers.h b/src/Ai/Dungeon/AuchenaiCrypts/Trigger/AuchenaiCryptsTriggers.h new file mode 100644 index 000000000..1d3144194 --- /dev/null +++ b/src/Ai/Dungeon/AuchenaiCrypts/Trigger/AuchenaiCryptsTriggers.h @@ -0,0 +1,38 @@ +#ifndef _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSTRIGGERS_H +#define _PLAYERBOT_TBCDUNGEONAUCHENAICRYPTSTRIGGERS_H + +#include "Trigger.h" +#include "GenericTriggers.h" +#include "DungeonStrategyUtils.h" + +enum class AuchenaiCryptsIDs : uint32 +{ + // Shirrak The Dead Watcher + NPC_FOCUS_FIRE = 18374, +}; + +class ShirrakTankPositionBossTrigger : public Trigger +{ +public: + ShirrakTankPositionBossTrigger(PlayerbotAI* botAI) : Trigger(botAI, "shirrak tank position boss") {} + + bool IsActive() override; +}; + +class ShirrakFleeFocusFireTrigger : public Trigger +{ +public: + ShirrakFleeFocusFireTrigger(PlayerbotAI* botAI) : Trigger(botAI, "shirrak flee focus fire") {} + + bool IsActive() override; +}; + +class ShirrakRangedKeepDistanceTrigger : public Trigger +{ +public: + ShirrakRangedKeepDistanceTrigger(PlayerbotAI* botAI) : Trigger(botAI, "shirrak ranged keep distance") {} + + bool IsActive() override; +}; + +#endif diff --git a/src/Ai/Dungeon/DungeonStrategyContext.h b/src/Ai/Dungeon/DungeonStrategyContext.h index 3311aeee2..07e5fe505 100644 --- a/src/Ai/Dungeon/DungeonStrategyContext.h +++ b/src/Ai/Dungeon/DungeonStrategyContext.h @@ -2,6 +2,7 @@ #define _PLAYERBOT_DUNGEONSTRATEGYCONTEXT_H #include "Strategy.h" +#include "AuchenaiCrypts/Strategy/AuchenaiCryptsStrategy.h" #include "UtgardeKeep/Strategy/UtgardeKeepStrategy.h" #include "Nexus/Strategy/NexusStrategy.h" #include "AzjolNerub/Strategy/AzjolNerubStrategy.h" @@ -44,7 +45,7 @@ class DungeonStrategyContext : public NamedObjectContext // ... // Burning Crusade - // ... + creators["tbc-ac"] = &DungeonStrategyContext::tbc_ac; // Auchindoun: Auchenai Crypts // Wrath of the Lich King creators["wotlk-uk"] = &DungeonStrategyContext::wotlk_uk; // Utgarde Keep @@ -65,6 +66,7 @@ class DungeonStrategyContext : public NamedObjectContext creators["wotlk-fos"] = &DungeonStrategyContext::wotlk_fos; // The Forge of Souls } private: + static Strategy* tbc_ac(PlayerbotAI* botAI) { return new TbcDungeonAuchenaiCryptsStrategy(botAI); } static Strategy* wotlk_uk(PlayerbotAI* botAI) { return new WotlkDungeonUKStrategy(botAI); } static Strategy* wotlk_nex(PlayerbotAI* botAI) { return new WotlkDungeonNexStrategy(botAI); } static Strategy* wotlk_an(PlayerbotAI* botAI) { return new WotlkDungeonANStrategy(botAI); } diff --git a/src/Ai/Dungeon/TbcDungeonActionContext.h b/src/Ai/Dungeon/TbcDungeonActionContext.h new file mode 100644 index 000000000..8c3547224 --- /dev/null +++ b/src/Ai/Dungeon/TbcDungeonActionContext.h @@ -0,0 +1,6 @@ +#ifndef _PLAYERBOT_TBCDUNGEONACTIONCONTEXT_H +#define _PLAYERBOT_TBCDUNGEONACTIONCONTEXT_H + +#include "AuchenaiCrypts/AuchenaiCryptsActionContext.h" + +#endif diff --git a/src/Ai/Dungeon/TbcDungeonTriggerContext.h b/src/Ai/Dungeon/TbcDungeonTriggerContext.h new file mode 100644 index 000000000..9a680b7af --- /dev/null +++ b/src/Ai/Dungeon/TbcDungeonTriggerContext.h @@ -0,0 +1,6 @@ +#ifndef _PLAYERBOT_TBCDUNGEONTRIGGERCONTEXT_H +#define _PLAYERBOT_TBCDUNGEONTRIGGERCONTEXT_H + +#include "AuchenaiCrypts/AuchenaiCryptsTriggerContext.h" + +#endif diff --git a/src/Bot/Engine/BuildSharedActionContexts.cpp b/src/Bot/Engine/BuildSharedActionContexts.cpp index 8fbb6c135..7e243eadb 100644 --- a/src/Bot/Engine/BuildSharedActionContexts.cpp +++ b/src/Bot/Engine/BuildSharedActionContexts.cpp @@ -18,6 +18,7 @@ #include "Ai/Raid/Ulduar/RaidUlduarActionContext.h" #include "Ai/Raid/Onyxia/RaidOnyxiaActionContext.h" #include "Ai/Raid/Icecrown/RaidIccActionContext.h" +#include "Ai/Dungeon/TbcDungeonActionContext.h" #include "Ai/Dungeon/WotlkDungeonActionContext.h" void AiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& actionContexts) @@ -41,6 +42,7 @@ void AiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList& triggerContexts) @@ -41,6 +42,7 @@ void AiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList allInstanceStrategies = { "aq20", "bwl", "karazhan", "gruulslair", "icc", "magtheridon", "moltencore", - "naxx", "onyxia", "ssc", "tempestkeep", "ulduar", "voa", "wotlk-an", "wotlk-cos", + "naxx", "onyxia", "ssc", "tbc-ac", "tempestkeep", "ulduar", "voa", "wotlk-an", "wotlk-cos", "wotlk-dtk", "wotlk-eoe", "wotlk-fos", "wotlk-gd", "wotlk-hol", "wotlk-hor", "wotlk-hos", "wotlk-nex", "wotlk-occ", "wotlk-ok", "wotlk-os", "wotlk-pos", "wotlk-toc", "wotlk-uk", "wotlk-up", "wotlk-vh", "zulaman" @@ -1600,6 +1600,9 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster) case 550: strategyName = "tempestkeep"; // Tempest Keep break; + case 558: + strategyName = "tbc-ac"; // Auchindoun: Auchenai Crypts + break; case 565: strategyName = "gruulslair"; // Gruul's Lair break;