From feb7bb8a8b9aa98165f825ea330883f9cb936f9e Mon Sep 17 00:00:00 2001 From: kadeshar Date: Tue, 25 Mar 2025 13:28:53 +0100 Subject: [PATCH] Added Vault of Archavon strategy with Emalon tactics (#1117) --- src/PlayerbotAI.cpp | 7 +- src/strategy/AiObjectContext.cpp | 4 + src/strategy/raids/RaidStrategyContext.h | 3 + .../vaultofarchavon/RaidVoAActionContext.h | 32 +++ .../raids/vaultofarchavon/RaidVoAActions.cpp | 187 ++++++++++++++++++ .../raids/vaultofarchavon/RaidVoAActions.h | 45 +++++ .../raids/vaultofarchavon/RaidVoAStrategy.cpp | 27 +++ .../raids/vaultofarchavon/RaidVoAStrategy.h | 19 ++ .../vaultofarchavon/RaidVoATriggerContext.h | 31 +++ .../raids/vaultofarchavon/RaidVoATriggers.cpp | 137 +++++++++++++ .../raids/vaultofarchavon/RaidVoATriggers.h | 50 +++++ 11 files changed, 540 insertions(+), 2 deletions(-) create mode 100644 src/strategy/raids/vaultofarchavon/RaidVoAActionContext.h create mode 100644 src/strategy/raids/vaultofarchavon/RaidVoAActions.cpp create mode 100644 src/strategy/raids/vaultofarchavon/RaidVoAActions.h create mode 100644 src/strategy/raids/vaultofarchavon/RaidVoAStrategy.cpp create mode 100644 src/strategy/raids/vaultofarchavon/RaidVoAStrategy.h create mode 100644 src/strategy/raids/vaultofarchavon/RaidVoATriggerContext.h create mode 100644 src/strategy/raids/vaultofarchavon/RaidVoATriggers.cpp create mode 100644 src/strategy/raids/vaultofarchavon/RaidVoATriggers.h diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 8c154b10..150e3d75 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -1534,7 +1534,7 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster) strategyName = "wotlk-hol"; // Halls of Lightning break; case 603: - strategyName = "uld"; + strategyName = "uld"; // Ulduar break; case 604: strategyName = "wotlk-gd"; // Gundrak @@ -1551,8 +1551,11 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster) case 619: strategyName = "wotlk-ok"; // Ahn'kahet: The Old Kingdom break; + case 624: + strategyName = "voa"; // Vault of Archavon + break; case 631: - strategyName = "icc"; + strategyName = "icc"; // Icecrown Citadel break; case 632: strategyName = "wotlk-fos"; // The Forge of Souls diff --git a/src/strategy/AiObjectContext.cpp b/src/strategy/AiObjectContext.cpp index 12e741b6..52e7a247 100644 --- a/src/strategy/AiObjectContext.cpp +++ b/src/strategy/AiObjectContext.cpp @@ -27,6 +27,8 @@ #include "raids/obsidiansanctum/RaidOsActionContext.h" #include "raids/obsidiansanctum/RaidOsTriggerContext.h" #include "raids/eyeofeternity/RaidEoEActionContext.h" +#include "raids/vaultofarchavon/RaidVoATriggerContext.h" +#include "raids/vaultofarchavon/RaidVoAActionContext.h" #include "raids/eyeofeternity/RaidEoETriggerContext.h" #include "raids/moltencore/RaidMcActionContext.h" #include "raids/moltencore/RaidMcTriggerContext.h" @@ -54,6 +56,7 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) actionContexts.Add(new RaidNaxxActionContext()); actionContexts.Add(new RaidOsActionContext()); actionContexts.Add(new RaidEoEActionContext()); + actionContexts.Add(new RaidVoAActionContext()); actionContexts.Add(new RaidUlduarActionContext()); actionContexts.Add(new RaidIccActionContext()); actionContexts.Add(new WotlkDungeonUKActionContext()); @@ -79,6 +82,7 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) triggerContexts.Add(new RaidNaxxTriggerContext()); triggerContexts.Add(new RaidOsTriggerContext()); triggerContexts.Add(new RaidEoETriggerContext()); + triggerContexts.Add(new RaidVoATriggerContext()); triggerContexts.Add(new RaidUlduarTriggerContext()); triggerContexts.Add(new RaidIccTriggerContext()); triggerContexts.Add(new WotlkDungeonUKTriggerContext()); diff --git a/src/strategy/raids/RaidStrategyContext.h b/src/strategy/raids/RaidStrategyContext.h index d863aa0a..1b0cf49e 100644 --- a/src/strategy/raids/RaidStrategyContext.h +++ b/src/strategy/raids/RaidStrategyContext.h @@ -10,6 +10,7 @@ #include "RaidMcStrategy.h" #include "RaidAq20Strategy.h" #include "RaidIccStrategy.h" +#include "RaidVoAStrategy.h" class RaidStrategyContext : public NamedObjectContext { @@ -25,6 +26,7 @@ public: creators["naxx"] = &RaidStrategyContext::naxx; creators["wotlk-os"] = &RaidStrategyContext::wotlk_os; creators["wotlk-eoe"] = &RaidStrategyContext::wotlk_eoe; + creators["voa"] = &RaidStrategyContext::voa; creators["uld"] = &RaidStrategyContext::uld; creators["icc"] = &RaidStrategyContext::icc; } @@ -36,6 +38,7 @@ private: static Strategy* naxx(PlayerbotAI* botAI) { return new RaidNaxxStrategy(botAI); } static Strategy* wotlk_os(PlayerbotAI* botAI) { return new RaidOsStrategy(botAI); } static Strategy* wotlk_eoe(PlayerbotAI* botAI) { return new RaidEoEStrategy(botAI); } + static Strategy* voa(PlayerbotAI* botAI) { return new RaidVoAStrategy(botAI); } static Strategy* uld(PlayerbotAI* botAI) { return new RaidUlduarStrategy(botAI); } static Strategy* icc(PlayerbotAI* botAI) { return new RaidIccStrategy(botAI); } }; diff --git a/src/strategy/raids/vaultofarchavon/RaidVoAActionContext.h b/src/strategy/raids/vaultofarchavon/RaidVoAActionContext.h new file mode 100644 index 00000000..b2ac1fbd --- /dev/null +++ b/src/strategy/raids/vaultofarchavon/RaidVoAActionContext.h @@ -0,0 +1,32 @@ +// /* +// * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license, you may redistribute it +// and/or modify it under version 2 of the License, or (at your option), any later version. +// */ + +#ifndef _PLAYERBOT_RAIDVOAACTIONCONTEXT_H +#define _PLAYERBOT_RAIDVOAACTIONCONTEXT_H + +#include "Action.h" +#include "NamedObjectContext.h" +#include "RaidVoAActions.h" +#include "PlayerbotAI.h" + +class RaidVoAActionContext : public NamedObjectContext +{ +public: + RaidVoAActionContext() + { + creators["emalon mark boss action"] = &RaidVoAActionContext::emalon_mark_boss_action; + creators["emalon lighting nova action"] = &RaidVoAActionContext::emalon_lighting_nova_action; + creators["emalon overcharge action"] = &RaidVoAActionContext::emalon_overcharge_action; + creators["emalon fall from floor action"] = &RaidVoAActionContext::emalon_fall_from_floor_action; + } + +private: + static Action* emalon_mark_boss_action(PlayerbotAI* ai) { return new EmalonMarkBossAction(ai); } + static Action* emalon_lighting_nova_action(PlayerbotAI* ai) { return new EmalonLightingNovaAction(ai); } + static Action* emalon_overcharge_action(PlayerbotAI* ai) { return new EmalonOverchargeAction(ai); } + static Action* emalon_fall_from_floor_action(PlayerbotAI* ai) { return new EmalonFallFromFloorAction(ai); } +}; + +#endif diff --git a/src/strategy/raids/vaultofarchavon/RaidVoAActions.cpp b/src/strategy/raids/vaultofarchavon/RaidVoAActions.cpp new file mode 100644 index 00000000..05d6328e --- /dev/null +++ b/src/strategy/raids/vaultofarchavon/RaidVoAActions.cpp @@ -0,0 +1,187 @@ +#include "RaidVoAActions.h" +#include "RaidVoATriggers.h" +#include "Define.h" +#include "Event.h" +#include "Group.h" +#include "ObjectGuid.h" +#include "Player.h" +#include "Playerbots.h" +#include "Unit.h" + +const Position VOA_EMALON_RESTORE_POSITION = Position(-221.8f, -243.8f, 96.8f, 4.7f); + +bool EmalonMarkBossAction::Execute(Event event) +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "emalon the storm watcher"); + if (!boss || !boss->IsAlive()) + { + return false; + } + + bool isMainTank = botAI->IsMainTank(bot); + Unit* mainTankUnit = AI_VALUE(Unit*, "main tank"); + Player* mainTank = mainTankUnit ? mainTankUnit->ToPlayer() : nullptr; + + if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a real player + { + // Iterate through the first 3 bot tanks to assign the Skull marker + for (int i = 0; i < 3; ++i) + { + if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank + { + Group* group = bot->GetGroup(); + if (group && boss) + { + int8 skullIndex = 7; // Skull + ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex); + + // If there's no skull set yet, or the skull is on a different target, set boss + if (!currentSkullTarget || (boss->GetGUID() != currentSkullTarget)) + { + group->SetTargetIcon(skullIndex, bot->GetGUID(), boss->GetGUID()); + return true; + } + } + break; // Stop after finding the first valid bot tank + } + } + } + else if (isMainTank) // Bot is the main tank + { + Group* group = bot->GetGroup(); + if (group) + { + int8 skullIndex = 7; // Skull + ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex); + + // If there's no skull set yet, or the skull is on a different target, set the Eonar's Gift + if (!currentSkullTarget || (boss->GetGUID() != currentSkullTarget)) + { + group->SetTargetIcon(skullIndex, bot->GetGUID(), boss->GetGUID()); + return true; + } + } + } + + return false; +} + +bool EmalonMarkBossAction::isUseful() +{ + EmalonMarkBossTrigger emalonMarkBossTrigger(botAI); + return emalonMarkBossTrigger.IsActive(); +} + +bool EmalonLightingNovaAction::Execute(Event event) +{ + const float radius = 25.0f; // 20 yards + 5 yard for safety for 10 man. For 25man there is no maximum range but 25 yards should be ok + + Unit* boss = AI_VALUE2(Unit*, "find target", "emalon the storm watcher"); + if (!boss) + return false; + + float currentDistance = bot->GetDistance2d(boss); + + if (currentDistance < radius) + { + return MoveAway(boss, radius - currentDistance); + } + + return false; +} + +bool EmalonLightingNovaAction::isUseful() +{ + EmalonLightingNovaTrigger emalonLightingNovaTrigger(botAI); + return emalonLightingNovaTrigger.IsActive(); +} + +bool EmalonOverchargeAction::Execute(Event event) +{ + // Check if there is any overcharged minion + Unit* minion = nullptr; + GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); + for (auto& npc : npcs) + { + Unit* unit = botAI->GetUnit(npc); + if (!unit) + continue; + + uint32 entry = unit->GetEntry(); + if (entry == NPC_TEMPEST_MINION && unit->HasAura(AURA_OVERCHARGE)) + { + minion = unit; + break; + } + } + if (!minion) + { + return false; + } + + bool isMainTank = botAI->IsMainTank(bot); + Unit* mainTankUnit = AI_VALUE(Unit*, "main tank"); + Player* mainTank = mainTankUnit ? mainTankUnit->ToPlayer() : nullptr; + + if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a real player + { + // Iterate through the first 3 bot tanks to assign the Skull marker + for (int i = 0; i < 3; ++i) + { + if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank + { + Group* group = bot->GetGroup(); + if (group && minion) + { + int8 skullIndex = 7; // Skull + ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex); + + // If there's no skull set yet, or the skull is on a different target, set Tempest Minion + if (!currentSkullTarget || (minion->GetGUID() != currentSkullTarget)) + { + group->SetTargetIcon(skullIndex, bot->GetGUID(), minion->GetGUID()); + return true; + } + } + break; // Stop after finding the first valid bot tank + } + } + } + else if (isMainTank) // Bot is the main tank + { + Group* group = bot->GetGroup(); + if (group) + { + int8 skullIndex = 7; // Skull + ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex); + + // If there's no skull set yet, or the skull is on a different target, set the Eonar's Gift + if (!currentSkullTarget || (minion->GetGUID() != currentSkullTarget)) + { + group->SetTargetIcon(skullIndex, bot->GetGUID(), minion->GetGUID()); + return true; + } + } + } + + return false; +} + +bool EmalonOverchargeAction::isUseful() +{ + EmalonOverchargeTrigger emalonOverchargeTrigger(botAI); + return emalonOverchargeTrigger.IsActive(); +} + +bool EmalonFallFromFloorAction::Execute(Event event) +{ + return bot->TeleportTo(bot->GetMapId(), VOA_EMALON_RESTORE_POSITION.GetPositionX(), + VOA_EMALON_RESTORE_POSITION.GetPositionY(), VOA_EMALON_RESTORE_POSITION.GetPositionZ(), + VOA_EMALON_RESTORE_POSITION.GetOrientation()); +} + +bool EmalonFallFromFloorAction::isUseful() +{ + EmalonFallFromFloorTrigger emalonFallFromFloorTrigger(botAI); + return emalonFallFromFloorTrigger.IsActive(); +} diff --git a/src/strategy/raids/vaultofarchavon/RaidVoAActions.h b/src/strategy/raids/vaultofarchavon/RaidVoAActions.h new file mode 100644 index 00000000..7aa72a23 --- /dev/null +++ b/src/strategy/raids/vaultofarchavon/RaidVoAActions.h @@ -0,0 +1,45 @@ +#ifndef _PLAYERBOT_RAIDVOAACTIONS_H +#define _PLAYERBOT_RAIDVOAACTIONS_H + +#include "Action.h" +#include "MovementActions.h" +#include "PlayerbotAI.h" +#include "Event.h" + +// +// Emalon the Storm Watcher +// + +class EmalonMarkBossAction : public MovementAction +{ +public: + EmalonMarkBossAction(PlayerbotAI* botAI) : MovementAction(botAI, "emalon mark boss action") {} + bool Execute(Event event) override; + bool isUseful() override; +}; + +class EmalonLightingNovaAction : public MovementAction +{ +public: + EmalonLightingNovaAction(PlayerbotAI* botAI) : MovementAction(botAI, "emalon lighting nova action") {} + bool Execute(Event event) override; + bool isUseful() override; +}; + +class EmalonOverchargeAction : public Action +{ +public: + EmalonOverchargeAction(PlayerbotAI* botAI) : Action(botAI, "emalon overcharge action") {} + bool Execute(Event event) override; + bool isUseful() override; +}; + +class EmalonFallFromFloorAction : public Action +{ +public: + EmalonFallFromFloorAction(PlayerbotAI* botAI) : Action(botAI, "emalon fall from floor action") {} + bool Execute(Event event) override; + bool isUseful() override; +}; + +#endif diff --git a/src/strategy/raids/vaultofarchavon/RaidVoAStrategy.cpp b/src/strategy/raids/vaultofarchavon/RaidVoAStrategy.cpp new file mode 100644 index 00000000..36469698 --- /dev/null +++ b/src/strategy/raids/vaultofarchavon/RaidVoAStrategy.cpp @@ -0,0 +1,27 @@ +#include "RaidVoAStrategy.h" +#include "Action.h" +#include "Strategy.h" +#include "Trigger.h" +#include "vector" + +void RaidVoAStrategy::InitTriggers(std::vector& triggers) +{ + // + // Emalon the Storm Watcher + // + triggers.push_back(new TriggerNode( + "emalon lighting nova trigger", + NextAction::array(0, new NextAction("emalon lighting nova action", ACTION_RAID + 1), nullptr))); + + triggers.push_back(new TriggerNode( + "emalon mark boss trigger", + NextAction::array(0, new NextAction("emalon mark boss action", ACTION_RAID), nullptr))); + + triggers.push_back(new TriggerNode( + "emalon overcharge trigger", + NextAction::array(0, new NextAction("emalon overcharge action", ACTION_RAID), nullptr))); + + triggers.push_back(new TriggerNode( + "emalon fall from floor trigger", + NextAction::array(0, new NextAction("emalon fall from floor action", ACTION_RAID), nullptr))); +} diff --git a/src/strategy/raids/vaultofarchavon/RaidVoAStrategy.h b/src/strategy/raids/vaultofarchavon/RaidVoAStrategy.h new file mode 100644 index 00000000..04ed2ac3 --- /dev/null +++ b/src/strategy/raids/vaultofarchavon/RaidVoAStrategy.h @@ -0,0 +1,19 @@ + +#ifndef _PLAYERBOT_RAIDVOASTRATEGY_H +#define _PLAYERBOT_RAIDVOASTRATEGY_H + +#include "Strategy.h" +#include "PlayerbotAI.h" +#include "string" +#include "Trigger.h" +#include "vector" + +class RaidVoAStrategy : public Strategy +{ +public: + RaidVoAStrategy(PlayerbotAI* ai) : Strategy(ai) {} + virtual std::string const getName() override { return "voa"; } + virtual void InitTriggers(std::vector& triggers) override; +}; + +#endif diff --git a/src/strategy/raids/vaultofarchavon/RaidVoATriggerContext.h b/src/strategy/raids/vaultofarchavon/RaidVoATriggerContext.h new file mode 100644 index 00000000..ee32c7fb --- /dev/null +++ b/src/strategy/raids/vaultofarchavon/RaidVoATriggerContext.h @@ -0,0 +1,31 @@ +// /* +// * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license, you may redistribute it +// and/or modify it under version 2 of the License, or (at your option), any later version. +// */ + +#ifndef _PLAYERBOT_RAIDVOATRIGGERCONTEXT_H +#define _PLAYERBOT_RAIDVOATRIGGERCONTEXT_H + +#include "AiObjectContext.h" +#include "NamedObjectContext.h" +#include "RaidVoATriggers.h" + +class RaidVoATriggerContext : public NamedObjectContext +{ +public: + RaidVoATriggerContext() + { + creators["emalon mark boss trigger"] = &RaidVoATriggerContext::emalon_mark_boss_trigger; + creators["emalon lighting nova trigger"] = &RaidVoATriggerContext::emalon_lighting_nova_trigger; + creators["emalon overcharge trigger"] = &RaidVoATriggerContext::emalon_overcharge_trigger; + creators["emalon fall from floor trigger"] = &RaidVoATriggerContext::emalon_fall_from_floor_trigger; + } + +private: + static Trigger* emalon_mark_boss_trigger(PlayerbotAI* ai) { return new EmalonMarkBossTrigger(ai); } + static Trigger* emalon_lighting_nova_trigger(PlayerbotAI* ai) { return new EmalonLightingNovaTrigger(ai); } + static Trigger* emalon_overcharge_trigger(PlayerbotAI* ai) { return new EmalonOverchargeTrigger(ai); } + static Trigger* emalon_fall_from_floor_trigger(PlayerbotAI* ai) { return new EmalonFallFromFloorTrigger(ai); } +}; + +#endif diff --git a/src/strategy/raids/vaultofarchavon/RaidVoATriggers.cpp b/src/strategy/raids/vaultofarchavon/RaidVoATriggers.cpp new file mode 100644 index 00000000..03a8b9b3 --- /dev/null +++ b/src/strategy/raids/vaultofarchavon/RaidVoATriggers.cpp @@ -0,0 +1,137 @@ +#include "RaidVoATriggers.h" + +#include "EventMap.h" +#include "Object.h" +#include "PlayerbotAI.h" +#include "Playerbots.h" + +bool EmalonMarkBossTrigger::IsActive() +{ + // Only tank bot can mark target + if (!botAI->IsTank(bot)) + { + return false; + } + + // Check boss and it is alive + Unit* boss = AI_VALUE2(Unit*, "find target", "emalon the storm watcher"); + if (!boss || !boss->IsAlive()) + { + return false; + } + + // Check if boss have skull mark + Group* group = bot->GetGroup(); + int8 skullIndex = 7; // Skull + ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex); + if (currentSkullTarget == boss->GetGUID()) + { + return false; + } + + // Check if there is any overcharged minion + Unit* overchargedMinion = nullptr; + GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); + for (auto& npc : npcs) + { + Unit* unit = botAI->GetUnit(npc); + if (!unit) + continue; + + uint32 entry = unit->GetEntry(); + if (entry == NPC_TEMPEST_MINION && unit->HasAura(AURA_OVERCHARGE)) + { + overchargedMinion = unit; + break; + } + } + if (overchargedMinion) + { + return false; + } + + return true; +} + +bool EmalonLightingNovaTrigger::IsActive() +{ + // Check boss and it is alive + Unit* boss = AI_VALUE2(Unit*, "find target", "emalon the storm watcher"); + if (!boss || !boss->IsAlive()) + { + return false; + } + + // Tank dont need to move + if (botAI->IsTank(bot)) + { + return false; + } + + // Check if boss is casting Lightning Nova + bool isCasting = boss->HasUnitState(UNIT_STATE_CASTING); + bool isLightingNova = boss->FindCurrentSpellBySpellId(SPELL_LIGHTNING_NOVA_10_MAN) || + boss->FindCurrentSpellBySpellId(SPELL_LIGHTNING_NOVA_25_MAN); + return isCasting && isLightingNova; +} + +bool EmalonOverchargeTrigger::IsActive() +{ + // Only tank bot can mark target + if (!botAI->IsTank(bot)) + { + return false; + } + + // Check boss and it is alive + Unit* boss = AI_VALUE2(Unit*, "find target", "emalon the storm watcher"); + if (!boss || !boss->IsAlive()) + { + return false; + } + + // Check if there is any overcharged minion + Unit* overchargedMinion = nullptr; + GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs"); + for (auto& npc : npcs) + { + Unit* unit = botAI->GetUnit(npc); + if (!unit) + continue; + + uint32 entry = unit->GetEntry(); + if (entry == NPC_TEMPEST_MINION && unit->HasAura(AURA_OVERCHARGE)) + { + overchargedMinion = unit; + break; + } + } + if (!overchargedMinion) + { + return false; + } + + // Check if minion have skull mark + Group* group = bot->GetGroup(); + int8 skullIndex = 7; // Skull + ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex); + if (currentSkullTarget == overchargedMinion->GetGUID()) + { + return false; + } + + return true; +} + +bool EmalonFallFromFloorTrigger::IsActive() +{ + // Check boss and it is alive + Unit* boss = AI_VALUE2(Unit*, "find target", "emalon the storm watcher"); + if (!boss || !boss->IsAlive()) + { + return false; + } + + // Check if bot is on the floor + return bot->GetPositionZ() < 80.0f; +} diff --git a/src/strategy/raids/vaultofarchavon/RaidVoATriggers.h b/src/strategy/raids/vaultofarchavon/RaidVoATriggers.h new file mode 100644 index 00000000..e952b235 --- /dev/null +++ b/src/strategy/raids/vaultofarchavon/RaidVoATriggers.h @@ -0,0 +1,50 @@ +#ifndef _PLAYERBOT_RAIDVOATRIGGERS_H +#define _PLAYERBOT_RAIDVOATRIGGERS_H + +#include "EventMap.h" +#include "GenericTriggers.h" +#include "PlayerbotAIConfig.h" +#include "Trigger.h" + +enum VoAIDs +{ + // Emalon the Storm Watcher + AURA_OVERCHARGE = 64217, + BOSS_EMALON = 33993, + NPC_TEMPEST_MINION = 33998, + SPELL_LIGHTNING_NOVA_10_MAN = 64216, + SPELL_LIGHTNING_NOVA_25_MAN = 65279, +}; + +// +// Emalon the Storm Watcher +// +class EmalonMarkBossTrigger : public Trigger +{ +public: + EmalonMarkBossTrigger(PlayerbotAI* ai) : Trigger(ai, "emalon mark boss trigger") {} + bool IsActive() override; +}; + +class EmalonLightingNovaTrigger : public Trigger +{ +public: + EmalonLightingNovaTrigger(PlayerbotAI* ai) : Trigger(ai, "emalon lighting nova trigger") {} + bool IsActive() override; +}; + +class EmalonOverchargeTrigger : public Trigger +{ +public: + EmalonOverchargeTrigger(PlayerbotAI* ai) : Trigger(ai, "emalon overcharge trigger") {} + bool IsActive() override; +}; + +class EmalonFallFromFloorTrigger : public Trigger +{ +public: + EmalonFallFromFloorTrigger(PlayerbotAI* ai) : Trigger(ai, "emalon fall from floor trigger") {} + bool IsActive() override; +}; + +#endif