mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Added Vault of Archavon strategy with Emalon tactics (#1117)
This commit is contained in:
@@ -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());
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "RaidMcStrategy.h"
|
||||
#include "RaidAq20Strategy.h"
|
||||
#include "RaidIccStrategy.h"
|
||||
#include "RaidVoAStrategy.h"
|
||||
|
||||
class RaidStrategyContext : public NamedObjectContext<Strategy>
|
||||
{
|
||||
@@ -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); }
|
||||
};
|
||||
|
||||
32
src/strategy/raids/vaultofarchavon/RaidVoAActionContext.h
Normal file
32
src/strategy/raids/vaultofarchavon/RaidVoAActionContext.h
Normal file
@@ -0,0 +1,32 @@
|
||||
// /*
|
||||
// * Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, 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<Action>
|
||||
{
|
||||
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
|
||||
187
src/strategy/raids/vaultofarchavon/RaidVoAActions.cpp
Normal file
187
src/strategy/raids/vaultofarchavon/RaidVoAActions.cpp
Normal file
@@ -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();
|
||||
}
|
||||
45
src/strategy/raids/vaultofarchavon/RaidVoAActions.h
Normal file
45
src/strategy/raids/vaultofarchavon/RaidVoAActions.h
Normal file
@@ -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
|
||||
27
src/strategy/raids/vaultofarchavon/RaidVoAStrategy.cpp
Normal file
27
src/strategy/raids/vaultofarchavon/RaidVoAStrategy.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "RaidVoAStrategy.h"
|
||||
#include "Action.h"
|
||||
#include "Strategy.h"
|
||||
#include "Trigger.h"
|
||||
#include "vector"
|
||||
|
||||
void RaidVoAStrategy::InitTriggers(std::vector<TriggerNode*>& 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)));
|
||||
}
|
||||
19
src/strategy/raids/vaultofarchavon/RaidVoAStrategy.h
Normal file
19
src/strategy/raids/vaultofarchavon/RaidVoAStrategy.h
Normal file
@@ -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<TriggerNode*>& triggers) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
31
src/strategy/raids/vaultofarchavon/RaidVoATriggerContext.h
Normal file
31
src/strategy/raids/vaultofarchavon/RaidVoATriggerContext.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// /*
|
||||
// * Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, 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<Trigger>
|
||||
{
|
||||
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
|
||||
137
src/strategy/raids/vaultofarchavon/RaidVoATriggers.cpp
Normal file
137
src/strategy/raids/vaultofarchavon/RaidVoATriggers.cpp
Normal file
@@ -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;
|
||||
}
|
||||
50
src/strategy/raids/vaultofarchavon/RaidVoATriggers.h
Normal file
50
src/strategy/raids/vaultofarchavon/RaidVoATriggers.h
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user