mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-03-10 11:00:31 +00:00
[HOT FIX] MS build issues regarding folder / command lenght usage or rc.exe (#2038)
This commit is contained in:
1493
src/Ai/Raid/Karazhan/Action/RaidKarazhanActions.cpp
Normal file
1493
src/Ai/Raid/Karazhan/Action/RaidKarazhanActions.cpp
Normal file
File diff suppressed because it is too large
Load Diff
322
src/Ai/Raid/Karazhan/Action/RaidKarazhanActions.h
Normal file
322
src/Ai/Raid/Karazhan/Action/RaidKarazhanActions.h
Normal file
@@ -0,0 +1,322 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANACTIONS_H
|
||||
#define _PLAYERBOT_RAIDKARAZHANACTIONS_H
|
||||
|
||||
#include "Action.h"
|
||||
#include "AttackAction.h"
|
||||
#include "MovementActions.h"
|
||||
|
||||
class ManaWarpStunCreatureBeforeWarpBreachAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
ManaWarpStunCreatureBeforeWarpBreachAction(
|
||||
PlayerbotAI* botAI, std::string const name = "mana warp stun creature before warp breach") : AttackAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class AttumenTheHuntsmanMarkTargetAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
AttumenTheHuntsmanMarkTargetAction(
|
||||
PlayerbotAI* botAI, std::string const name = "attumen the huntsman mark target") : AttackAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class AttumenTheHuntsmanSplitBossesAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
AttumenTheHuntsmanSplitBossesAction(
|
||||
PlayerbotAI* botAI, std::string const name = "attumen the huntsman split bosses") : AttackAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class AttumenTheHuntsmanStackBehindAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
AttumenTheHuntsmanStackBehindAction(
|
||||
PlayerbotAI* botAI, std::string const name = "attumen the huntsman stack behind") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class AttumenTheHuntsmanManageDpsTimerAction : public Action
|
||||
{
|
||||
public:
|
||||
AttumenTheHuntsmanManageDpsTimerAction(
|
||||
PlayerbotAI* botAI, std::string const name = "attumen the huntsman manage dps timer") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class MoroesMainTankAttackBossAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
MoroesMainTankAttackBossAction(
|
||||
PlayerbotAI* botAI, std::string const name = "moroes main tank attack boss") : AttackAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class MoroesMarkTargetAction : public Action
|
||||
{
|
||||
public:
|
||||
MoroesMarkTargetAction(
|
||||
PlayerbotAI* botAI, std::string const name = "moroes mark target") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class MaidenOfVirtueMoveBossToHealerAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
MaidenOfVirtueMoveBossToHealerAction(
|
||||
PlayerbotAI* botAI, std::string const name = "maiden of virtue move boss to healer") : AttackAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class MaidenOfVirtuePositionRangedAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
MaidenOfVirtuePositionRangedAction(
|
||||
PlayerbotAI* botAI, std::string const name = "maiden of virtue position ranged") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class BigBadWolfPositionBossAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
BigBadWolfPositionBossAction(
|
||||
PlayerbotAI* botAI, std::string const name = "big bad wolf position boss") : AttackAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class BigBadWolfRunAwayFromBossAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
BigBadWolfRunAwayFromBossAction(
|
||||
PlayerbotAI* botAI, std::string const name = "big bad wolf run away from boss") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class RomuloAndJulianneMarkTargetAction : public Action
|
||||
{
|
||||
public:
|
||||
RomuloAndJulianneMarkTargetAction(
|
||||
PlayerbotAI* botAI, std::string const name = "romulo and julianne mark target") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class WizardOfOzMarkTargetAction : public Action
|
||||
{
|
||||
public:
|
||||
WizardOfOzMarkTargetAction(
|
||||
PlayerbotAI* botAI, std::string const name = "wizard of oz mark target") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class WizardOfOzScorchStrawmanAction : public Action
|
||||
{
|
||||
public:
|
||||
WizardOfOzScorchStrawmanAction(
|
||||
PlayerbotAI* botAI, std::string const name = "wizard of oz scorch strawman") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class TheCuratorMarkAstralFlareAction : public Action
|
||||
{
|
||||
public:
|
||||
TheCuratorMarkAstralFlareAction(
|
||||
PlayerbotAI* botAI, std::string const name = "the curator mark astral flare") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class TheCuratorPositionBossAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
TheCuratorPositionBossAction(
|
||||
PlayerbotAI* botAI, std::string const name = "the curator position boss") : AttackAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class TheCuratorSpreadRangedAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
TheCuratorSpreadRangedAction(
|
||||
PlayerbotAI* botAI, std::string const name = "the curator spread ranged") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class TerestianIllhoofMarkTargetAction : public Action
|
||||
{
|
||||
public:
|
||||
TerestianIllhoofMarkTargetAction(
|
||||
PlayerbotAI* botAI, std::string const name = "terestian illhoof mark target") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class ShadeOfAranRunAwayFromArcaneExplosionAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
ShadeOfAranRunAwayFromArcaneExplosionAction(
|
||||
PlayerbotAI* botAI, std::string const name = "shade of aran run away from arcane explosion") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class ShadeOfAranStopMovingDuringFlameWreathAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
ShadeOfAranStopMovingDuringFlameWreathAction(
|
||||
PlayerbotAI* botAI, std::string const name = "shade of aran stop moving during flame wreath") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class ShadeOfAranMarkConjuredElementalAction : public Action
|
||||
{
|
||||
public:
|
||||
ShadeOfAranMarkConjuredElementalAction(
|
||||
PlayerbotAI* botAI, std::string const name = "shade of aran mark conjured elemental") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class ShadeOfAranRangedMaintainDistanceAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
ShadeOfAranRangedMaintainDistanceAction(
|
||||
PlayerbotAI* botAI, std::string const name = "shade of aran ranged maintain distance") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class NetherspiteBlockRedBeamAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
NetherspiteBlockRedBeamAction(
|
||||
PlayerbotAI* botAI, std::string const name = "netherspite block red beam") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
private:
|
||||
Position GetPositionOnBeam(Unit* netherspite, Unit* portal, float distanceFromBoss);
|
||||
std::unordered_map<ObjectGuid, bool> _wasBlockingRedBeam;
|
||||
};
|
||||
|
||||
class NetherspiteBlockBlueBeamAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
NetherspiteBlockBlueBeamAction(
|
||||
PlayerbotAI* botAI, std::string const name = "netherspite block blue beam") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
private:
|
||||
std::unordered_map<ObjectGuid, bool> _wasBlockingBlueBeam;
|
||||
};
|
||||
|
||||
class NetherspiteBlockGreenBeamAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
NetherspiteBlockGreenBeamAction(
|
||||
PlayerbotAI* botAI, std::string const name = "netherspite block green beam") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
private:
|
||||
std::unordered_map<ObjectGuid, bool> _wasBlockingGreenBeam;
|
||||
};
|
||||
|
||||
class NetherspiteAvoidBeamAndVoidZoneAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
NetherspiteAvoidBeamAndVoidZoneAction(
|
||||
PlayerbotAI* botAI, std::string const name = "netherspite avoid beam and void zone") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
|
||||
private:
|
||||
struct BeamAvoid
|
||||
{
|
||||
Unit* portal;
|
||||
float minDist, maxDist;
|
||||
};
|
||||
bool IsAwayFromBeams(float x, float y, const std::vector<BeamAvoid>& beams, Unit* netherspite);
|
||||
};
|
||||
|
||||
class NetherspiteBanishPhaseAvoidVoidZoneAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
NetherspiteBanishPhaseAvoidVoidZoneAction(
|
||||
PlayerbotAI* botAI, std::string const name = "netherspite banish phase avoid void zone") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class NetherspiteManageTimersAndTrackersAction : public Action
|
||||
{
|
||||
public:
|
||||
NetherspiteManageTimersAndTrackersAction(
|
||||
PlayerbotAI* botAI, std::string const name = "netherspite manage timers and trackers") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class PrinceMalchezaarEnfeebledAvoidHazardAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
PrinceMalchezaarEnfeebledAvoidHazardAction(
|
||||
PlayerbotAI* botAI, std::string const name = "prince malchezaar enfeebled avoid hazard") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class PrinceMalchezaarNonTankAvoidInfernalAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
PrinceMalchezaarNonTankAvoidInfernalAction(
|
||||
PlayerbotAI* botAI, std::string const name = "prince malchezaar non tank avoid infernal") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class PrinceMalchezaarMainTankMovementAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
PrinceMalchezaarMainTankMovementAction(
|
||||
PlayerbotAI* botAI, std::string const name = "prince malchezaar main tank movement") : AttackAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class NightbaneGroundPhasePositionBossAction : public AttackAction
|
||||
{
|
||||
public:
|
||||
NightbaneGroundPhasePositionBossAction(
|
||||
PlayerbotAI* botAI, std::string const name = "nightbane ground phase position boss") : AttackAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class NightbaneGroundPhaseRotateRangedPositionsAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
NightbaneGroundPhaseRotateRangedPositionsAction(
|
||||
PlayerbotAI* botAI, std::string const name = "nightbane ground phase rotate ranged positions") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class NightbaneCastFearWardOnMainTankAction : public Action
|
||||
{
|
||||
public:
|
||||
NightbaneCastFearWardOnMainTankAction(
|
||||
PlayerbotAI* botAI, std::string const name = "nightbane cast fear ward on main tank") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class NightbaneControlPetAggressionAction : public Action
|
||||
{
|
||||
public:
|
||||
NightbaneControlPetAggressionAction(
|
||||
PlayerbotAI* botAI, std::string const name = "nightbane control pet aggression") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class NightbaneFlightPhaseMovementAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
NightbaneFlightPhaseMovementAction(
|
||||
PlayerbotAI* botAI, std::string const name = "nightbane flight phase movement") : MovementAction(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class NightbaneManageTimersAndTrackersAction : public Action
|
||||
{
|
||||
public:
|
||||
NightbaneManageTimersAndTrackersAction(
|
||||
PlayerbotAI* botAI, std::string const name = "nightbane manage timers and trackers") : Action(botAI, name) {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
363
src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.cpp
Normal file
363
src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.cpp
Normal file
@@ -0,0 +1,363 @@
|
||||
#include "RaidKarazhanMultipliers.h"
|
||||
#include "RaidKarazhanActions.h"
|
||||
#include "RaidKarazhanHelpers.h"
|
||||
#include "AttackAction.h"
|
||||
#include "ChooseTargetActions.h"
|
||||
#include "DruidActions.h"
|
||||
#include "FollowActions.h"
|
||||
#include "GenericActions.h"
|
||||
#include "HunterActions.h"
|
||||
#include "MageActions.h"
|
||||
#include "Playerbots.h"
|
||||
#include "PriestActions.h"
|
||||
#include "ReachTargetActions.h"
|
||||
#include "RogueActions.h"
|
||||
#include "ShamanActions.h"
|
||||
|
||||
using namespace KarazhanHelpers;
|
||||
|
||||
// Keep tanks from jumping back and forth between Attumen and Midnight
|
||||
float AttumenTheHuntsmanDisableTankAssistMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* midnight = AI_VALUE2(Unit*, "find target", "midnight");
|
||||
if (!midnight)
|
||||
return 1.0f;
|
||||
|
||||
Unit* attumen = AI_VALUE2(Unit*, "find target", "attumen the huntsman");
|
||||
if (!attumen)
|
||||
return 1.0f;
|
||||
|
||||
if (bot->GetVictim() != nullptr && dynamic_cast<TankAssistAction*>(action))
|
||||
return 0.0f;
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Try to get rid of jittering when bots are stacked behind Attumen
|
||||
float AttumenTheHuntsmanStayStackedMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* attumenMounted = GetFirstAliveUnitByEntry(botAI, NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED);
|
||||
if (!attumenMounted)
|
||||
return 1.0f;
|
||||
|
||||
if (!botAI->IsMainTank(bot) && attumenMounted->GetVictim() != bot)
|
||||
{
|
||||
if (dynamic_cast<CombatFormationMoveAction*>(action) ||
|
||||
dynamic_cast<FleeAction*>(action) ||
|
||||
dynamic_cast<CastBlinkBackAction*>(action) ||
|
||||
dynamic_cast<CastDisengageAction*>(action) ||
|
||||
dynamic_cast<CastReachTargetSpellAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Give the main tank 8 seconds to grab aggro when Attumen mounts Midnight
|
||||
// In reality it's shorter because it takes Attumen a few seconds to aggro after mounting
|
||||
float AttumenTheHuntsmanWaitForDpsMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* attumenMounted = GetFirstAliveUnitByEntry(botAI, NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED);
|
||||
if (!attumenMounted)
|
||||
return 1.0f;
|
||||
|
||||
const uint32 instanceId = attumenMounted->GetMap()->GetInstanceId();
|
||||
const time_t now = std::time(nullptr);
|
||||
const uint8 dpsWaitSeconds = 8;
|
||||
|
||||
auto it = attumenDpsWaitTimer.find(instanceId);
|
||||
if (it == attumenDpsWaitTimer.end() || (now - it->second) < dpsWaitSeconds)
|
||||
{
|
||||
if (!botAI->IsMainTank(bot))
|
||||
{
|
||||
if (dynamic_cast<AttackAction*>(action) || (dynamic_cast<CastSpellAction*>(action) &&
|
||||
!dynamic_cast<CastHealingSpellAction*>(action)))
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// The assist tank should stay on the boss to be 2nd on aggro and tank Hateful Bolts
|
||||
float TheCuratorDisableTankAssistMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* curator = AI_VALUE2(Unit*, "find target", "the curator");
|
||||
if (!curator)
|
||||
return 1.0f;
|
||||
|
||||
if (bot->GetVictim() != nullptr && dynamic_cast<TankAssistAction*>(action))
|
||||
return 0.0f;
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Save Bloodlust/Heroism for Evocation (100% increased damage)
|
||||
float TheCuratorDelayBloodlustAndHeroismMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* curator = AI_VALUE2(Unit*, "find target", "the curator");
|
||||
if (!curator)
|
||||
return 1.0f;
|
||||
|
||||
if (!curator->HasAura(SPELL_CURATOR_EVOCATION))
|
||||
{
|
||||
if (dynamic_cast<CastBloodlustAction*>(action) ||
|
||||
dynamic_cast<CastHeroismAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Don't charge back in when running from Arcane Explosion
|
||||
float ShadeOfAranArcaneExplosionDisableChargeMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* aran = AI_VALUE2(Unit*, "find target", "shade of aran");
|
||||
if (!aran)
|
||||
return 1.0f;
|
||||
|
||||
if (aran->HasUnitState(UNIT_STATE_CASTING) &&
|
||||
aran->FindCurrentSpellBySpellId(SPELL_ARCANE_EXPLOSION))
|
||||
{
|
||||
if (dynamic_cast<CastReachTargetSpellAction*>(action))
|
||||
return 0.0f;
|
||||
|
||||
if (bot->GetDistance2d(aran) >= 20.0f)
|
||||
{
|
||||
if (dynamic_cast<CombatFormationMoveAction*>(action) ||
|
||||
dynamic_cast<FleeAction*>(action) ||
|
||||
dynamic_cast<FollowAction*>(action) ||
|
||||
dynamic_cast<ReachTargetAction*>(action) ||
|
||||
dynamic_cast<AvoidAoeAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// I will not move when Flame Wreath is cast or the raid blows up
|
||||
float ShadeOfAranFlameWreathDisableMovementMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* aran = AI_VALUE2(Unit*, "find target", "shade of aran");
|
||||
if (!aran)
|
||||
return 1.0f;
|
||||
|
||||
if (IsFlameWreathActive(botAI, bot))
|
||||
{
|
||||
if (dynamic_cast<CombatFormationMoveAction*>(action) ||
|
||||
dynamic_cast<FleeAction*>(action) ||
|
||||
dynamic_cast<FollowAction*>(action) ||
|
||||
dynamic_cast<ReachTargetAction*>(action) ||
|
||||
dynamic_cast<AvoidAoeAction*>(action) ||
|
||||
dynamic_cast<CastKillingSpreeAction*>(action) ||
|
||||
dynamic_cast<CastBlinkBackAction*>(action) ||
|
||||
dynamic_cast<CastDisengageAction*>(action) ||
|
||||
dynamic_cast<CastReachTargetSpellAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Try to rid of the jittering when blocking beams
|
||||
float NetherspiteKeepBlockingBeamMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
if (!netherspite || netherspite->HasAura(SPELL_NETHERSPITE_BANISHED))
|
||||
return 1.0f;
|
||||
|
||||
auto [redBlocker, greenBlocker, blueBlocker] = GetCurrentBeamBlockers(botAI, bot);
|
||||
|
||||
if (bot == redBlocker)
|
||||
{
|
||||
if (dynamic_cast<CombatFormationMoveAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (bot == blueBlocker)
|
||||
{
|
||||
if (dynamic_cast<CombatFormationMoveAction*>(action) ||
|
||||
dynamic_cast<ReachTargetAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (bot == greenBlocker)
|
||||
{
|
||||
if (dynamic_cast<CombatFormationMoveAction*>(action) ||
|
||||
dynamic_cast<ReachTargetAction*>(action) ||
|
||||
dynamic_cast<FleeAction*>(action) ||
|
||||
dynamic_cast<CastKillingSpreeAction*>(action) ||
|
||||
dynamic_cast<CastReachTargetSpellAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Give tanks 5 seconds to get aggro during phase transitions
|
||||
float NetherspiteWaitForDpsMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
if (!netherspite || netherspite->HasAura(SPELL_NETHERSPITE_BANISHED))
|
||||
return 1.0f;
|
||||
|
||||
const uint32 instanceId = netherspite->GetMap()->GetInstanceId();
|
||||
const time_t now = std::time(nullptr);
|
||||
const uint8 dpsWaitSeconds = 5;
|
||||
|
||||
auto it = netherspiteDpsWaitTimer.find(instanceId);
|
||||
if (it == netherspiteDpsWaitTimer.end() || (now - it->second) < dpsWaitSeconds)
|
||||
{
|
||||
if (!botAI->IsTank(bot))
|
||||
{
|
||||
if (dynamic_cast<AttackAction*>(action) || (dynamic_cast<CastSpellAction*>(action) &&
|
||||
!dynamic_cast<CastHealingSpellAction*>(action)))
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Disable standard "avoid aoe" strategy, which may interfere with scripted avoidance
|
||||
float PrinceMalchezaarDisableAvoidAoeMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* malchezaar = AI_VALUE2(Unit*, "find target", "prince malchezaar");
|
||||
if (!malchezaar)
|
||||
return 1.0f;
|
||||
|
||||
if (dynamic_cast<AvoidAoeAction*>(action))
|
||||
return 0.0f;
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Don't run back into Shadow Nova when Enfeebled
|
||||
float PrinceMalchezaarEnfeebleKeepDistanceMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* malchezaar = AI_VALUE2(Unit*, "find target", "prince malchezaar");
|
||||
if (!malchezaar)
|
||||
return 1.0f;
|
||||
|
||||
if (bot->HasAura(SPELL_ENFEEBLE))
|
||||
{
|
||||
if (dynamic_cast<MovementAction*>(action) &&
|
||||
!dynamic_cast<PrinceMalchezaarEnfeebledAvoidHazardAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Wait until Phase 3 to use Bloodlust/Heroism
|
||||
float PrinceMalchezaarDelayBloodlustAndHeroismMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* malchezaar = AI_VALUE2(Unit*, "find target", "prince malchezaar");
|
||||
if (!malchezaar)
|
||||
return 1.0f;
|
||||
|
||||
if (malchezaar->GetHealthPct() > 30.0f)
|
||||
{
|
||||
if (dynamic_cast<CastBloodlustAction*>(action) ||
|
||||
dynamic_cast<CastHeroismAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Pets tend to run out of bounds and cause skeletons to spawn off the map
|
||||
// Pets also tend to pull adds from inside of the tower through the floor
|
||||
// This multiplier DOES NOT impact Hunter and Warlock pets
|
||||
// Hunter and Warlock pets are addressed in ControlPetAggressionAction
|
||||
float NightbaneDisablePetsMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane");
|
||||
if (!nightbane)
|
||||
return 1.0f;
|
||||
|
||||
if (dynamic_cast<CastForceOfNatureAction*>(action) ||
|
||||
dynamic_cast<CastFeralSpiritAction*>(action) ||
|
||||
dynamic_cast<CastFireElementalTotemAction*>(action) ||
|
||||
dynamic_cast<CastFireElementalTotemMeleeAction*>(action) ||
|
||||
dynamic_cast<CastSummonWaterElementalAction*>(action) ||
|
||||
dynamic_cast<CastShadowfiendAction*>(action))
|
||||
return 0.0f;
|
||||
|
||||
if (nightbane->GetPositionZ() > NIGHTBANE_FLIGHT_Z)
|
||||
{
|
||||
if (dynamic_cast<PetAttackAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Give the main tank 8 seconds to get aggro during phase transitions
|
||||
float NightbaneWaitForDpsMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane");
|
||||
if (!nightbane || nightbane->GetPositionZ() > NIGHTBANE_FLIGHT_Z)
|
||||
return 1.0f;
|
||||
|
||||
const uint32 instanceId = nightbane->GetMap()->GetInstanceId();
|
||||
const time_t now = std::time(nullptr);
|
||||
const uint8 dpsWaitSeconds = 8;
|
||||
|
||||
auto it = nightbaneDpsWaitTimer.find(instanceId);
|
||||
if (it == nightbaneDpsWaitTimer.end() || (now - it->second) < dpsWaitSeconds)
|
||||
{
|
||||
if (!botAI->IsMainTank(bot))
|
||||
{
|
||||
if (dynamic_cast<AttackAction*>(action) || (dynamic_cast<CastSpellAction*>(action) &&
|
||||
!dynamic_cast<CastHealingSpellAction*>(action)))
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// The "avoid aoe" strategy must be disabled for the main tank
|
||||
// Otherwise, the main tank will spin Nightbane to avoid Charred Earth and wipe the raid
|
||||
// It is also disabled for all bots during the flight phase
|
||||
float NightbaneDisableAvoidAoeMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane");
|
||||
if (!nightbane)
|
||||
return 1.0f;
|
||||
|
||||
if (nightbane->GetPositionZ() > NIGHTBANE_FLIGHT_Z || botAI->IsMainTank(bot))
|
||||
{
|
||||
if (dynamic_cast<AvoidAoeAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
// Disable some movement actions that conflict with the strategies
|
||||
float NightbaneDisableMovementMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane");
|
||||
if (!nightbane)
|
||||
return 1.0f;
|
||||
|
||||
if (dynamic_cast<CastBlinkBackAction*>(action) ||
|
||||
dynamic_cast<CastDisengageAction*>(action) ||
|
||||
dynamic_cast<FleeAction*>(action))
|
||||
return 0.0f;
|
||||
|
||||
// Disable CombatFormationMoveAction for all bots except:
|
||||
// (1) main tank and (2) only during the ground phase, other melee
|
||||
if (botAI->IsRanged(bot) ||
|
||||
(botAI->IsMelee(bot) && !botAI->IsMainTank(bot) &&
|
||||
nightbane->GetPositionZ() > NIGHTBANE_FLIGHT_Z))
|
||||
{
|
||||
if (dynamic_cast<CombatFormationMoveAction*>(action))
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
134
src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.h
Normal file
134
src/Ai/Raid/Karazhan/Multiplier/RaidKarazhanMultipliers.h
Normal file
@@ -0,0 +1,134 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANMULTIPLIERS_H
|
||||
#define _PLAYERBOT_RAIDKARAZHANMULTIPLIERS_H
|
||||
|
||||
#include "Multiplier.h"
|
||||
|
||||
class AttumenTheHuntsmanDisableTankAssistMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
AttumenTheHuntsmanDisableTankAssistMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "attumen the huntsman disable tank assist multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class AttumenTheHuntsmanStayStackedMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
AttumenTheHuntsmanStayStackedMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "attumen the huntsman stay stacked multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class AttumenTheHuntsmanWaitForDpsMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
AttumenTheHuntsmanWaitForDpsMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "attumen the huntsman wait for dps multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class TheCuratorDisableTankAssistMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
TheCuratorDisableTankAssistMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "the curator disable tank assist multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class TheCuratorDelayBloodlustAndHeroismMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
TheCuratorDelayBloodlustAndHeroismMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "the curator delay bloodlust and heroism multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class ShadeOfAranArcaneExplosionDisableChargeMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
ShadeOfAranArcaneExplosionDisableChargeMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "shade of aran arcane explosion disable charge multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class ShadeOfAranFlameWreathDisableMovementMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
ShadeOfAranFlameWreathDisableMovementMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "shade of aran flame wreath disable movement multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class NetherspiteKeepBlockingBeamMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
NetherspiteKeepBlockingBeamMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "netherspite keep blocking beam multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class NetherspiteWaitForDpsMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
NetherspiteWaitForDpsMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "netherspite wait for dps multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class PrinceMalchezaarDisableAvoidAoeMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
PrinceMalchezaarDisableAvoidAoeMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "prince malchezaar disable avoid aoe multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class PrinceMalchezaarEnfeebleKeepDistanceMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
PrinceMalchezaarEnfeebleKeepDistanceMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "prince malchezaar enfeeble keep distance multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class PrinceMalchezaarDelayBloodlustAndHeroismMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
PrinceMalchezaarDelayBloodlustAndHeroismMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "prince malchezaar delay bloodlust and heroism multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class NightbaneDisablePetsMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
NightbaneDisablePetsMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "nightbane disable pets multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class NightbaneWaitForDpsMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
NightbaneWaitForDpsMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "nightbane wait for dps multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class NightbaneDisableAvoidAoeMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
NightbaneDisableAvoidAoeMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "nightbane disable avoid aoe multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class NightbaneDisableMovementMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
NightbaneDisableMovementMultiplier(
|
||||
PlayerbotAI* botAI) : Multiplier(botAI, "nightbane disable movement multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
#endif
|
||||
263
src/Ai/Raid/Karazhan/RaidKarazhanActionContext.h
Normal file
263
src/Ai/Raid/Karazhan/RaidKarazhanActionContext.h
Normal file
@@ -0,0 +1,263 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANACTIONCONTEXT_H
|
||||
#define _PLAYERBOT_RAIDKARAZHANACTIONCONTEXT_H
|
||||
|
||||
#include "RaidKarazhanActions.h"
|
||||
#include "NamedObjectContext.h"
|
||||
|
||||
class RaidKarazhanActionContext : public NamedObjectContext<Action>
|
||||
{
|
||||
public:
|
||||
RaidKarazhanActionContext()
|
||||
{
|
||||
// Trash
|
||||
creators["mana warp stun creature before warp breach"] =
|
||||
&RaidKarazhanActionContext::mana_warp_stun_creature_before_warp_breach;
|
||||
|
||||
// Attumen the Huntsman
|
||||
creators["attumen the huntsman mark target"] =
|
||||
&RaidKarazhanActionContext::attumen_the_huntsman_mark_target;
|
||||
|
||||
creators["attumen the huntsman split bosses"] =
|
||||
&RaidKarazhanActionContext::attumen_the_huntsman_split_bosses;
|
||||
|
||||
creators["attumen the huntsman stack behind"] =
|
||||
&RaidKarazhanActionContext::attumen_the_huntsman_stack_behind;
|
||||
|
||||
creators["attumen the huntsman manage dps timer"] =
|
||||
&RaidKarazhanActionContext::attumen_the_huntsman_manage_dps_timer;
|
||||
|
||||
// Moroes
|
||||
creators["moroes main tank attack boss"] =
|
||||
&RaidKarazhanActionContext::moroes_main_tank_attack_boss;
|
||||
|
||||
creators["moroes mark target"] =
|
||||
&RaidKarazhanActionContext::moroes_mark_target;
|
||||
|
||||
// Maiden of Virtue
|
||||
creators["maiden of virtue move boss to healer"] =
|
||||
&RaidKarazhanActionContext::maiden_of_virtue_move_boss_to_healer;
|
||||
|
||||
creators["maiden of virtue position ranged"] =
|
||||
&RaidKarazhanActionContext::maiden_of_virtue_position_ranged;
|
||||
|
||||
// The Big Bad Wolf
|
||||
creators["big bad wolf position boss"] =
|
||||
&RaidKarazhanActionContext::big_bad_wolf_position_boss;
|
||||
|
||||
creators["big bad wolf run away from boss"] =
|
||||
&RaidKarazhanActionContext::big_bad_wolf_run_away_from_boss;
|
||||
|
||||
// Romulo and Julianne
|
||||
creators["romulo and julianne mark target"] =
|
||||
&RaidKarazhanActionContext::romulo_and_julianne_mark_target;
|
||||
|
||||
// The Wizard of Oz
|
||||
creators["wizard of oz mark target"] =
|
||||
&RaidKarazhanActionContext::wizard_of_oz_mark_target;
|
||||
|
||||
creators["wizard of oz scorch strawman"] =
|
||||
&RaidKarazhanActionContext::wizard_of_oz_scorch_strawman;
|
||||
|
||||
// The Curator
|
||||
creators["the curator mark astral flare"] =
|
||||
&RaidKarazhanActionContext::the_curator_mark_astral_flare;
|
||||
|
||||
creators["the curator position boss"] =
|
||||
&RaidKarazhanActionContext::the_curator_position_boss;
|
||||
|
||||
creators["the curator spread ranged"] =
|
||||
&RaidKarazhanActionContext::the_curator_spread_ranged;
|
||||
|
||||
// Terestian Illhoof
|
||||
creators["terestian illhoof mark target"] =
|
||||
&RaidKarazhanActionContext::terestian_illhoof_mark_target;
|
||||
|
||||
// Shade of Aran
|
||||
creators["shade of aran run away from arcane explosion"] =
|
||||
&RaidKarazhanActionContext::shade_of_aran_run_away_from_arcane_explosion;
|
||||
|
||||
creators["shade of aran stop moving during flame wreath"] =
|
||||
&RaidKarazhanActionContext::shade_of_aran_stop_moving_during_flame_wreath;
|
||||
|
||||
creators["shade of aran mark conjured elemental"] =
|
||||
&RaidKarazhanActionContext::shade_of_aran_mark_conjured_elemental;
|
||||
|
||||
creators["shade of aran ranged maintain distance"] =
|
||||
&RaidKarazhanActionContext::shade_of_aran_ranged_maintain_distance;
|
||||
|
||||
// Netherspite
|
||||
creators["netherspite block red beam"] =
|
||||
&RaidKarazhanActionContext::netherspite_block_red_beam;
|
||||
|
||||
creators["netherspite block blue beam"] =
|
||||
&RaidKarazhanActionContext::netherspite_block_blue_beam;
|
||||
|
||||
creators["netherspite block green beam"] =
|
||||
&RaidKarazhanActionContext::netherspite_block_green_beam;
|
||||
|
||||
creators["netherspite avoid beam and void zone"] =
|
||||
&RaidKarazhanActionContext::netherspite_avoid_beam_and_void_zone;
|
||||
|
||||
creators["netherspite banish phase avoid void zone"] =
|
||||
&RaidKarazhanActionContext::netherspite_banish_phase_avoid_void_zone;
|
||||
|
||||
creators["netherspite manage timers and trackers"] =
|
||||
&RaidKarazhanActionContext::netherspite_manage_timers_and_trackers;
|
||||
|
||||
// Prince Malchezaar
|
||||
creators["prince malchezaar enfeebled avoid hazard"] =
|
||||
&RaidKarazhanActionContext::prince_malchezaar_enfeebled_avoid_hazard;
|
||||
|
||||
creators["prince malchezaar non tank avoid infernal"] =
|
||||
&RaidKarazhanActionContext::prince_malchezaar_non_tank_avoid_infernal;
|
||||
|
||||
creators["prince malchezaar main tank movement"] =
|
||||
&RaidKarazhanActionContext::prince_malchezaar_main_tank_movement;
|
||||
|
||||
// Nightbane
|
||||
creators["nightbane ground phase position boss"] =
|
||||
&RaidKarazhanActionContext::nightbane_ground_phase_position_boss;
|
||||
|
||||
creators["nightbane ground phase rotate ranged positions"] =
|
||||
&RaidKarazhanActionContext::nightbane_ground_phase_rotate_ranged_positions;
|
||||
|
||||
creators["nightbane cast fear ward on main tank"] =
|
||||
&RaidKarazhanActionContext::nightbane_cast_fear_ward_on_main_tank;
|
||||
|
||||
creators["nightbane control pet aggression"] =
|
||||
&RaidKarazhanActionContext::nightbane_control_pet_aggression;
|
||||
|
||||
creators["nightbane flight phase movement"] =
|
||||
&RaidKarazhanActionContext::nightbane_flight_phase_movement;
|
||||
|
||||
creators["nightbane manage timers and trackers"] =
|
||||
&RaidKarazhanActionContext::nightbane_manage_timers_and_trackers;
|
||||
}
|
||||
|
||||
private:
|
||||
// Trash
|
||||
static Action* mana_warp_stun_creature_before_warp_breach(
|
||||
PlayerbotAI* botAI) { return new ManaWarpStunCreatureBeforeWarpBreachAction(botAI); }
|
||||
|
||||
// Attumen the Huntsman
|
||||
static Action* attumen_the_huntsman_mark_target(
|
||||
PlayerbotAI* botAI) { return new AttumenTheHuntsmanMarkTargetAction(botAI); }
|
||||
|
||||
static Action* attumen_the_huntsman_split_bosses(
|
||||
PlayerbotAI* botAI) { return new AttumenTheHuntsmanSplitBossesAction(botAI); }
|
||||
|
||||
static Action* attumen_the_huntsman_stack_behind(
|
||||
PlayerbotAI* botAI) { return new AttumenTheHuntsmanStackBehindAction(botAI); }
|
||||
|
||||
static Action* attumen_the_huntsman_manage_dps_timer(
|
||||
PlayerbotAI* botAI) { return new AttumenTheHuntsmanManageDpsTimerAction(botAI); }
|
||||
|
||||
// Moroes
|
||||
static Action* moroes_main_tank_attack_boss(
|
||||
PlayerbotAI* botAI) { return new MoroesMainTankAttackBossAction(botAI); }
|
||||
|
||||
static Action* moroes_mark_target(
|
||||
PlayerbotAI* botAI) { return new MoroesMarkTargetAction(botAI); }
|
||||
|
||||
// Maiden of Virtue
|
||||
static Action* maiden_of_virtue_move_boss_to_healer(
|
||||
PlayerbotAI* botAI) { return new MaidenOfVirtueMoveBossToHealerAction(botAI); }
|
||||
|
||||
static Action* maiden_of_virtue_position_ranged(
|
||||
PlayerbotAI* botAI) { return new MaidenOfVirtuePositionRangedAction(botAI); }
|
||||
|
||||
// The Big Bad Wolf
|
||||
static Action* big_bad_wolf_position_boss(
|
||||
PlayerbotAI* botAI) { return new BigBadWolfPositionBossAction(botAI); }
|
||||
|
||||
static Action* big_bad_wolf_run_away_from_boss(
|
||||
PlayerbotAI* botAI) { return new BigBadWolfRunAwayFromBossAction(botAI); }
|
||||
|
||||
// Romulo and Julianne
|
||||
static Action* romulo_and_julianne_mark_target(
|
||||
PlayerbotAI* botAI) { return new RomuloAndJulianneMarkTargetAction(botAI); }
|
||||
|
||||
// The Wizard of Oz
|
||||
static Action* wizard_of_oz_mark_target(
|
||||
PlayerbotAI* botAI) { return new WizardOfOzMarkTargetAction(botAI); }
|
||||
|
||||
static Action* wizard_of_oz_scorch_strawman(
|
||||
PlayerbotAI* botAI) { return new WizardOfOzScorchStrawmanAction(botAI); }
|
||||
|
||||
// The Curator
|
||||
static Action* the_curator_mark_astral_flare(
|
||||
PlayerbotAI* botAI) { return new TheCuratorMarkAstralFlareAction(botAI); }
|
||||
|
||||
static Action* the_curator_position_boss(
|
||||
PlayerbotAI* botAI) { return new TheCuratorPositionBossAction(botAI); }
|
||||
|
||||
static Action* the_curator_spread_ranged(
|
||||
PlayerbotAI* botAI) { return new TheCuratorSpreadRangedAction(botAI); }
|
||||
|
||||
// Terestian Illhoof
|
||||
static Action* terestian_illhoof_mark_target(
|
||||
PlayerbotAI* botAI) { return new TerestianIllhoofMarkTargetAction(botAI); }
|
||||
|
||||
// Shade of Aran
|
||||
static Action* shade_of_aran_run_away_from_arcane_explosion(
|
||||
PlayerbotAI* botAI) { return new ShadeOfAranRunAwayFromArcaneExplosionAction(botAI); }
|
||||
|
||||
static Action* shade_of_aran_stop_moving_during_flame_wreath(
|
||||
PlayerbotAI* botAI) { return new ShadeOfAranStopMovingDuringFlameWreathAction(botAI); }
|
||||
|
||||
static Action* shade_of_aran_mark_conjured_elemental(
|
||||
PlayerbotAI* botAI) { return new ShadeOfAranMarkConjuredElementalAction(botAI); }
|
||||
|
||||
static Action* shade_of_aran_ranged_maintain_distance(
|
||||
PlayerbotAI* botAI) { return new ShadeOfAranRangedMaintainDistanceAction(botAI); }
|
||||
|
||||
// Netherspite
|
||||
static Action* netherspite_block_red_beam(
|
||||
PlayerbotAI* botAI) { return new NetherspiteBlockRedBeamAction(botAI); }
|
||||
|
||||
static Action* netherspite_block_blue_beam(
|
||||
PlayerbotAI* botAI) { return new NetherspiteBlockBlueBeamAction(botAI); }
|
||||
|
||||
static Action* netherspite_block_green_beam(
|
||||
PlayerbotAI* botAI) { return new NetherspiteBlockGreenBeamAction(botAI); }
|
||||
|
||||
static Action* netherspite_avoid_beam_and_void_zone(
|
||||
PlayerbotAI* botAI) { return new NetherspiteAvoidBeamAndVoidZoneAction(botAI); }
|
||||
|
||||
static Action* netherspite_banish_phase_avoid_void_zone(
|
||||
PlayerbotAI* botAI) { return new NetherspiteBanishPhaseAvoidVoidZoneAction(botAI); }
|
||||
|
||||
static Action* netherspite_manage_timers_and_trackers(
|
||||
PlayerbotAI* botAI) { return new NetherspiteManageTimersAndTrackersAction(botAI); }
|
||||
|
||||
// Prince Malchezaar
|
||||
static Action* prince_malchezaar_enfeebled_avoid_hazard(
|
||||
PlayerbotAI* botAI) { return new PrinceMalchezaarEnfeebledAvoidHazardAction(botAI); }
|
||||
|
||||
static Action* prince_malchezaar_non_tank_avoid_infernal(
|
||||
PlayerbotAI* botAI) { return new PrinceMalchezaarNonTankAvoidInfernalAction(botAI); }
|
||||
|
||||
static Action* prince_malchezaar_main_tank_movement(
|
||||
PlayerbotAI* botAI) { return new PrinceMalchezaarMainTankMovementAction(botAI); }
|
||||
|
||||
// Nightbane
|
||||
static Action* nightbane_ground_phase_position_boss(
|
||||
PlayerbotAI* botAI) { return new NightbaneGroundPhasePositionBossAction(botAI); }
|
||||
|
||||
static Action* nightbane_ground_phase_rotate_ranged_positions(
|
||||
PlayerbotAI* botAI) { return new NightbaneGroundPhaseRotateRangedPositionsAction(botAI); }
|
||||
|
||||
static Action* nightbane_cast_fear_ward_on_main_tank(
|
||||
PlayerbotAI* botAI) { return new NightbaneCastFearWardOnMainTankAction(botAI); }
|
||||
|
||||
static Action* nightbane_control_pet_aggression(
|
||||
PlayerbotAI* botAI) { return new NightbaneControlPetAggressionAction(botAI); }
|
||||
|
||||
static Action* nightbane_flight_phase_movement(
|
||||
PlayerbotAI* botAI) { return new NightbaneFlightPhaseMovementAction(botAI); }
|
||||
|
||||
static Action* nightbane_manage_timers_and_trackers(
|
||||
PlayerbotAI* botAI) { return new NightbaneManageTimersAndTrackersAction(botAI); }
|
||||
};
|
||||
|
||||
#endif
|
||||
263
src/Ai/Raid/Karazhan/RaidKarazhanTriggerContext.h
Normal file
263
src/Ai/Raid/Karazhan/RaidKarazhanTriggerContext.h
Normal file
@@ -0,0 +1,263 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANTRIGGERCONTEXT_H
|
||||
#define _PLAYERBOT_RAIDKARAZHANTRIGGERCONTEXT_H
|
||||
|
||||
#include "RaidKarazhanTriggers.h"
|
||||
#include "AiObjectContext.h"
|
||||
|
||||
class RaidKarazhanTriggerContext : public NamedObjectContext<Trigger>
|
||||
{
|
||||
public:
|
||||
RaidKarazhanTriggerContext()
|
||||
{
|
||||
// Trash
|
||||
creators["mana warp is about to explode"] =
|
||||
&RaidKarazhanTriggerContext::mana_warp_is_about_to_explode;
|
||||
|
||||
// Attumen the Huntsman
|
||||
creators["attumen the huntsman need target priority"] =
|
||||
&RaidKarazhanTriggerContext::attumen_the_huntsman_need_target_priority;
|
||||
|
||||
creators["attumen the huntsman attumen spawned"] =
|
||||
&RaidKarazhanTriggerContext::attumen_the_huntsman_attumen_spawned;
|
||||
|
||||
creators["attumen the huntsman attumen is mounted"] =
|
||||
&RaidKarazhanTriggerContext::attumen_the_huntsman_attumen_is_mounted;
|
||||
|
||||
creators["attumen the huntsman boss wipes aggro when mounting"] =
|
||||
&RaidKarazhanTriggerContext::attumen_the_huntsman_boss_wipes_aggro_when_mounting;
|
||||
|
||||
// Moroes
|
||||
creators["moroes boss engaged by main tank"] =
|
||||
&RaidKarazhanTriggerContext::moroes_boss_engaged_by_main_tank;
|
||||
|
||||
creators["moroes need target priority"] =
|
||||
&RaidKarazhanTriggerContext::moroes_need_target_priority;
|
||||
|
||||
// Maiden of Virtue
|
||||
creators["maiden of virtue healers are stunned by repentance"] =
|
||||
&RaidKarazhanTriggerContext::maiden_of_virtue_healers_are_stunned_by_repentance;
|
||||
|
||||
creators["maiden of virtue holy wrath deals chain damage"] =
|
||||
&RaidKarazhanTriggerContext::maiden_of_virtue_holy_wrath_deals_chain_damage;
|
||||
|
||||
// The Big Bad Wolf
|
||||
creators["big bad wolf boss engaged by tank"] =
|
||||
&RaidKarazhanTriggerContext::big_bad_wolf_boss_engaged_by_tank;
|
||||
|
||||
creators["big bad wolf boss is chasing little red riding hood"] =
|
||||
&RaidKarazhanTriggerContext::big_bad_wolf_boss_is_chasing_little_red_riding_hood;
|
||||
|
||||
// Romulo and Julianne
|
||||
creators["romulo and julianne both bosses revived"] =
|
||||
&RaidKarazhanTriggerContext::romulo_and_julianne_both_bosses_revived;
|
||||
|
||||
// The Wizard of Oz
|
||||
creators["wizard of oz need target priority"] =
|
||||
&RaidKarazhanTriggerContext::wizard_of_oz_need_target_priority;
|
||||
|
||||
creators["wizard of oz strawman is vulnerable to fire"] =
|
||||
&RaidKarazhanTriggerContext::wizard_of_oz_strawman_is_vulnerable_to_fire;
|
||||
|
||||
// The Curator
|
||||
creators["the curator astral flare spawned"] =
|
||||
&RaidKarazhanTriggerContext::the_curator_astral_flare_spawned;
|
||||
|
||||
creators["the curator boss engaged by tanks"] =
|
||||
&RaidKarazhanTriggerContext::the_curator_boss_engaged_by_tanks;
|
||||
|
||||
creators["the curator astral flares cast arcing sear"] =
|
||||
&RaidKarazhanTriggerContext::the_curator_astral_flares_cast_arcing_sear;
|
||||
|
||||
// Terestian Illhoof
|
||||
creators["terestian illhoof need target priority"] =
|
||||
&RaidKarazhanTriggerContext::terestian_illhoof_need_target_priority;
|
||||
|
||||
// Shade of Aran
|
||||
creators["shade of aran arcane explosion is casting"] =
|
||||
&RaidKarazhanTriggerContext::shade_of_aran_arcane_explosion_is_casting;
|
||||
|
||||
creators["shade of aran flame wreath is active"] =
|
||||
&RaidKarazhanTriggerContext::shade_of_aran_flame_wreath_is_active;
|
||||
|
||||
creators["shade of aran conjured elementals summoned"] =
|
||||
&RaidKarazhanTriggerContext::shade_of_aran_conjured_elementals_summoned;
|
||||
|
||||
creators["shade of aran boss uses counterspell and blizzard"] =
|
||||
&RaidKarazhanTriggerContext::shade_of_aran_boss_uses_counterspell_and_blizzard;
|
||||
|
||||
// Netherspite
|
||||
creators["netherspite red beam is active"] =
|
||||
&RaidKarazhanTriggerContext::netherspite_red_beam_is_active;
|
||||
|
||||
creators["netherspite blue beam is active"] =
|
||||
&RaidKarazhanTriggerContext::netherspite_blue_beam_is_active;
|
||||
|
||||
creators["netherspite green beam is active"] =
|
||||
&RaidKarazhanTriggerContext::netherspite_green_beam_is_active;
|
||||
|
||||
creators["netherspite bot is not beam blocker"] =
|
||||
&RaidKarazhanTriggerContext::netherspite_bot_is_not_beam_blocker;
|
||||
|
||||
creators["netherspite boss is banished"] =
|
||||
&RaidKarazhanTriggerContext::netherspite_boss_is_banished;
|
||||
|
||||
creators["netherspite need to manage timers and trackers"] =
|
||||
&RaidKarazhanTriggerContext::netherspite_need_to_manage_timers_and_trackers;
|
||||
|
||||
// Prince Malchezaar
|
||||
creators["prince malchezaar bot is enfeebled"] =
|
||||
&RaidKarazhanTriggerContext::prince_malchezaar_bot_is_enfeebled;
|
||||
|
||||
creators["prince malchezaar infernals are spawned"] =
|
||||
&RaidKarazhanTriggerContext::prince_malchezaar_infernals_are_spawned;
|
||||
|
||||
creators["prince malchezaar boss engaged by main tank"] =
|
||||
&RaidKarazhanTriggerContext::prince_malchezaar_boss_engaged_by_main_tank;
|
||||
|
||||
// Nightbane
|
||||
creators["nightbane boss engaged by main tank"] =
|
||||
&RaidKarazhanTriggerContext::nightbane_boss_engaged_by_main_tank;
|
||||
|
||||
creators["nightbane ranged bots are in charred earth"] =
|
||||
&RaidKarazhanTriggerContext::nightbane_ranged_bots_are_in_charred_earth;
|
||||
|
||||
creators["nightbane main tank is susceptible to fear"] =
|
||||
&RaidKarazhanTriggerContext::nightbane_main_tank_is_susceptible_to_fear;
|
||||
|
||||
creators["nightbane pets ignore collision to chase flying boss"] =
|
||||
&RaidKarazhanTriggerContext::nightbane_pets_ignore_collision_to_chase_flying_boss;
|
||||
|
||||
creators["nightbane boss is flying"] =
|
||||
&RaidKarazhanTriggerContext::nightbane_boss_is_flying;
|
||||
|
||||
creators["nightbane need to manage timers and trackers"] =
|
||||
&RaidKarazhanTriggerContext::nightbane_need_to_manage_timers_and_trackers;
|
||||
}
|
||||
|
||||
private:
|
||||
// Trash
|
||||
static Trigger* mana_warp_is_about_to_explode(
|
||||
PlayerbotAI* botAI) { return new ManaWarpIsAboutToExplodeTrigger(botAI); }
|
||||
|
||||
// Attumen the Huntsman
|
||||
static Trigger* attumen_the_huntsman_need_target_priority(
|
||||
PlayerbotAI* botAI) { return new AttumenTheHuntsmanNeedTargetPriorityTrigger(botAI); }
|
||||
|
||||
static Trigger* attumen_the_huntsman_attumen_spawned(
|
||||
PlayerbotAI* botAI) { return new AttumenTheHuntsmanAttumenSpawnedTrigger(botAI); }
|
||||
|
||||
static Trigger* attumen_the_huntsman_attumen_is_mounted(
|
||||
PlayerbotAI* botAI) { return new AttumenTheHuntsmanAttumenIsMountedTrigger(botAI); }
|
||||
|
||||
static Trigger* attumen_the_huntsman_boss_wipes_aggro_when_mounting(
|
||||
PlayerbotAI* botAI) { return new AttumenTheHuntsmanBossWipesAggroWhenMountingTrigger(botAI); }
|
||||
|
||||
// Moroes
|
||||
static Trigger* moroes_boss_engaged_by_main_tank(
|
||||
PlayerbotAI* botAI) { return new MoroesBossEngagedByMainTankTrigger(botAI); }
|
||||
|
||||
static Trigger* moroes_need_target_priority(
|
||||
PlayerbotAI* botAI) { return new MoroesNeedTargetPriorityTrigger(botAI); }
|
||||
|
||||
// Maiden of Virtue
|
||||
static Trigger* maiden_of_virtue_healers_are_stunned_by_repentance(
|
||||
PlayerbotAI* botAI) { return new MaidenOfVirtueHealersAreStunnedByRepentanceTrigger(botAI); }
|
||||
|
||||
static Trigger* maiden_of_virtue_holy_wrath_deals_chain_damage(
|
||||
PlayerbotAI* botAI) { return new MaidenOfVirtueHolyWrathDealsChainDamageTrigger(botAI); }
|
||||
|
||||
// The Big Bad Wolf
|
||||
static Trigger* big_bad_wolf_boss_engaged_by_tank(
|
||||
PlayerbotAI* botAI) { return new BigBadWolfBossEngagedByTankTrigger(botAI); }
|
||||
|
||||
static Trigger* big_bad_wolf_boss_is_chasing_little_red_riding_hood(
|
||||
PlayerbotAI* botAI) { return new BigBadWolfBossIsChasingLittleRedRidingHoodTrigger(botAI); }
|
||||
|
||||
// Romulo and Julianne
|
||||
static Trigger* romulo_and_julianne_both_bosses_revived(
|
||||
PlayerbotAI* botAI) { return new RomuloAndJulianneBothBossesRevivedTrigger(botAI); }
|
||||
|
||||
// The Wizard of Oz
|
||||
static Trigger* wizard_of_oz_need_target_priority(
|
||||
PlayerbotAI* botAI) { return new WizardOfOzNeedTargetPriorityTrigger(botAI); }
|
||||
|
||||
static Trigger* wizard_of_oz_strawman_is_vulnerable_to_fire(
|
||||
PlayerbotAI* botAI) { return new WizardOfOzStrawmanIsVulnerableToFireTrigger(botAI); }
|
||||
|
||||
// The Curator
|
||||
static Trigger* the_curator_astral_flare_spawned(
|
||||
PlayerbotAI* botAI) { return new TheCuratorAstralFlareSpawnedTrigger(botAI); }
|
||||
|
||||
static Trigger* the_curator_boss_engaged_by_tanks(
|
||||
PlayerbotAI* botAI) { return new TheCuratorBossEngagedByTanksTrigger(botAI); }
|
||||
|
||||
static Trigger* the_curator_astral_flares_cast_arcing_sear(
|
||||
PlayerbotAI* botAI) { return new TheCuratorBossAstralFlaresCastArcingSearTrigger(botAI); }
|
||||
|
||||
// Terestian Illhoof
|
||||
static Trigger* terestian_illhoof_need_target_priority(
|
||||
PlayerbotAI* botAI) { return new TerestianIllhoofNeedTargetPriorityTrigger(botAI); }
|
||||
|
||||
// Shade of Aran
|
||||
static Trigger* shade_of_aran_arcane_explosion_is_casting(
|
||||
PlayerbotAI* botAI) { return new ShadeOfAranArcaneExplosionIsCastingTrigger(botAI); }
|
||||
|
||||
static Trigger* shade_of_aran_flame_wreath_is_active(
|
||||
PlayerbotAI* botAI) { return new ShadeOfAranFlameWreathIsActiveTrigger(botAI); }
|
||||
|
||||
static Trigger* shade_of_aran_conjured_elementals_summoned(
|
||||
PlayerbotAI* botAI) { return new ShadeOfAranConjuredElementalsSummonedTrigger(botAI); }
|
||||
|
||||
static Trigger* shade_of_aran_boss_uses_counterspell_and_blizzard(
|
||||
PlayerbotAI* botAI) { return new ShadeOfAranBossUsesCounterspellAndBlizzardTrigger(botAI); }
|
||||
|
||||
// Netherspite
|
||||
static Trigger* netherspite_red_beam_is_active(
|
||||
PlayerbotAI* botAI) { return new NetherspiteRedBeamIsActiveTrigger(botAI); }
|
||||
|
||||
static Trigger* netherspite_blue_beam_is_active(
|
||||
PlayerbotAI* botAI) { return new NetherspiteBlueBeamIsActiveTrigger(botAI); }
|
||||
|
||||
static Trigger* netherspite_green_beam_is_active(
|
||||
PlayerbotAI* botAI) { return new NetherspiteGreenBeamIsActiveTrigger(botAI); }
|
||||
|
||||
static Trigger* netherspite_bot_is_not_beam_blocker(
|
||||
PlayerbotAI* botAI) { return new NetherspiteBotIsNotBeamBlockerTrigger(botAI); }
|
||||
|
||||
static Trigger* netherspite_boss_is_banished(
|
||||
PlayerbotAI* botAI) { return new NetherspiteBossIsBanishedTrigger(botAI); }
|
||||
|
||||
static Trigger* netherspite_need_to_manage_timers_and_trackers(
|
||||
PlayerbotAI* botAI) { return new NetherspiteNeedToManageTimersAndTrackersTrigger(botAI); }
|
||||
|
||||
// Prince Malchezaar
|
||||
static Trigger* prince_malchezaar_bot_is_enfeebled(
|
||||
PlayerbotAI* botAI) { return new PrinceMalchezaarBotIsEnfeebledTrigger(botAI); }
|
||||
|
||||
static Trigger* prince_malchezaar_infernals_are_spawned(
|
||||
PlayerbotAI* botAI) { return new PrinceMalchezaarInfernalsAreSpawnedTrigger(botAI); }
|
||||
|
||||
static Trigger* prince_malchezaar_boss_engaged_by_main_tank(
|
||||
PlayerbotAI* botAI) { return new PrinceMalchezaarBossEngagedByMainTankTrigger(botAI); }
|
||||
|
||||
// Nightbane
|
||||
static Trigger* nightbane_boss_engaged_by_main_tank(
|
||||
PlayerbotAI* botAI) { return new NightbaneBossEngagedByMainTankTrigger(botAI); }
|
||||
|
||||
static Trigger* nightbane_ranged_bots_are_in_charred_earth(
|
||||
PlayerbotAI* botAI) { return new NightbaneRangedBotsAreInCharredEarthTrigger(botAI); }
|
||||
|
||||
static Trigger* nightbane_main_tank_is_susceptible_to_fear(
|
||||
PlayerbotAI* botAI) { return new NightbaneMainTankIsSusceptibleToFearTrigger(botAI); }
|
||||
|
||||
static Trigger* nightbane_pets_ignore_collision_to_chase_flying_boss(
|
||||
PlayerbotAI* botAI) { return new NightbanePetsIgnoreCollisionToChaseFlyingBossTrigger(botAI); }
|
||||
|
||||
static Trigger* nightbane_boss_is_flying(
|
||||
PlayerbotAI* botAI) { return new NightbaneBossIsFlyingTrigger(botAI); }
|
||||
|
||||
static Trigger* nightbane_need_to_manage_timers_and_trackers(
|
||||
PlayerbotAI* botAI) { return new NightbaneNeedToManageTimersAndTrackersTrigger(botAI); }
|
||||
};
|
||||
|
||||
#endif
|
||||
162
src/Ai/Raid/Karazhan/Strategy/RaidKarazhanStrategy.cpp
Normal file
162
src/Ai/Raid/Karazhan/Strategy/RaidKarazhanStrategy.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#include "RaidKarazhanStrategy.h"
|
||||
#include "RaidKarazhanMultipliers.h"
|
||||
|
||||
void RaidKarazhanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
// Trash
|
||||
triggers.push_back(new TriggerNode("mana warp is about to explode",
|
||||
{ NextAction("mana warp stun creature before warp breach", ACTION_EMERGENCY + 6) }
|
||||
));
|
||||
|
||||
// Attumen the Huntsman
|
||||
triggers.push_back(new TriggerNode("attumen the huntsman need target priority",
|
||||
{ NextAction("attumen the huntsman mark target", ACTION_RAID + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("attumen the huntsman attumen spawned",
|
||||
{ NextAction("attumen the huntsman split bosses", ACTION_RAID + 2) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("attumen the huntsman attumen is mounted",
|
||||
{ NextAction("attumen the huntsman stack behind", ACTION_RAID + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("attumen the huntsman boss wipes aggro when mounting",
|
||||
{ NextAction("attumen the huntsman manage dps timer", ACTION_RAID + 2) }
|
||||
));
|
||||
|
||||
// Moroes
|
||||
triggers.push_back(new TriggerNode("moroes boss engaged by main tank",
|
||||
{ NextAction("moroes main tank attack boss", ACTION_RAID + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("moroes need target priority",
|
||||
{ NextAction("moroes mark target", ACTION_RAID + 1) }
|
||||
));
|
||||
|
||||
// Maiden of Virtue
|
||||
triggers.push_back(new TriggerNode("maiden of virtue healers are stunned by repentance",
|
||||
{ NextAction("maiden of virtue move boss to healer", ACTION_RAID + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("maiden of virtue holy wrath deals chain damage",
|
||||
{ NextAction("maiden of virtue position ranged", ACTION_RAID + 1) }
|
||||
));
|
||||
|
||||
// The Big Bad Wolf
|
||||
triggers.push_back(new TriggerNode("big bad wolf boss is chasing little red riding hood",
|
||||
{ NextAction("big bad wolf run away from boss", ACTION_EMERGENCY + 6) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("big bad wolf boss engaged by tank",
|
||||
{ NextAction("big bad wolf position boss", ACTION_RAID + 1) }
|
||||
));
|
||||
|
||||
// Romulo and Julianne
|
||||
triggers.push_back(new TriggerNode("romulo and julianne both bosses revived",
|
||||
{ NextAction("romulo and julianne mark target", ACTION_RAID + 1) }
|
||||
));
|
||||
|
||||
// The Wizard of Oz
|
||||
triggers.push_back(new TriggerNode("wizard of oz need target priority",
|
||||
{ NextAction("wizard of oz mark target", ACTION_RAID + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("wizard of oz strawman is vulnerable to fire",
|
||||
{ NextAction("wizard of oz scorch strawman", ACTION_RAID + 2) }
|
||||
));
|
||||
|
||||
// The Curator
|
||||
triggers.push_back(new TriggerNode("the curator astral flare spawned",
|
||||
{ NextAction("the curator mark astral flare", ACTION_RAID + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("the curator boss engaged by tanks",
|
||||
{ NextAction("the curator position boss", ACTION_RAID + 2) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("the curator astral flares cast arcing sear",
|
||||
{ NextAction("the curator spread ranged", ACTION_RAID + 2) }
|
||||
));
|
||||
|
||||
// Terestian Illhoof
|
||||
triggers.push_back(new TriggerNode("terestian illhoof need target priority",
|
||||
{ NextAction("terestian illhoof mark target", ACTION_RAID + 1) }
|
||||
));
|
||||
|
||||
// Shade of Aran
|
||||
triggers.push_back(new TriggerNode("shade of aran arcane explosion is casting",
|
||||
{ NextAction("shade of aran run away from arcane explosion", ACTION_EMERGENCY + 6) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("shade of aran flame wreath is active",
|
||||
{ NextAction("shade of aran stop moving during flame wreath", ACTION_EMERGENCY + 7) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("shade of aran conjured elementals summoned",
|
||||
{ NextAction("shade of aran mark conjured elemental", ACTION_RAID + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("shade of aran boss uses counterspell and blizzard",
|
||||
{ NextAction("shade of aran ranged maintain distance", ACTION_RAID + 2) }
|
||||
));
|
||||
|
||||
// Netherspite
|
||||
triggers.push_back(new TriggerNode("netherspite red beam is active",
|
||||
{ NextAction("netherspite block red beam", ACTION_EMERGENCY + 8) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("netherspite blue beam is active",
|
||||
{ NextAction("netherspite block blue beam", ACTION_EMERGENCY + 8) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("netherspite green beam is active",
|
||||
{ NextAction("netherspite block green beam", ACTION_EMERGENCY + 8) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("netherspite bot is not beam blocker",
|
||||
{ NextAction("netherspite avoid beam and void zone", ACTION_EMERGENCY + 7) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("netherspite boss is banished",
|
||||
{ NextAction("netherspite banish phase avoid void zone", ACTION_RAID + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("netherspite need to manage timers and trackers",
|
||||
{ NextAction("netherspite manage timers and trackers", ACTION_EMERGENCY + 10) }
|
||||
));
|
||||
|
||||
// Prince Malchezaar
|
||||
triggers.push_back(new TriggerNode("prince malchezaar bot is enfeebled",
|
||||
{ NextAction("prince malchezaar enfeebled avoid hazard", ACTION_EMERGENCY + 6) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("prince malchezaar infernals are spawned",
|
||||
{ NextAction("prince malchezaar non tank avoid infernal", ACTION_EMERGENCY + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("prince malchezaar boss engaged by main tank",
|
||||
{ NextAction("prince malchezaar main tank movement", ACTION_EMERGENCY + 6) }
|
||||
));
|
||||
|
||||
// Nightbane
|
||||
triggers.push_back(new TriggerNode("nightbane boss engaged by main tank",
|
||||
{ NextAction("nightbane ground phase position boss", ACTION_RAID + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("nightbane ranged bots are in charred earth",
|
||||
{ NextAction("nightbane ground phase rotate ranged positions", ACTION_EMERGENCY + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("nightbane main tank is susceptible to fear",
|
||||
{ NextAction("nightbane cast fear ward on main tank", ACTION_RAID + 2) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("nightbane pets ignore collision to chase flying boss",
|
||||
{ NextAction("nightbane control pet aggression", ACTION_RAID + 2) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("nightbane boss is flying",
|
||||
{ NextAction("nightbane flight phase movement", ACTION_RAID + 1) }
|
||||
));
|
||||
triggers.push_back(new TriggerNode("nightbane need to manage timers and trackers",
|
||||
{ NextAction("nightbane manage timers and trackers", ACTION_EMERGENCY + 10) }
|
||||
));
|
||||
}
|
||||
|
||||
void RaidKarazhanStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
||||
{
|
||||
multipliers.push_back(new AttumenTheHuntsmanDisableTankAssistMultiplier(botAI));
|
||||
multipliers.push_back(new AttumenTheHuntsmanStayStackedMultiplier(botAI));
|
||||
multipliers.push_back(new AttumenTheHuntsmanWaitForDpsMultiplier(botAI));
|
||||
multipliers.push_back(new TheCuratorDisableTankAssistMultiplier(botAI));
|
||||
multipliers.push_back(new TheCuratorDelayBloodlustAndHeroismMultiplier(botAI));
|
||||
multipliers.push_back(new ShadeOfAranArcaneExplosionDisableChargeMultiplier(botAI));
|
||||
multipliers.push_back(new ShadeOfAranFlameWreathDisableMovementMultiplier(botAI));
|
||||
multipliers.push_back(new NetherspiteKeepBlockingBeamMultiplier(botAI));
|
||||
multipliers.push_back(new NetherspiteWaitForDpsMultiplier(botAI));
|
||||
multipliers.push_back(new PrinceMalchezaarDisableAvoidAoeMultiplier(botAI));
|
||||
multipliers.push_back(new PrinceMalchezaarEnfeebleKeepDistanceMultiplier(botAI));
|
||||
multipliers.push_back(new PrinceMalchezaarDelayBloodlustAndHeroismMultiplier(botAI));
|
||||
multipliers.push_back(new NightbaneDisablePetsMultiplier(botAI));
|
||||
multipliers.push_back(new NightbaneWaitForDpsMultiplier(botAI));
|
||||
multipliers.push_back(new NightbaneDisableAvoidAoeMultiplier(botAI));
|
||||
multipliers.push_back(new NightbaneDisableMovementMultiplier(botAI));
|
||||
}
|
||||
18
src/Ai/Raid/Karazhan/Strategy/RaidKarazhanStrategy.h
Normal file
18
src/Ai/Raid/Karazhan/Strategy/RaidKarazhanStrategy.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANSTRATEGY_H_
|
||||
#define _PLAYERBOT_RAIDKARAZHANSTRATEGY_H_
|
||||
|
||||
#include "Strategy.h"
|
||||
#include "Multiplier.h"
|
||||
|
||||
class RaidKarazhanStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
RaidKarazhanStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
std::string const getName() override { return "karazhan"; }
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
385
src/Ai/Raid/Karazhan/Trigger/RaidKarazhanTriggers.cpp
Normal file
385
src/Ai/Raid/Karazhan/Trigger/RaidKarazhanTriggers.cpp
Normal file
@@ -0,0 +1,385 @@
|
||||
#include "RaidKarazhanTriggers.h"
|
||||
#include "RaidKarazhanHelpers.h"
|
||||
#include "RaidKarazhanActions.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
using namespace KarazhanHelpers;
|
||||
|
||||
bool ManaWarpIsAboutToExplodeTrigger::IsActive()
|
||||
{
|
||||
Unit* manaWarp = AI_VALUE2(Unit*, "find target", "mana warp");
|
||||
return manaWarp && manaWarp->GetHealthPct() < 15;
|
||||
}
|
||||
|
||||
bool AttumenTheHuntsmanNeedTargetPriorityTrigger::IsActive()
|
||||
{
|
||||
if (botAI->IsHeal(bot))
|
||||
return false;
|
||||
|
||||
Unit* midnight = AI_VALUE2(Unit*, "find target", "midnight");
|
||||
return midnight != nullptr;
|
||||
}
|
||||
|
||||
bool AttumenTheHuntsmanAttumenSpawnedTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsAssistTankOfIndex(bot, 0))
|
||||
return false;
|
||||
|
||||
Unit* attumen = GetFirstAliveUnitByEntry(botAI, NPC_ATTUMEN_THE_HUNTSMAN);
|
||||
return attumen != nullptr;
|
||||
}
|
||||
|
||||
bool AttumenTheHuntsmanAttumenIsMountedTrigger::IsActive()
|
||||
{
|
||||
if (botAI->IsMainTank(bot))
|
||||
return false;
|
||||
|
||||
Unit* attumenMounted = GetFirstAliveUnitByEntry(botAI, NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED);
|
||||
return attumenMounted && attumenMounted->GetVictim() != bot;
|
||||
}
|
||||
|
||||
bool AttumenTheHuntsmanBossWipesAggroWhenMountingTrigger::IsActive()
|
||||
{
|
||||
if (!IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* midnight = AI_VALUE2(Unit*, "find target", "midnight");
|
||||
return midnight != nullptr;
|
||||
}
|
||||
|
||||
bool MoroesBossEngagedByMainTankTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsMainTank(bot))
|
||||
return false;
|
||||
|
||||
Unit* moroes = AI_VALUE2(Unit*, "find target", "moroes");
|
||||
return moroes != nullptr;
|
||||
}
|
||||
|
||||
bool MoroesNeedTargetPriorityTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsDps(bot))
|
||||
return false;
|
||||
|
||||
Unit* dorothea = AI_VALUE2(Unit*, "find target", "baroness dorothea millstipe");
|
||||
Unit* catriona = AI_VALUE2(Unit*, "find target", "lady catriona von'indi");
|
||||
Unit* keira = AI_VALUE2(Unit*, "find target", "lady keira berrybuck");
|
||||
Unit* rafe = AI_VALUE2(Unit*, "find target", "baron rafe dreuger");
|
||||
Unit* robin = AI_VALUE2(Unit*, "find target", "lord robin daris");
|
||||
Unit* crispin = AI_VALUE2(Unit*, "find target", "lord crispin ference");
|
||||
|
||||
Unit* target = GetFirstAliveUnit({ dorothea, catriona, keira, rafe, robin, crispin });
|
||||
return target != nullptr;
|
||||
}
|
||||
|
||||
bool MaidenOfVirtueHealersAreStunnedByRepentanceTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsTank(bot))
|
||||
return false;
|
||||
|
||||
Unit* maiden = AI_VALUE2(Unit*, "find target", "maiden of virtue");
|
||||
return maiden && maiden->GetVictim() == bot;
|
||||
}
|
||||
|
||||
bool MaidenOfVirtueHolyWrathDealsChainDamageTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsRanged(bot))
|
||||
return false;
|
||||
|
||||
Unit* maiden = AI_VALUE2(Unit*, "find target", "maiden of virtue");
|
||||
return maiden != nullptr;
|
||||
}
|
||||
|
||||
bool BigBadWolfBossEngagedByTankTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsTank(bot) || bot->HasAura(SPELL_LITTLE_RED_RIDING_HOOD))
|
||||
return false;
|
||||
|
||||
Unit* wolf = AI_VALUE2(Unit*, "find target", "the big bad wolf");
|
||||
return wolf != nullptr;
|
||||
}
|
||||
|
||||
bool BigBadWolfBossIsChasingLittleRedRidingHoodTrigger::IsActive()
|
||||
{
|
||||
if (!bot->HasAura(SPELL_LITTLE_RED_RIDING_HOOD))
|
||||
return false;
|
||||
|
||||
Unit* wolf = AI_VALUE2(Unit*, "find target", "the big bad wolf");
|
||||
return wolf != nullptr;
|
||||
}
|
||||
|
||||
bool RomuloAndJulianneBothBossesRevivedTrigger::IsActive()
|
||||
{
|
||||
if (!IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* romulo = AI_VALUE2(Unit*, "find target", "romulo");
|
||||
if (!romulo)
|
||||
return false;
|
||||
|
||||
Unit* julianne = AI_VALUE2(Unit*, "find target", "julianne");
|
||||
if (!julianne)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WizardOfOzNeedTargetPriorityTrigger::IsActive()
|
||||
{
|
||||
if (!IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* dorothee = AI_VALUE2(Unit*, "find target", "dorothee");
|
||||
Unit* tito = AI_VALUE2(Unit*, "find target", "tito");
|
||||
Unit* roar = AI_VALUE2(Unit*, "find target", "roar");
|
||||
Unit* strawman = AI_VALUE2(Unit*, "find target", "strawman");
|
||||
Unit* tinhead = AI_VALUE2(Unit*, "find target", "tinhead");
|
||||
Unit* crone = AI_VALUE2(Unit*, "find target", "the crone");
|
||||
|
||||
Unit* target = GetFirstAliveUnit({ dorothee, tito, roar, strawman, tinhead, crone });
|
||||
return target != nullptr;
|
||||
}
|
||||
|
||||
bool WizardOfOzStrawmanIsVulnerableToFireTrigger::IsActive()
|
||||
{
|
||||
if (bot->getClass() != CLASS_MAGE)
|
||||
return false;
|
||||
|
||||
Unit* strawman = AI_VALUE2(Unit*, "find target", "strawman");
|
||||
return strawman && strawman->IsAlive();
|
||||
}
|
||||
|
||||
bool TheCuratorAstralFlareSpawnedTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsDps(bot))
|
||||
return false;
|
||||
|
||||
Unit* flare = AI_VALUE2(Unit*, "find target", "astral flare");
|
||||
return flare != nullptr;
|
||||
}
|
||||
|
||||
bool TheCuratorBossEngagedByTanksTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsMainTank(bot) && !botAI->IsAssistTankOfIndex(bot, 0))
|
||||
return false;
|
||||
|
||||
Unit* curator = AI_VALUE2(Unit*, "find target", "the curator");
|
||||
return curator != nullptr;
|
||||
}
|
||||
|
||||
bool TheCuratorBossAstralFlaresCastArcingSearTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsRanged(bot))
|
||||
return false;
|
||||
|
||||
Unit* curator = AI_VALUE2(Unit*, "find target", "the curator");
|
||||
return curator != nullptr;
|
||||
}
|
||||
|
||||
bool TerestianIllhoofNeedTargetPriorityTrigger::IsActive()
|
||||
{
|
||||
if (!IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* illhoof = AI_VALUE2(Unit*, "find target", "terestian illhoof");
|
||||
return illhoof != nullptr;
|
||||
}
|
||||
|
||||
bool ShadeOfAranArcaneExplosionIsCastingTrigger::IsActive()
|
||||
{
|
||||
Unit* aran = AI_VALUE2(Unit*, "find target", "shade of aran");
|
||||
return aran && aran->HasUnitState(UNIT_STATE_CASTING) &&
|
||||
aran->FindCurrentSpellBySpellId(SPELL_ARCANE_EXPLOSION) &&
|
||||
!IsFlameWreathActive(botAI, bot);
|
||||
}
|
||||
|
||||
bool ShadeOfAranFlameWreathIsActiveTrigger::IsActive()
|
||||
{
|
||||
Unit* aran = AI_VALUE2(Unit*, "find target", "shade of aran");
|
||||
return aran && IsFlameWreathActive(botAI, bot);
|
||||
}
|
||||
|
||||
// Exclusion of Banish is so the player may Banish elementals if they wish
|
||||
bool ShadeOfAranConjuredElementalsSummonedTrigger::IsActive()
|
||||
{
|
||||
if (!IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* elemental = AI_VALUE2(Unit*, "find target", "conjured elemental");
|
||||
return elemental && elemental->IsAlive() &&
|
||||
!elemental->HasAura(SPELL_WARLOCK_BANISH);
|
||||
}
|
||||
|
||||
bool ShadeOfAranBossUsesCounterspellAndBlizzardTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsRanged(bot))
|
||||
return false;
|
||||
|
||||
Unit* aran = AI_VALUE2(Unit*, "find target", "shade of aran");
|
||||
return aran && !(aran->HasUnitState(UNIT_STATE_CASTING) &&
|
||||
aran->FindCurrentSpellBySpellId(SPELL_ARCANE_EXPLOSION)) &&
|
||||
!IsFlameWreathActive(botAI, bot);
|
||||
}
|
||||
|
||||
bool NetherspiteRedBeamIsActiveTrigger::IsActive()
|
||||
{
|
||||
Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
if (!netherspite || netherspite->HasAura(SPELL_NETHERSPITE_BANISHED))
|
||||
return false;
|
||||
|
||||
Unit* redPortal = bot->FindNearestCreature(NPC_RED_PORTAL, 150.0f);
|
||||
return redPortal != nullptr;
|
||||
}
|
||||
|
||||
bool NetherspiteBlueBeamIsActiveTrigger::IsActive()
|
||||
{
|
||||
Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
if (!netherspite || netherspite->HasAura(SPELL_NETHERSPITE_BANISHED))
|
||||
return false;
|
||||
|
||||
Unit* bluePortal = bot->FindNearestCreature(NPC_BLUE_PORTAL, 150.0f);
|
||||
return bluePortal != nullptr;
|
||||
}
|
||||
|
||||
bool NetherspiteGreenBeamIsActiveTrigger::IsActive()
|
||||
{
|
||||
Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
if (!netherspite || netherspite->HasAura(SPELL_NETHERSPITE_BANISHED))
|
||||
return false;
|
||||
|
||||
Unit* greenPortal = bot->FindNearestCreature(NPC_GREEN_PORTAL, 150.0f);
|
||||
return greenPortal != nullptr;
|
||||
}
|
||||
|
||||
bool NetherspiteBotIsNotBeamBlockerTrigger::IsActive()
|
||||
{
|
||||
Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
if (!netherspite || netherspite->HasAura(SPELL_NETHERSPITE_BANISHED))
|
||||
return false;
|
||||
|
||||
auto [redBlocker, greenBlocker, blueBlocker] = GetCurrentBeamBlockers(botAI, bot);
|
||||
return bot != redBlocker && bot != blueBlocker && bot != greenBlocker;
|
||||
}
|
||||
|
||||
bool NetherspiteBossIsBanishedTrigger::IsActive()
|
||||
{
|
||||
Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
if (!netherspite || !netherspite->HasAura(SPELL_NETHERSPITE_BANISHED))
|
||||
return false;
|
||||
|
||||
std::vector<Unit*> voidZones = GetAllVoidZones(botAI, bot);
|
||||
for (Unit* vz : voidZones)
|
||||
{
|
||||
if (bot->GetExactDist2d(vz) < 4.0f)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetherspiteNeedToManageTimersAndTrackersTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsTank(bot) && !IsInstanceTimerManager(botAI, bot))
|
||||
return false;
|
||||
|
||||
Unit* netherspite = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
return netherspite != nullptr;
|
||||
}
|
||||
|
||||
bool PrinceMalchezaarBotIsEnfeebledTrigger::IsActive()
|
||||
{
|
||||
return bot->HasAura(SPELL_ENFEEBLE);
|
||||
}
|
||||
|
||||
bool PrinceMalchezaarInfernalsAreSpawnedTrigger::IsActive()
|
||||
{
|
||||
if (botAI->IsMainTank(bot) || bot->HasAura(SPELL_ENFEEBLE))
|
||||
return false;
|
||||
|
||||
Unit* malchezaar = AI_VALUE2(Unit*, "find target", "prince malchezaar");
|
||||
return malchezaar != nullptr;
|
||||
}
|
||||
|
||||
bool PrinceMalchezaarBossEngagedByMainTankTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsMainTank(bot))
|
||||
return false;
|
||||
|
||||
Unit* malchezaar = AI_VALUE2(Unit*, "find target", "prince malchezaar");
|
||||
return malchezaar != nullptr;
|
||||
}
|
||||
|
||||
bool NightbaneBossEngagedByMainTankTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsMainTank(bot))
|
||||
return false;
|
||||
|
||||
Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane");
|
||||
return nightbane && nightbane->GetPositionZ() <= NIGHTBANE_FLIGHT_Z;
|
||||
}
|
||||
|
||||
bool NightbaneRangedBotsAreInCharredEarthTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->IsRanged(bot))
|
||||
return false;
|
||||
|
||||
Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane");
|
||||
return nightbane && nightbane->GetPositionZ() <= NIGHTBANE_FLIGHT_Z;
|
||||
}
|
||||
|
||||
bool NightbaneMainTankIsSusceptibleToFearTrigger::IsActive()
|
||||
{
|
||||
if (bot->getClass() != CLASS_PRIEST)
|
||||
return false;
|
||||
|
||||
Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane");
|
||||
if (!nightbane)
|
||||
return false;
|
||||
|
||||
Player* mainTank = nullptr;
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
||||
{
|
||||
Player* member = ref->GetSource();
|
||||
if (member && botAI->IsMainTank(member))
|
||||
{
|
||||
mainTank = member;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mainTank && !mainTank->HasAura(SPELL_FEAR_WARD) &&
|
||||
botAI->CanCastSpell("fear ward", mainTank);
|
||||
}
|
||||
|
||||
bool NightbanePetsIgnoreCollisionToChaseFlyingBossTrigger::IsActive()
|
||||
{
|
||||
Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane");
|
||||
if (!nightbane)
|
||||
return false;
|
||||
|
||||
Pet* pet = bot->GetPet();
|
||||
return pet && pet->IsAlive();
|
||||
}
|
||||
|
||||
bool NightbaneBossIsFlyingTrigger::IsActive()
|
||||
{
|
||||
Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane");
|
||||
if (!nightbane || nightbane->GetPositionZ() <= NIGHTBANE_FLIGHT_Z)
|
||||
return false;
|
||||
|
||||
const uint32 instanceId = nightbane->GetMap()->GetInstanceId();
|
||||
const time_t now = std::time(nullptr);
|
||||
const uint8 flightPhaseDurationSeconds = 35;
|
||||
|
||||
return nightbaneFlightPhaseStartTimer.find(instanceId) != nightbaneFlightPhaseStartTimer.end() &&
|
||||
(now - nightbaneFlightPhaseStartTimer[instanceId] < flightPhaseDurationSeconds);
|
||||
}
|
||||
|
||||
bool NightbaneNeedToManageTimersAndTrackersTrigger::IsActive()
|
||||
{
|
||||
Unit* nightbane = AI_VALUE2(Unit*, "find target", "nightbane");
|
||||
return nightbane != nullptr;
|
||||
}
|
||||
301
src/Ai/Raid/Karazhan/Trigger/RaidKarazhanTriggers.h
Normal file
301
src/Ai/Raid/Karazhan/Trigger/RaidKarazhanTriggers.h
Normal file
@@ -0,0 +1,301 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANTRIGGERS_H
|
||||
#define _PLAYERBOT_RAIDKARAZHANTRIGGERS_H
|
||||
|
||||
#include "Trigger.h"
|
||||
|
||||
class ManaWarpIsAboutToExplodeTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
ManaWarpIsAboutToExplodeTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "mana warp is about to explode") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class AttumenTheHuntsmanNeedTargetPriorityTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
AttumenTheHuntsmanNeedTargetPriorityTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "attumen the huntsman need target priority") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class AttumenTheHuntsmanAttumenSpawnedTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
AttumenTheHuntsmanAttumenSpawnedTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "attumen the huntsman attumen spawned") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class AttumenTheHuntsmanAttumenIsMountedTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
AttumenTheHuntsmanAttumenIsMountedTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "attumen the huntsman attumen is mounted") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class AttumenTheHuntsmanBossWipesAggroWhenMountingTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
AttumenTheHuntsmanBossWipesAggroWhenMountingTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "attumen the huntsman boss wipes aggro when mounting") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class MoroesBossEngagedByMainTankTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
MoroesBossEngagedByMainTankTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "moroes boss engaged by main tank") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class MoroesNeedTargetPriorityTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
MoroesNeedTargetPriorityTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "moroes need target priority") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class MaidenOfVirtueHealersAreStunnedByRepentanceTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
MaidenOfVirtueHealersAreStunnedByRepentanceTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "maiden of virtue healers are stunned by repentance") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class MaidenOfVirtueHolyWrathDealsChainDamageTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
MaidenOfVirtueHolyWrathDealsChainDamageTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "maiden of virtue holy wrath deals chain damage") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class BigBadWolfBossEngagedByTankTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
BigBadWolfBossEngagedByTankTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "big bad wolf boss engaged by tank") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class BigBadWolfBossIsChasingLittleRedRidingHoodTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
BigBadWolfBossIsChasingLittleRedRidingHoodTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "big bad wolf boss is chasing little red riding hood") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class RomuloAndJulianneBothBossesRevivedTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
RomuloAndJulianneBothBossesRevivedTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "romulo and julianne both bosses revived") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class WizardOfOzNeedTargetPriorityTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
WizardOfOzNeedTargetPriorityTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "wizard of oz need target priority") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class WizardOfOzStrawmanIsVulnerableToFireTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
WizardOfOzStrawmanIsVulnerableToFireTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "wizard of oz strawman is vulnerable to fire") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
class TheCuratorAstralFlareSpawnedTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
TheCuratorAstralFlareSpawnedTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "the curator astral flare spawned") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class TheCuratorBossEngagedByTanksTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
TheCuratorBossEngagedByTanksTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "the curator boss engaged by tanks") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class TheCuratorBossAstralFlaresCastArcingSearTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
TheCuratorBossAstralFlaresCastArcingSearTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "the curator astral flares cast arcing sear") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class TerestianIllhoofNeedTargetPriorityTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
TerestianIllhoofNeedTargetPriorityTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "terestian illhoof need target priority") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class ShadeOfAranArcaneExplosionIsCastingTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
ShadeOfAranArcaneExplosionIsCastingTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "shade of aran arcane explosion is casting") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class ShadeOfAranFlameWreathIsActiveTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
ShadeOfAranFlameWreathIsActiveTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "shade of aran flame wreath is active") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class ShadeOfAranConjuredElementalsSummonedTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
ShadeOfAranConjuredElementalsSummonedTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "shade of aran conjured elementals summoned") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class ShadeOfAranBossUsesCounterspellAndBlizzardTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
ShadeOfAranBossUsesCounterspellAndBlizzardTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "shade of aran boss uses counterspell and blizzard") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NetherspiteRedBeamIsActiveTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NetherspiteRedBeamIsActiveTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "netherspite red beam is active") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NetherspiteBlueBeamIsActiveTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NetherspiteBlueBeamIsActiveTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "netherspite blue beam is active") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NetherspiteGreenBeamIsActiveTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NetherspiteGreenBeamIsActiveTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "netherspite green beam is active") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NetherspiteBotIsNotBeamBlockerTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NetherspiteBotIsNotBeamBlockerTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "netherspite bot is not beam blocker") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NetherspiteBossIsBanishedTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NetherspiteBossIsBanishedTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "netherspite boss is banished") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NetherspiteNeedToManageTimersAndTrackersTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NetherspiteNeedToManageTimersAndTrackersTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "netherspite need to manage timers and trackers") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class PrinceMalchezaarBotIsEnfeebledTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
PrinceMalchezaarBotIsEnfeebledTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "prince malchezaar bot is enfeebled") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class PrinceMalchezaarInfernalsAreSpawnedTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
PrinceMalchezaarInfernalsAreSpawnedTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "prince malchezaar infernals are spawned") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class PrinceMalchezaarBossEngagedByMainTankTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
PrinceMalchezaarBossEngagedByMainTankTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "prince malchezaar boss engaged by main tank") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NightbaneBossEngagedByMainTankTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NightbaneBossEngagedByMainTankTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "nightbane boss engaged by main tank") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NightbaneRangedBotsAreInCharredEarthTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NightbaneRangedBotsAreInCharredEarthTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "nightbane ranged bots are in charred earth") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NightbaneMainTankIsSusceptibleToFearTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NightbaneMainTankIsSusceptibleToFearTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "nightbane main tank is susceptible to fear") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NightbanePetsIgnoreCollisionToChaseFlyingBossTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NightbanePetsIgnoreCollisionToChaseFlyingBossTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "nightbane pets ignore collision to chase flying boss") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NightbaneBossIsFlyingTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NightbaneBossIsFlyingTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "nightbane boss is flying") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class NightbaneNeedToManageTimersAndTrackersTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NightbaneNeedToManageTimersAndTrackersTrigger(
|
||||
PlayerbotAI* botAI) : Trigger(botAI, "nightbane need to manage timers and trackers") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
490
src/Ai/Raid/Karazhan/Util/RaidKarazhanHelpers.cpp
Normal file
490
src/Ai/Raid/Karazhan/Util/RaidKarazhanHelpers.cpp
Normal file
@@ -0,0 +1,490 @@
|
||||
#include "RaidKarazhanHelpers.h"
|
||||
#include "RaidKarazhanActions.h"
|
||||
#include "Playerbots.h"
|
||||
#include "RtiTargetValue.h"
|
||||
|
||||
namespace KarazhanHelpers
|
||||
{
|
||||
// Attumen the Huntsman
|
||||
std::unordered_map<uint32, time_t> attumenDpsWaitTimer;
|
||||
// Big Bad Wolf
|
||||
std::unordered_map<ObjectGuid, uint8> bigBadWolfRunIndex;
|
||||
// Netherspite
|
||||
std::unordered_map<uint32, time_t> netherspiteDpsWaitTimer;
|
||||
std::unordered_map<ObjectGuid, time_t> redBeamMoveTimer;
|
||||
std::unordered_map<ObjectGuid, bool> lastBeamMoveSideways;
|
||||
// Nightbane
|
||||
std::unordered_map<uint32, time_t> nightbaneDpsWaitTimer;
|
||||
std::unordered_map<ObjectGuid, uint8> nightbaneTankStep;
|
||||
std::unordered_map<ObjectGuid, uint8> nightbaneRangedStep;
|
||||
std::unordered_map<uint32, time_t> nightbaneFlightPhaseStartTimer;
|
||||
std::unordered_map<ObjectGuid, bool> nightbaneRainOfBonesHit;
|
||||
|
||||
const Position MAIDEN_OF_VIRTUE_BOSS_POSITION = { -10945.881f, -2103.782f, 92.712f };
|
||||
const Position MAIDEN_OF_VIRTUE_RANGED_POSITION[8] =
|
||||
{
|
||||
{ -10931.178f, -2116.580f, 92.179f },
|
||||
{ -10925.828f, -2102.425f, 92.180f },
|
||||
{ -10933.089f, -2088.502f, 92.180f },
|
||||
{ -10947.590f, -2082.815f, 92.180f },
|
||||
{ -10960.912f, -2090.437f, 92.179f },
|
||||
{ -10966.017f, -2105.288f, 92.175f },
|
||||
{ -10959.242f, -2119.617f, 92.180f },
|
||||
{ -10944.495f, -2123.857f, 92.180f },
|
||||
};
|
||||
|
||||
const Position BIG_BAD_WOLF_BOSS_POSITION = { -10913.391f, -1773.508f, 90.477f };
|
||||
const Position BIG_BAD_WOLF_RUN_POSITION[4] =
|
||||
{
|
||||
{ -10875.456f, -1779.036f, 90.477f },
|
||||
{ -10872.281f, -1751.638f, 90.477f },
|
||||
{ -10910.492f, -1747.401f, 90.477f },
|
||||
{ -10913.391f, -1773.508f, 90.477f },
|
||||
};
|
||||
|
||||
const Position THE_CURATOR_BOSS_POSITION = { -11139.463f, -1884.645f, 165.765f };
|
||||
|
||||
const Position NIGHTBANE_TRANSITION_BOSS_POSITION = { -11160.646f, -1932.773f, 91.473f }; // near some ribs
|
||||
const Position NIGHTBANE_FINAL_BOSS_POSITION = { -11173.530f, -1940.707f, 91.473f };
|
||||
const Position NIGHTBANE_RANGED_POSITION1 = { -11145.949f, -1970.927f, 91.473f };
|
||||
const Position NIGHTBANE_RANGED_POSITION2 = { -11143.594f, -1954.981f, 91.473f };
|
||||
const Position NIGHTBANE_RANGED_POSITION3 = { -11159.778f, -1961.031f, 91.473f };
|
||||
const Position NIGHTBANE_FLIGHT_STACK_POSITION = { -11159.555f, -1893.526f, 91.473f }; // Broken Barrel
|
||||
const Position NIGHTBANE_RAIN_OF_BONES_POSITION = { -11165.233f, -1911.123f, 91.473f };
|
||||
|
||||
void MarkTargetWithIcon(Player* bot, Unit* target, uint8 iconId)
|
||||
{
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
ObjectGuid currentGuid = group->GetTargetIcon(iconId);
|
||||
if (currentGuid != target->GetGUID())
|
||||
group->SetTargetIcon(iconId, bot->GetGUID(), target->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
void MarkTargetWithSkull(Player* bot, Unit* target)
|
||||
{
|
||||
MarkTargetWithIcon(bot, target, RtiTargetValue::skullIndex);
|
||||
}
|
||||
|
||||
void MarkTargetWithSquare(Player* bot, Unit* target)
|
||||
{
|
||||
MarkTargetWithIcon(bot, target, RtiTargetValue::squareIndex);
|
||||
}
|
||||
|
||||
void MarkTargetWithStar(Player* bot, Unit* target)
|
||||
{
|
||||
MarkTargetWithIcon(bot, target, RtiTargetValue::starIndex);
|
||||
}
|
||||
|
||||
void MarkTargetWithCircle(Player* bot, Unit* target)
|
||||
{
|
||||
MarkTargetWithIcon(bot, target, RtiTargetValue::circleIndex);
|
||||
}
|
||||
|
||||
void MarkTargetWithMoon(Player* bot, Unit* target)
|
||||
{
|
||||
MarkTargetWithIcon(bot, target, RtiTargetValue::moonIndex);
|
||||
}
|
||||
|
||||
void SetRtiTarget(PlayerbotAI* botAI, const std::string& rtiName, Unit* target)
|
||||
{
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
std::string currentRti = botAI->GetAiObjectContext()->GetValue<std::string>("rti")->Get();
|
||||
Unit* currentTarget = botAI->GetAiObjectContext()->GetValue<Unit*>("rti target")->Get();
|
||||
|
||||
if (currentRti != rtiName || currentTarget != target)
|
||||
{
|
||||
botAI->GetAiObjectContext()->GetValue<std::string>("rti")->Set(rtiName);
|
||||
botAI->GetAiObjectContext()->GetValue<Unit*>("rti target")->Set(target);
|
||||
}
|
||||
}
|
||||
|
||||
// Only one bot is needed to set/reset instance-wide timers
|
||||
bool IsInstanceTimerManager(PlayerbotAI* botAI, Player* bot)
|
||||
{
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
||||
{
|
||||
Player* member = ref->GetSource();
|
||||
if (member && member->IsAlive() && botAI->IsDps(member) && GET_PLAYERBOT_AI(member))
|
||||
return member == bot;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Unit* GetFirstAliveUnit(const std::vector<Unit*>& units)
|
||||
{
|
||||
for (Unit* unit : units)
|
||||
{
|
||||
if (unit && unit->IsAlive())
|
||||
return unit;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Unit* GetFirstAliveUnitByEntry(PlayerbotAI* botAI, uint32 entry)
|
||||
{
|
||||
const GuidVector npcs = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest hostile npcs")->Get();
|
||||
for (auto const& npcGuid : npcs)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(npcGuid);
|
||||
if (unit && unit->IsAlive() && unit->GetEntry() == entry)
|
||||
return unit;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Unit* GetNearestPlayerInRadius(Player* bot, float radius)
|
||||
{
|
||||
Unit* nearestPlayer = nullptr;
|
||||
float nearestDistance = radius;
|
||||
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* ref = group->GetFirstMember(); ref != nullptr; ref = ref->next())
|
||||
{
|
||||
Player* member = ref->GetSource();
|
||||
if (!member || !member->IsAlive() || member == bot)
|
||||
continue;
|
||||
|
||||
float distance = bot->GetExactDist2d(member);
|
||||
if (distance < nearestDistance)
|
||||
{
|
||||
nearestDistance = distance;
|
||||
nearestPlayer = member;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nearestPlayer;
|
||||
}
|
||||
|
||||
bool IsFlameWreathActive(PlayerbotAI* botAI, Player* bot)
|
||||
{
|
||||
Unit* aran = botAI->GetAiObjectContext()->GetValue<Unit*>("find target", "shade of aran")->Get();
|
||||
Spell* currentSpell = aran ? aran->GetCurrentSpell(CURRENT_GENERIC_SPELL) : nullptr;
|
||||
|
||||
if (currentSpell && currentSpell->m_spellInfo &&
|
||||
currentSpell->m_spellInfo->Id == SPELL_FLAME_WREATH_CAST)
|
||||
return true;
|
||||
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
||||
{
|
||||
Player* member = ref->GetSource();
|
||||
if (!member || !member->IsAlive())
|
||||
continue;
|
||||
|
||||
if (member->HasAura(SPELL_FLAME_WREATH_AURA))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Red beam blockers: tank bots, no Nether Exhaustion Red
|
||||
std::vector<Player*> GetRedBlockers(PlayerbotAI* botAI, Player* bot)
|
||||
{
|
||||
std::vector<Player*> redBlockers;
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
||||
{
|
||||
Player* member = ref->GetSource();
|
||||
if (!member || !member->IsAlive() || !botAI->IsTank(member) || !GET_PLAYERBOT_AI(member) ||
|
||||
member->HasAura(SPELL_NETHER_EXHAUSTION_RED))
|
||||
continue;
|
||||
|
||||
redBlockers.push_back(member);
|
||||
}
|
||||
}
|
||||
|
||||
return redBlockers;
|
||||
}
|
||||
|
||||
// Blue beam blockers: non-Rogue/Warrior DPS bots, no Nether Exhaustion Blue and <24 stacks of Blue Beam debuff
|
||||
std::vector<Player*> GetBlueBlockers(PlayerbotAI* botAI, Player* bot)
|
||||
{
|
||||
std::vector<Player*> blueBlockers;
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
||||
{
|
||||
Player* member = ref->GetSource();
|
||||
if (!member || !member->IsAlive() || !GET_PLAYERBOT_AI(member))
|
||||
continue;
|
||||
|
||||
bool hasExhaustion = member->HasAura(SPELL_NETHER_EXHAUSTION_BLUE);
|
||||
Aura* blueBuff = member->GetAura(SPELL_BLUE_BEAM_DEBUFF);
|
||||
bool overStack = blueBuff && blueBuff->GetStackAmount() >= 24;
|
||||
|
||||
bool isDps = botAI->IsDps(member);
|
||||
bool isWarrior = member->getClass() == CLASS_WARRIOR;
|
||||
bool isRogue = member->getClass() == CLASS_ROGUE;
|
||||
|
||||
if (isDps && !isWarrior && !isRogue && !hasExhaustion && !overStack)
|
||||
blueBlockers.push_back(member);
|
||||
}
|
||||
}
|
||||
|
||||
return blueBlockers;
|
||||
}
|
||||
|
||||
// Green beam blockers:
|
||||
// (1) Prioritize Rogues and non-tank Warrior bots, no Nether Exhaustion Green
|
||||
// (2) Then assign Healer bots, no Nether Exhaustion Green and <24 stacks of Green Beam debuff
|
||||
std::vector<Player*> GetGreenBlockers(PlayerbotAI* botAI, Player* bot)
|
||||
{
|
||||
std::vector<Player*> greenBlockers;
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
||||
{
|
||||
Player* member = ref->GetSource();
|
||||
if (!member || !member->IsAlive() || !GET_PLAYERBOT_AI(member))
|
||||
continue;
|
||||
|
||||
bool hasExhaustion = member->HasAura(SPELL_NETHER_EXHAUSTION_GREEN);
|
||||
bool isRogue = member->getClass() == CLASS_ROGUE;
|
||||
bool isDpsWarrior = member->getClass() == CLASS_WARRIOR && botAI->IsDps(member);
|
||||
bool eligibleRogueWarrior = (isRogue || isDpsWarrior) && !hasExhaustion;
|
||||
|
||||
if (eligibleRogueWarrior)
|
||||
greenBlockers.push_back(member);
|
||||
}
|
||||
|
||||
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
||||
{
|
||||
Player* member = ref->GetSource();
|
||||
if (!member || !member->IsAlive() || !GET_PLAYERBOT_AI(member))
|
||||
continue;
|
||||
|
||||
bool hasExhaustion = member->HasAura(SPELL_NETHER_EXHAUSTION_GREEN);
|
||||
Aura* greenBuff = member->GetAura(SPELL_GREEN_BEAM_DEBUFF);
|
||||
bool overStack = greenBuff && greenBuff->GetStackAmount() >= 24;
|
||||
bool isHealer = botAI->IsHeal(member);
|
||||
bool eligibleHealer = isHealer && !hasExhaustion && !overStack;
|
||||
|
||||
if (eligibleHealer)
|
||||
greenBlockers.push_back(member);
|
||||
}
|
||||
}
|
||||
|
||||
return greenBlockers;
|
||||
}
|
||||
|
||||
std::tuple<Player*, Player*, Player*> GetCurrentBeamBlockers(PlayerbotAI* botAI, Player* bot)
|
||||
{
|
||||
static ObjectGuid currentRedBlocker;
|
||||
static ObjectGuid currentGreenBlocker;
|
||||
static ObjectGuid currentBlueBlocker;
|
||||
|
||||
Player* redBlocker = nullptr;
|
||||
Player* greenBlocker = nullptr;
|
||||
Player* blueBlocker = nullptr;
|
||||
|
||||
std::vector<Player*> redBlockers = GetRedBlockers(botAI, bot);
|
||||
if (!redBlockers.empty())
|
||||
{
|
||||
auto it = std::find_if(redBlockers.begin(), redBlockers.end(), [](Player* player)
|
||||
{
|
||||
return player && player->GetGUID() == currentRedBlocker;
|
||||
});
|
||||
|
||||
if (it != redBlockers.end())
|
||||
redBlocker = *it;
|
||||
else
|
||||
redBlocker = redBlockers.front();
|
||||
|
||||
currentRedBlocker = redBlocker ? redBlocker->GetGUID() : ObjectGuid::Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentRedBlocker = ObjectGuid::Empty;
|
||||
redBlocker = nullptr;
|
||||
}
|
||||
|
||||
std::vector<Player*> greenBlockers = GetGreenBlockers(botAI, bot);
|
||||
if (!greenBlockers.empty())
|
||||
{
|
||||
auto it = std::find_if(greenBlockers.begin(), greenBlockers.end(), [](Player* player)
|
||||
{
|
||||
return player && player->GetGUID() == currentGreenBlocker;
|
||||
});
|
||||
|
||||
if (it != greenBlockers.end())
|
||||
greenBlocker = *it;
|
||||
else
|
||||
greenBlocker = greenBlockers.front();
|
||||
|
||||
currentGreenBlocker = greenBlocker ? greenBlocker->GetGUID() : ObjectGuid::Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentGreenBlocker = ObjectGuid::Empty;
|
||||
greenBlocker = nullptr;
|
||||
}
|
||||
|
||||
std::vector<Player*> blueBlockers = GetBlueBlockers(botAI, bot);
|
||||
if (!blueBlockers.empty())
|
||||
{
|
||||
auto it = std::find_if(blueBlockers.begin(), blueBlockers.end(), [](Player* player)
|
||||
{
|
||||
return player && player->GetGUID() == currentBlueBlocker;
|
||||
});
|
||||
|
||||
if (it != blueBlockers.end())
|
||||
blueBlocker = *it;
|
||||
else
|
||||
blueBlocker = blueBlockers.front();
|
||||
|
||||
currentBlueBlocker = blueBlocker ? blueBlocker->GetGUID() : ObjectGuid::Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentBlueBlocker = ObjectGuid::Empty;
|
||||
blueBlocker = nullptr;
|
||||
}
|
||||
|
||||
return std::make_tuple(redBlocker, greenBlocker, blueBlocker);
|
||||
}
|
||||
|
||||
std::vector<Unit*> GetAllVoidZones(PlayerbotAI* botAI, Player* bot)
|
||||
{
|
||||
std::vector<Unit*> voidZones;
|
||||
const float radius = 30.0f;
|
||||
const GuidVector npcs = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest npcs")->Get();
|
||||
for (auto const& npcGuid : npcs)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(npcGuid);
|
||||
if (!unit || unit->GetEntry() != NPC_VOID_ZONE)
|
||||
continue;
|
||||
|
||||
float dist = bot->GetExactDist2d(unit);
|
||||
if (dist < radius)
|
||||
voidZones.push_back(unit);
|
||||
}
|
||||
|
||||
return voidZones;
|
||||
}
|
||||
|
||||
bool IsSafePosition(float x, float y, float z, const std::vector<Unit*>& hazards, float hazardRadius)
|
||||
{
|
||||
for (Unit* hazard : hazards)
|
||||
{
|
||||
float dist = hazard->GetExactDist2d(x, y);
|
||||
if (dist < hazardRadius)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Unit*> GetSpawnedInfernals(PlayerbotAI* botAI)
|
||||
{
|
||||
std::vector<Unit*> infernals;
|
||||
const GuidVector npcs = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest npcs")->Get();
|
||||
for (auto const& npcGuid : npcs)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(npcGuid);
|
||||
if (unit && unit->GetEntry() == NPC_NETHERSPITE_INFERNAL)
|
||||
infernals.push_back(unit);
|
||||
}
|
||||
|
||||
return infernals;
|
||||
}
|
||||
|
||||
bool IsStraightPathSafe(const Position& start, const Position& target, const std::vector<Unit*>& hazards,
|
||||
float hazardRadius, float stepSize)
|
||||
{
|
||||
float sx = start.GetPositionX();
|
||||
float sy = start.GetPositionY();
|
||||
float sz = start.GetPositionZ();
|
||||
float tx = target.GetPositionX();
|
||||
float ty = target.GetPositionY();
|
||||
float tz = target.GetPositionZ();
|
||||
|
||||
const float totalDist = start.GetExactDist2d(target.GetPositionX(), target.GetPositionY());
|
||||
if (totalDist == 0.0f)
|
||||
return true;
|
||||
|
||||
for (float checkDist = 0.0f; checkDist <= totalDist; checkDist += stepSize)
|
||||
{
|
||||
float t = checkDist / totalDist;
|
||||
float checkX = sx + (tx - sx) * t;
|
||||
float checkY = sy + (ty - sy) * t;
|
||||
float checkZ = sz + (tz - sz) * t;
|
||||
for (Unit* hazard : hazards)
|
||||
{
|
||||
const float hx = checkX - hazard->GetPositionX();
|
||||
const float hy = checkY - hazard->GetPositionY();
|
||||
if ((hx*hx + hy*hy) < hazardRadius * hazardRadius)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryFindSafePositionWithSafePath(
|
||||
Player* bot, float originX, float originY, float originZ, float centerX, float centerY, float centerZ,
|
||||
const std::vector<Unit*>& hazards, float safeDistance, float stepSize, uint8 numAngles,
|
||||
float maxSampleDist, bool requireSafePath, float& bestDestX, float& bestDestY, float& bestDestZ)
|
||||
{
|
||||
float bestMoveDist = std::numeric_limits<float>::max();
|
||||
bool found = false;
|
||||
|
||||
for (int i = 0; i < numAngles; ++i)
|
||||
{
|
||||
float angle = (2.0f * M_PI * i) / numAngles;
|
||||
float dx = cos(angle);
|
||||
float dy = sin(angle);
|
||||
|
||||
for (float dist = stepSize; dist <= maxSampleDist; dist += stepSize)
|
||||
{
|
||||
float x = centerX + dx * dist;
|
||||
float y = centerY + dy * dist;
|
||||
float z = centerZ;
|
||||
float destX = x, destY = y, destZ = z;
|
||||
if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, centerX, centerY, centerZ,
|
||||
destX, destY, destZ, true))
|
||||
continue;
|
||||
|
||||
if (!IsSafePosition(destX, destY, destZ, hazards, safeDistance))
|
||||
continue;
|
||||
|
||||
if (requireSafePath)
|
||||
{
|
||||
if (!IsStraightPathSafe(Position(originX, originY, originZ), Position(destX, destY, destZ),
|
||||
hazards, safeDistance, stepSize))
|
||||
continue;
|
||||
}
|
||||
|
||||
const float moveDist = Position(originX, originY, originZ).GetExactDist2d(destX, destY);
|
||||
if (moveDist < bestMoveDist)
|
||||
{
|
||||
bestMoveDist = moveDist;
|
||||
bestDestX = destX;
|
||||
bestDestY = destY;
|
||||
bestDestZ = destZ;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
}
|
||||
136
src/Ai/Raid/Karazhan/Util/RaidKarazhanHelpers.h
Normal file
136
src/Ai/Raid/Karazhan/Util/RaidKarazhanHelpers.h
Normal file
@@ -0,0 +1,136 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANHELPERS_H_
|
||||
#define _PLAYERBOT_RAIDKARAZHANHELPERS_H_
|
||||
|
||||
#include <ctime>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "AiObject.h"
|
||||
#include "Position.h"
|
||||
#include "Unit.h"
|
||||
|
||||
namespace KarazhanHelpers
|
||||
{
|
||||
enum KarazhanSpells
|
||||
{
|
||||
// Maiden of Virtue
|
||||
SPELL_REPENTANCE = 29511,
|
||||
|
||||
// Opera Event
|
||||
SPELL_LITTLE_RED_RIDING_HOOD = 30756,
|
||||
|
||||
// The Curator
|
||||
SPELL_CURATOR_EVOCATION = 30254,
|
||||
|
||||
// Shade of Aran
|
||||
SPELL_FLAME_WREATH_CAST = 30004,
|
||||
SPELL_FLAME_WREATH_AURA = 29946,
|
||||
SPELL_ARCANE_EXPLOSION = 29973,
|
||||
|
||||
// Netherspite
|
||||
SPELL_RED_BEAM_DEBUFF = 30421, // "Nether Portal - Perseverance" (player aura)
|
||||
SPELL_GREEN_BEAM_DEBUFF = 30422, // "Nether Portal - Serenity" (player aura)
|
||||
SPELL_BLUE_BEAM_DEBUFF = 30423, // "Nether Portal - Dominance" (player aura)
|
||||
SPELL_GREEN_BEAM_HEAL = 30467, // "Nether Portal - Serenity" (Netherspite aura)
|
||||
SPELL_NETHER_EXHAUSTION_RED = 38637,
|
||||
SPELL_NETHER_EXHAUSTION_GREEN = 38638,
|
||||
SPELL_NETHER_EXHAUSTION_BLUE = 38639,
|
||||
SPELL_NETHERSPITE_BANISHED = 39833, // "Vortex Shade Black"
|
||||
|
||||
// Prince Malchezaar
|
||||
SPELL_ENFEEBLE = 30843,
|
||||
|
||||
// Nightbane
|
||||
SPELL_CHARRED_EARTH = 30129,
|
||||
SPELL_BELLOWING_ROAR = 36922,
|
||||
SPELL_RAIN_OF_BONES = 37091,
|
||||
|
||||
// Warlock
|
||||
SPELL_WARLOCK_BANISH = 18647,
|
||||
|
||||
// Priest
|
||||
SPELL_FEAR_WARD = 6346,
|
||||
};
|
||||
|
||||
enum KarazhanNPCs
|
||||
{
|
||||
// Trash
|
||||
NPC_SPECTRAL_RETAINER = 16410,
|
||||
NPC_MANA_WARP = 16530,
|
||||
|
||||
// Attumen the Huntsman
|
||||
NPC_ATTUMEN_THE_HUNTSMAN = 15550,
|
||||
NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED = 16152,
|
||||
|
||||
// Shade of Aran
|
||||
NPC_CONJURED_ELEMENTAL = 17167,
|
||||
|
||||
// Netherspite
|
||||
NPC_VOID_ZONE = 16697,
|
||||
NPC_GREEN_PORTAL = 17367, // "Nether Portal - Serenity <Healing Portal>"
|
||||
NPC_BLUE_PORTAL = 17368, // "Nether Portal - Dominance <Damage Portal>"
|
||||
NPC_RED_PORTAL = 17369, // "Nether Portal - Perseverance <Tanking Portal>"
|
||||
|
||||
// Prince Malchezaar
|
||||
NPC_NETHERSPITE_INFERNAL = 17646,
|
||||
};
|
||||
|
||||
const uint32 KARAZHAN_MAP_ID = 532;
|
||||
const float NIGHTBANE_FLIGHT_Z = 95.0f;
|
||||
|
||||
// Attumen the Huntsman
|
||||
extern std::unordered_map<uint32, time_t> attumenDpsWaitTimer;
|
||||
// Big Bad Wolf
|
||||
extern std::unordered_map<ObjectGuid, uint8> bigBadWolfRunIndex;
|
||||
// Netherspite
|
||||
extern std::unordered_map<uint32, time_t> netherspiteDpsWaitTimer;
|
||||
extern std::unordered_map<ObjectGuid, time_t> redBeamMoveTimer;
|
||||
extern std::unordered_map<ObjectGuid, bool> lastBeamMoveSideways;
|
||||
// Nightbane
|
||||
extern std::unordered_map<uint32, time_t> nightbaneDpsWaitTimer;
|
||||
extern std::unordered_map<ObjectGuid, uint8> nightbaneTankStep;
|
||||
extern std::unordered_map<ObjectGuid, uint8> nightbaneRangedStep;
|
||||
extern std::unordered_map<uint32, time_t> nightbaneFlightPhaseStartTimer;
|
||||
extern std::unordered_map<ObjectGuid, bool> nightbaneRainOfBonesHit;
|
||||
|
||||
extern const Position MAIDEN_OF_VIRTUE_BOSS_POSITION;
|
||||
extern const Position MAIDEN_OF_VIRTUE_RANGED_POSITION[8];
|
||||
extern const Position BIG_BAD_WOLF_BOSS_POSITION;
|
||||
extern const Position BIG_BAD_WOLF_RUN_POSITION[4];
|
||||
extern const Position THE_CURATOR_BOSS_POSITION;
|
||||
extern const Position NIGHTBANE_TRANSITION_BOSS_POSITION;
|
||||
extern const Position NIGHTBANE_FINAL_BOSS_POSITION;
|
||||
extern const Position NIGHTBANE_RANGED_POSITION1;
|
||||
extern const Position NIGHTBANE_RANGED_POSITION2;
|
||||
extern const Position NIGHTBANE_RANGED_POSITION3;
|
||||
extern const Position NIGHTBANE_FLIGHT_STACK_POSITION;
|
||||
extern const Position NIGHTBANE_RAIN_OF_BONES_POSITION;
|
||||
|
||||
void MarkTargetWithIcon(Player* bot, Unit* target, uint8 iconId);
|
||||
void MarkTargetWithSkull(Player* bot, Unit* target);
|
||||
void MarkTargetWithSquare(Player* bot, Unit* target);
|
||||
void MarkTargetWithStar(Player* bot, Unit* target);
|
||||
void MarkTargetWithCircle(Player* bot, Unit* target);
|
||||
void MarkTargetWithMoon(Player* bot, Unit* target);
|
||||
void SetRtiTarget(PlayerbotAI* botAI, const std::string& rtiName, Unit* target);
|
||||
bool IsInstanceTimerManager(PlayerbotAI* botAI, Player* bot);
|
||||
Unit* GetFirstAliveUnit(const std::vector<Unit*>& units);
|
||||
Unit* GetFirstAliveUnitByEntry(PlayerbotAI* botAI, uint32 entry);
|
||||
Unit* GetNearestPlayerInRadius(Player* bot, float radius);
|
||||
bool IsFlameWreathActive(PlayerbotAI* botAI, Player* bot);
|
||||
std::vector<Player*> GetRedBlockers(PlayerbotAI* botAI, Player* bot);
|
||||
std::vector<Player*> GetBlueBlockers(PlayerbotAI* botAI, Player* bot);
|
||||
std::vector<Player*> GetGreenBlockers(PlayerbotAI* botAI, Player* bot);
|
||||
std::tuple<Player*, Player*, Player*> GetCurrentBeamBlockers(PlayerbotAI* botAI, Player* bot);
|
||||
std::vector<Unit*> GetAllVoidZones(PlayerbotAI *botAI, Player* bot);
|
||||
bool IsSafePosition (float x, float y, float z, const std::vector<Unit*>& hazards, float hazardRadius);
|
||||
std::vector<Unit*> GetSpawnedInfernals(PlayerbotAI* botAI);
|
||||
bool IsStraightPathSafe(
|
||||
const Position& start, const Position& target,
|
||||
const std::vector<Unit*>& hazards, float hazardRadius, float stepSize);
|
||||
bool TryFindSafePositionWithSafePath(
|
||||
Player* bot, float originX, float originY, float originZ, float centerX, float centerY, float centerZ,
|
||||
const std::vector<Unit*>& hazards, float safeDistance, float stepSize, uint8 numAngles,
|
||||
float maxSampleDist, bool requireSafePath, float& bestDestX, float& bestDestY, float& bestDestZ);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user