From 608f9d1a68882e91867fcf08bb37b659cfb88ef7 Mon Sep 17 00:00:00 2001 From: Bobblybook Date: Sun, 13 Oct 2024 21:21:40 +1100 Subject: [PATCH] Gundrak implementation EASY one for once --- src/strategy/AiObjectContext.cpp | 2 + .../dungeons/DungeonStrategyContext.h | 5 +-- .../wotlk/WotlkDungeonActionContext.h | 2 +- .../wotlk/WotlkDungeonTriggerContext.h | 2 +- .../wotlk/gundrak/GundrakActionContext.h | 20 +++++++++ .../dungeons/wotlk/gundrak/GundrakActions.cpp | 44 +++++++++++++++++++ .../dungeons/wotlk/gundrak/GundrakActions.h | 24 ++++++++++ .../wotlk/gundrak/GundrakMultipliers.cpp | 37 ++++++++++++++++ .../wotlk/gundrak/GundrakMultipliers.h | 24 ++++++++++ .../wotlk/gundrak/GundrakStrategy.cpp | 29 ++++++++++++ .../dungeons/wotlk/gundrak/GundrakStrategy.h | 18 ++++++++ .../wotlk/gundrak/GundrakTriggerContext.h | 21 +++++++++ .../wotlk/gundrak/GundrakTriggers.cpp | 18 ++++++++ .../dungeons/wotlk/gundrak/GundrakTriggers.h | 37 ++++++++++++++++ src/strategy/dungeons/wotlk/gundrak/TODO | 0 15 files changed, 278 insertions(+), 5 deletions(-) create mode 100644 src/strategy/dungeons/wotlk/gundrak/GundrakActionContext.h create mode 100644 src/strategy/dungeons/wotlk/gundrak/GundrakActions.cpp create mode 100644 src/strategy/dungeons/wotlk/gundrak/GundrakActions.h create mode 100644 src/strategy/dungeons/wotlk/gundrak/GundrakMultipliers.cpp create mode 100644 src/strategy/dungeons/wotlk/gundrak/GundrakMultipliers.h create mode 100644 src/strategy/dungeons/wotlk/gundrak/GundrakStrategy.cpp create mode 100644 src/strategy/dungeons/wotlk/gundrak/GundrakStrategy.h create mode 100644 src/strategy/dungeons/wotlk/gundrak/GundrakTriggerContext.h create mode 100644 src/strategy/dungeons/wotlk/gundrak/GundrakTriggers.cpp create mode 100644 src/strategy/dungeons/wotlk/gundrak/GundrakTriggers.h delete mode 100644 src/strategy/dungeons/wotlk/gundrak/TODO diff --git a/src/strategy/AiObjectContext.cpp b/src/strategy/AiObjectContext.cpp index d8b603ff..ddd9ea9c 100644 --- a/src/strategy/AiObjectContext.cpp +++ b/src/strategy/AiObjectContext.cpp @@ -56,6 +56,7 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) actionContexts.Add(new WotlkDungeonOKActionContext()); actionContexts.Add(new WotlkDungeonDTKActionContext()); actionContexts.Add(new WotlkDungeonVHActionContext()); + actionContexts.Add(new WotlkDungeonGDActionContext()); triggerContexts.Add(new TriggerContext()); triggerContexts.Add(new ChatTriggerContext()); @@ -72,6 +73,7 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) triggerContexts.Add(new WotlkDungeonOKTriggerContext()); triggerContexts.Add(new WotlkDungeonDTKTriggerContext()); triggerContexts.Add(new WotlkDungeonVHTriggerContext()); + triggerContexts.Add(new WotlkDungeonGDTriggerContext()); valueContexts.Add(new ValueContext()); diff --git a/src/strategy/dungeons/DungeonStrategyContext.h b/src/strategy/dungeons/DungeonStrategyContext.h index 8062e09b..523a601e 100644 --- a/src/strategy/dungeons/DungeonStrategyContext.h +++ b/src/strategy/dungeons/DungeonStrategyContext.h @@ -8,12 +8,11 @@ #include "wotlk/oldkingdom/OldKingdomStrategy.h" #include "wotlk/draktharonkeep/DrakTharonKeepStrategy.h" #include "wotlk/violethold/VioletHoldStrategy.h" +#include "wotlk/gundrak/GundrakStrategy.h" /* Full list/TODO: -Gundrak - GD -Slad'ran, Drakkari Colossus, Moorabi, Gal'darah, Eck the Ferocious (Heroic only) Halls of Stone - HoS Maiden of Grief, Krystallus, Tribunal of Ages, Sjonnir The Ironshaper Halls of Lightning - HoL @@ -76,8 +75,8 @@ class DungeonStrategyContext : public NamedObjectContext static Strategy* wotlk_ok(PlayerbotAI* botAI) { return new WotlkDungeonOKStrategy(botAI); } static Strategy* wotlk_dtk(PlayerbotAI* botAI) { return new WotlkDungeonDTKStrategy(botAI); } static Strategy* wotlk_vh(PlayerbotAI* botAI) { return new WotlkDungeonVHStrategy(botAI); } + static Strategy* wotlk_gd(PlayerbotAI* botAI) { return new WotlkDungeonGDStrategy(botAI); } - static Strategy* wotlk_gd(PlayerbotAI* botAI) { return new WotlkDungeonUKStrategy(botAI); } static Strategy* wotlk_hos(PlayerbotAI* botAI) { return new WotlkDungeonUKStrategy(botAI); } static Strategy* wotlk_hol(PlayerbotAI* botAI) { return new WotlkDungeonUKStrategy(botAI); } static Strategy* wotlk_occ(PlayerbotAI* botAI) { return new WotlkDungeonUKStrategy(botAI); } diff --git a/src/strategy/dungeons/wotlk/WotlkDungeonActionContext.h b/src/strategy/dungeons/wotlk/WotlkDungeonActionContext.h index 060a4e5c..91a87760 100644 --- a/src/strategy/dungeons/wotlk/WotlkDungeonActionContext.h +++ b/src/strategy/dungeons/wotlk/WotlkDungeonActionContext.h @@ -7,7 +7,7 @@ #include "oldkingdom/OldKingdomActionContext.h" #include "draktharonkeep/DrakTharonKeepActionContext.h" #include "violethold/VioletHoldActionContext.h" -// #include "gundrak/GundrakActionContext.h" +#include "gundrak/GundrakActionContext.h" // #include "hallsofstone/HallsOfStoneActionContext.h" // #include "hallsoflightning/HallsOfLightningActionContext.h" // #include "oculus/OculusActionContext.h" diff --git a/src/strategy/dungeons/wotlk/WotlkDungeonTriggerContext.h b/src/strategy/dungeons/wotlk/WotlkDungeonTriggerContext.h index 11097b06..31524e69 100644 --- a/src/strategy/dungeons/wotlk/WotlkDungeonTriggerContext.h +++ b/src/strategy/dungeons/wotlk/WotlkDungeonTriggerContext.h @@ -7,7 +7,7 @@ #include "oldkingdom/OldKingdomTriggerContext.h" #include "draktharonkeep/DrakTharonKeepTriggerContext.h" #include "violethold/VioletHoldTriggerContext.h" -// #include "gundrak/GundrakTriggerContext.h" +#include "gundrak/GundrakTriggerContext.h" // #include "hallsofstone/HallsOfStoneTriggerContext.h" // #include "hallsoflightning/HallsOfLightningTriggerContext.h" // #include "oculus/OculusTriggerContext.h" diff --git a/src/strategy/dungeons/wotlk/gundrak/GundrakActionContext.h b/src/strategy/dungeons/wotlk/gundrak/GundrakActionContext.h new file mode 100644 index 00000000..bbece7ef --- /dev/null +++ b/src/strategy/dungeons/wotlk/gundrak/GundrakActionContext.h @@ -0,0 +1,20 @@ +#ifndef _PLAYERBOT_WOTLKDUNGEONGDACTIONCONTEXT_H +#define _PLAYERBOT_WOTLKDUNGEONGDACTIONCONTEXT_H + +#include "Action.h" +#include "NamedObjectContext.h" +#include "GundrakActions.h" + +class WotlkDungeonGDActionContext : public NamedObjectContext +{ + public: + WotlkDungeonGDActionContext() { + creators["avoid poison nova"] = &WotlkDungeonGDActionContext::avoid_poison_nova; + creators["avoid whirling slash"] = &WotlkDungeonGDActionContext::avoid_whirling_slash; + } + private: + static Action* avoid_poison_nova(PlayerbotAI* ai) { return new AvoidPoisonNovaAction(ai); } + static Action* avoid_whirling_slash(PlayerbotAI* ai) { return new AvoidWhirlingSlashAction(ai); } +}; + +#endif diff --git a/src/strategy/dungeons/wotlk/gundrak/GundrakActions.cpp b/src/strategy/dungeons/wotlk/gundrak/GundrakActions.cpp new file mode 100644 index 00000000..122c47a1 --- /dev/null +++ b/src/strategy/dungeons/wotlk/gundrak/GundrakActions.cpp @@ -0,0 +1,44 @@ +#include "Playerbots.h" +#include "GundrakActions.h" +#include "GundrakStrategy.h" + +bool AvoidPoisonNovaAction::Execute(Event event) +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "slad'ran"); + if (!boss) { return false; } + + float distance = bot->GetExactDist2d(boss->GetPosition()); + float radius = 15.0f; + float distanceExtra = 2.0f; + + if (distance < radius + distanceExtra) + { + return MoveAway(boss, radius + distanceExtra - distance); + } + + return false; +} + +bool AvoidWhirlingSlashAction::Execute(Event event) +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "gal'darah"); + if (!boss) { return false; } + + float distance = bot->GetExactDist2d(boss->GetPosition()); + float radius = 5.0f; + float distanceExtra = 2.0f; + + if (distance < radius + distanceExtra) + { + if (botAI->IsTank(bot)) + { + // The boss chases tank during this, leads to jittery stutter-stepping + // by the tank if we don't pre-move additional range. 2*radius seems ok + return MoveAway(boss, (2.0f * radius) + distanceExtra - distance); + } + // else + return MoveAway(boss, radius + distanceExtra - distance); + } + + return false; +} diff --git a/src/strategy/dungeons/wotlk/gundrak/GundrakActions.h b/src/strategy/dungeons/wotlk/gundrak/GundrakActions.h new file mode 100644 index 00000000..e163248b --- /dev/null +++ b/src/strategy/dungeons/wotlk/gundrak/GundrakActions.h @@ -0,0 +1,24 @@ +#ifndef _PLAYERBOT_WOTLKDUNGEONGDACTIONS_H +#define _PLAYERBOT_WOTLKDUNGEONGDACTIONS_H + +#include "Action.h" +#include "AttackAction.h" +#include "PlayerbotAI.h" +#include "Playerbots.h" +#include "GundrakTriggers.h" + +class AvoidPoisonNovaAction : public MovementAction +{ +public: + AvoidPoisonNovaAction(PlayerbotAI* ai) : MovementAction(ai, "avoid poison nova") {} + bool Execute(Event event) override; +}; + +class AvoidWhirlingSlashAction : public MovementAction +{ +public: + AvoidWhirlingSlashAction(PlayerbotAI* ai) : MovementAction(ai, "avoid whirling slash") {} + bool Execute(Event event) override; +}; + +#endif diff --git a/src/strategy/dungeons/wotlk/gundrak/GundrakMultipliers.cpp b/src/strategy/dungeons/wotlk/gundrak/GundrakMultipliers.cpp new file mode 100644 index 00000000..a484a593 --- /dev/null +++ b/src/strategy/dungeons/wotlk/gundrak/GundrakMultipliers.cpp @@ -0,0 +1,37 @@ +#include "GundrakMultipliers.h" +#include "GundrakActions.h" +#include "GenericSpellActions.h" +#include "ChooseTargetActions.h" +#include "MovementActions.h" +#include "GundrakTriggers.h" +#include "Action.h" + +float SladranMultiplier::GetValue(Action* action) +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "slad'ran"); + if (!boss) { return 1.0f; } + + if (boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(SPELL_POISON_NOVA)) + { + if (dynamic_cast(action) && !dynamic_cast(action)) + { + return 0.0f; + } + } + return 1.0f; +} + +float GaldarahMultiplier::GetValue(Action* action) +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "gal'darah"); + if (!boss) { return 1.0f; } + + if (boss->HasAura(SPELL_WHIRLING_SLASH)) + { + if (dynamic_cast(action) && !dynamic_cast(action)) + { + return 0.0f; + } + } + return 1.0f; +} diff --git a/src/strategy/dungeons/wotlk/gundrak/GundrakMultipliers.h b/src/strategy/dungeons/wotlk/gundrak/GundrakMultipliers.h new file mode 100644 index 00000000..e1ceb0b6 --- /dev/null +++ b/src/strategy/dungeons/wotlk/gundrak/GundrakMultipliers.h @@ -0,0 +1,24 @@ +#ifndef _PLAYERBOT_WOTLKDUNGEONGDMULTIPLIERS_H +#define _PLAYERBOT_WOTLKDUNGEONGDMULTIPLIERS_H + +#include "Multiplier.h" + +class SladranMultiplier : public Multiplier +{ + public: + SladranMultiplier(PlayerbotAI* ai) : Multiplier(ai, "slad'ran") {} + + public: + virtual float GetValue(Action* action); +}; + +class GaldarahMultiplier : public Multiplier +{ + public: + GaldarahMultiplier(PlayerbotAI* ai) : Multiplier(ai, "gal'darah") {} + + public: + virtual float GetValue(Action* action); +}; + +#endif diff --git a/src/strategy/dungeons/wotlk/gundrak/GundrakStrategy.cpp b/src/strategy/dungeons/wotlk/gundrak/GundrakStrategy.cpp new file mode 100644 index 00000000..5c29bd21 --- /dev/null +++ b/src/strategy/dungeons/wotlk/gundrak/GundrakStrategy.cpp @@ -0,0 +1,29 @@ +#include "GundrakStrategy.h" +#include "GundrakMultipliers.h" + + +void WotlkDungeonGDStrategy::InitTriggers(std::vector &triggers) +{ + // Moorabi + + // Drakkari Colossus + + // Slad'ran + // TODO: Might need to add target priority for heroic on the snakes or to burn down boss. + // Will re-test in heroic, decent dps groups should be able to blast him down with no funky strats. + triggers.push_back(new TriggerNode("poison nova", + NextAction::array(0, new NextAction("avoid poison nova", ACTION_RAID + 5), nullptr))); + + // Gal'darah + triggers.push_back(new TriggerNode("whirling slash", + NextAction::array(0, new NextAction("avoid whirling slash", ACTION_RAID + 5), nullptr))); + + // Eck the Ferocious (Heroic only) + // TODO +} + +void WotlkDungeonGDStrategy::InitMultipliers(std::vector &multipliers) +{ + multipliers.push_back(new SladranMultiplier(botAI)); + multipliers.push_back(new GaldarahMultiplier(botAI)); +} diff --git a/src/strategy/dungeons/wotlk/gundrak/GundrakStrategy.h b/src/strategy/dungeons/wotlk/gundrak/GundrakStrategy.h new file mode 100644 index 00000000..c7910c1c --- /dev/null +++ b/src/strategy/dungeons/wotlk/gundrak/GundrakStrategy.h @@ -0,0 +1,18 @@ +#ifndef _PLAYERBOT_WOTLKDUNGEONGDSTRATEGY_H +#define _PLAYERBOT_WOTLKDUNGEONGDSTRATEGY_H + +#include "Multiplier.h" +#include "AiObjectContext.h" +#include "Strategy.h" + + +class WotlkDungeonGDStrategy : public Strategy +{ +public: + WotlkDungeonGDStrategy(PlayerbotAI* ai) : Strategy(ai) {} + virtual std::string const getName() override { return "gundrak"; } + virtual void InitTriggers(std::vector &triggers) override; + virtual void InitMultipliers(std::vector &multipliers) override; +}; + +#endif diff --git a/src/strategy/dungeons/wotlk/gundrak/GundrakTriggerContext.h b/src/strategy/dungeons/wotlk/gundrak/GundrakTriggerContext.h new file mode 100644 index 00000000..fc744d1d --- /dev/null +++ b/src/strategy/dungeons/wotlk/gundrak/GundrakTriggerContext.h @@ -0,0 +1,21 @@ +#ifndef _PLAYERBOT_WOTLKDUNGEONGDTRIGGERCONTEXT_H +#define _PLAYERBOT_WOTLKDUNGEONGDTRIGGERCONTEXT_H + +#include "NamedObjectContext.h" +#include "AiObjectContext.h" +#include "GundrakTriggers.h" + +class WotlkDungeonGDTriggerContext : public NamedObjectContext +{ + public: + WotlkDungeonGDTriggerContext() + { + creators["poison nova"] = &WotlkDungeonGDTriggerContext::poison_nova; + creators["whirling slash"] = &WotlkDungeonGDTriggerContext::whirling_slash; + } + private: + static Trigger* poison_nova(PlayerbotAI* ai) { return new SladranPoisonNovaTrigger(ai); } + static Trigger* whirling_slash(PlayerbotAI* ai) { return new GaldarahWhirlingSlashTrigger(ai); } +}; + +#endif diff --git a/src/strategy/dungeons/wotlk/gundrak/GundrakTriggers.cpp b/src/strategy/dungeons/wotlk/gundrak/GundrakTriggers.cpp new file mode 100644 index 00000000..875b41dd --- /dev/null +++ b/src/strategy/dungeons/wotlk/gundrak/GundrakTriggers.cpp @@ -0,0 +1,18 @@ +#include "Playerbots.h" +#include "GundrakTriggers.h" +#include "AiObject.h" +#include "AiObjectContext.h" + +bool SladranPoisonNovaTrigger::IsActive() +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "slad'ran"); + if (!boss) { return false; } + + return boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(SPELL_POISON_NOVA); +} + +bool GaldarahWhirlingSlashTrigger::IsActive() +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "gal'darah"); + return boss && boss->HasAura(SPELL_WHIRLING_SLASH); +} diff --git a/src/strategy/dungeons/wotlk/gundrak/GundrakTriggers.h b/src/strategy/dungeons/wotlk/gundrak/GundrakTriggers.h new file mode 100644 index 00000000..4b2245bc --- /dev/null +++ b/src/strategy/dungeons/wotlk/gundrak/GundrakTriggers.h @@ -0,0 +1,37 @@ +#ifndef _PLAYERBOT_WOTLKDUNGEONGDTRIGGERS_H +#define _PLAYERBOT_WOTLKDUNGEONGDTRIGGERS_H + +#include "Trigger.h" +#include "PlayerbotAIConfig.h" +#include "GenericTriggers.h" +#include "DungeonStrategyUtils.h" + +enum GundrakIDs +{ + // Slad'ran + SPELL_POISON_NOVA_N = 55081, + SPELL_POISON_NOVA_H = 59842, + + // Gal'darah + SPELL_WHIRLING_SLASH_N = 55250, + SPELL_WHIRLING_SLASH_H = 59824, +}; + +#define SPELL_POISON_NOVA DUNGEON_MODE(bot, SPELL_POISON_NOVA_N, SPELL_POISON_NOVA_H) +#define SPELL_WHIRLING_SLASH DUNGEON_MODE(bot, SPELL_WHIRLING_SLASH_N, SPELL_WHIRLING_SLASH_H) + +class SladranPoisonNovaTrigger : public Trigger +{ +public: + SladranPoisonNovaTrigger(PlayerbotAI* ai) : Trigger(ai, "slad'ran poison nova") {} + bool IsActive() override; +}; + +class GaldarahWhirlingSlashTrigger : public Trigger +{ +public: + GaldarahWhirlingSlashTrigger(PlayerbotAI* ai) : Trigger(ai, "gal'darah whirling slash") {} + bool IsActive() override; +}; + +#endif diff --git a/src/strategy/dungeons/wotlk/gundrak/TODO b/src/strategy/dungeons/wotlk/gundrak/TODO deleted file mode 100644 index e69de29b..00000000