mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Merge pull request #1623 from brighton-chi/karazhan
Implement Karazhan strategy
This commit is contained in:
@@ -443,7 +443,7 @@ AiPlayerbot.AutoAvoidAoe = 1
|
||||
AiPlayerbot.MaxAoeAvoidRadius = 15.0
|
||||
|
||||
# A whitelist of aoe spell IDs that should not be avoided
|
||||
AiPlayerbot.AoeAvoidSpellWhitelist = 50759,57491,13810
|
||||
AiPlayerbot.AoeAvoidSpellWhitelist = 50759,57491,13810,29946
|
||||
|
||||
# Enable healer bot save mana strategy
|
||||
# Default: 1 (enabled)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
DELETE FROM ai_playerbot_texts WHERE name IN (
|
||||
'netherspite_beam_blocking_red',
|
||||
'netherspite_beam_blocking_blue',
|
||||
'netherspite_beam_blocking_green',
|
||||
'netherspite_beam_leaving_blue',
|
||||
'netherspite_beam_leaving_green'
|
||||
);
|
||||
|
||||
DELETE FROM ai_playerbot_texts_chance WHERE name IN (
|
||||
'netherspite_beam_blocking_red',
|
||||
'netherspite_beam_blocking_blue',
|
||||
'netherspite_beam_blocking_green',
|
||||
'netherspite_beam_leaving_blue',
|
||||
'netherspite_beam_leaving_green'
|
||||
);
|
||||
|
||||
INSERT INTO ai_playerbot_texts (name, text, say_type, reply_type, text_loc1, text_loc2, text_loc3, text_loc4, text_loc5, text_loc6, text_loc7, text_loc8) VALUES
|
||||
('netherspite_beam_blocking_red', '%player is moving to block the red beam!', 0, 0, '', '', '', '', '', '', '', ''),
|
||||
('netherspite_beam_blocking_blue', '%player is moving to block the blue beam!', 0, 0, '', '', '', '', '', '', '', ''),
|
||||
('netherspite_beam_blocking_green', '%player is moving to block the green beam!', 0, 0, '', '', '', '', '', '', '', ''),
|
||||
('netherspite_beam_leaving_blue', '%player is leaving the blue beam--next blocker up!', 0, 0, '', '', '', '', '', '', '', ''),
|
||||
('netherspite_beam_leaving_green', '%player is leaving the green beam--next blocker up!', 0, 0, '', '', '', '', '', '', '', '');
|
||||
|
||||
INSERT INTO ai_playerbot_texts_chance (name, probability) VALUES
|
||||
('netherspite_beam_blocking_red', 100),
|
||||
('netherspite_beam_blocking_blue', 100),
|
||||
('netherspite_beam_blocking_green', 100),
|
||||
('netherspite_beam_leaving_blue', 100),
|
||||
('netherspite_beam_leaving_green', 100);
|
||||
@@ -1513,19 +1513,22 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
|
||||
switch (mapId)
|
||||
{
|
||||
case 249:
|
||||
strategyName = "onyxia";
|
||||
strategyName = "onyxia"; // Onyxia's Lair
|
||||
break;
|
||||
case 409:
|
||||
strategyName = "mc";
|
||||
strategyName = "mc"; // Molten Core
|
||||
break;
|
||||
case 469:
|
||||
strategyName = "bwl";
|
||||
strategyName = "bwl"; // Blackwing Lair
|
||||
break;
|
||||
case 509:
|
||||
strategyName = "aq20";
|
||||
strategyName = "aq20"; // Ruins of Ahn'Qiraj
|
||||
break;
|
||||
case 532:
|
||||
strategyName = "karazhan"; // Karazhan
|
||||
break;
|
||||
case 533:
|
||||
strategyName = "naxx";
|
||||
strategyName = "naxx"; // Naxxramas
|
||||
break;
|
||||
case 574:
|
||||
strategyName = "wotlk-uk"; // Utgarde Keep
|
||||
|
||||
@@ -33,22 +33,24 @@
|
||||
#include "raids/RaidStrategyContext.h"
|
||||
#include "raids/aq20/RaidAq20ActionContext.h"
|
||||
#include "raids/aq20/RaidAq20TriggerContext.h"
|
||||
#include "raids/blackwinglair/RaidBwlActionContext.h"
|
||||
#include "raids/blackwinglair/RaidBwlTriggerContext.h"
|
||||
#include "raids/eyeofeternity/RaidEoEActionContext.h"
|
||||
#include "raids/eyeofeternity/RaidEoETriggerContext.h"
|
||||
#include "raids/icecrown/RaidIccActionContext.h"
|
||||
#include "raids/icecrown/RaidIccTriggerContext.h"
|
||||
#include "raids/moltencore/RaidMcActionContext.h"
|
||||
#include "raids/moltencore/RaidMcTriggerContext.h"
|
||||
#include "raids/blackwinglair/RaidBwlActionContext.h"
|
||||
#include "raids/blackwinglair/RaidBwlTriggerContext.h"
|
||||
#include "raids/karazhan/RaidKarazhanActionContext.h"
|
||||
#include "raids/karazhan/RaidKarazhanTriggerContext.h"
|
||||
#include "raids/naxxramas/RaidNaxxActionContext.h"
|
||||
#include "raids/naxxramas/RaidNaxxTriggerContext.h"
|
||||
#include "raids/eyeofeternity/RaidEoEActionContext.h"
|
||||
#include "raids/eyeofeternity/RaidEoETriggerContext.h"
|
||||
#include "raids/vaultofarchavon/RaidVoAActionContext.h"
|
||||
#include "raids/vaultofarchavon/RaidVoATriggerContext.h"
|
||||
#include "raids/obsidiansanctum/RaidOsActionContext.h"
|
||||
#include "raids/obsidiansanctum/RaidOsTriggerContext.h"
|
||||
#include "raids/onyxia/RaidOnyxiaActionContext.h"
|
||||
#include "raids/onyxia/RaidOnyxiaTriggerContext.h"
|
||||
#include "raids/vaultofarchavon/RaidVoAActionContext.h"
|
||||
#include "raids/vaultofarchavon/RaidVoATriggerContext.h"
|
||||
#include "raids/icecrown/RaidIccActionContext.h"
|
||||
#include "raids/icecrown/RaidIccTriggerContext.h"
|
||||
|
||||
SharedNamedObjectContextList<Strategy> AiObjectContext::sharedStrategyContexts;
|
||||
SharedNamedObjectContextList<Action> AiObjectContext::sharedActionContexts;
|
||||
@@ -96,8 +98,8 @@ void AiObjectContext::BuildSharedStrategyContexts(SharedNamedObjectContextList<S
|
||||
strategyContexts.Add(new MovementStrategyContext());
|
||||
strategyContexts.Add(new AssistStrategyContext());
|
||||
strategyContexts.Add(new QuestStrategyContext());
|
||||
strategyContexts.Add(new RaidStrategyContext());
|
||||
strategyContexts.Add(new DungeonStrategyContext());
|
||||
strategyContexts.Add(new RaidStrategyContext());
|
||||
}
|
||||
|
||||
void AiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Action>& actionContexts)
|
||||
@@ -105,15 +107,16 @@ void AiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Act
|
||||
actionContexts.Add(new ActionContext());
|
||||
actionContexts.Add(new ChatActionContext());
|
||||
actionContexts.Add(new WorldPacketActionContext());
|
||||
actionContexts.Add(new RaidAq20ActionContext());
|
||||
actionContexts.Add(new RaidMcActionContext());
|
||||
actionContexts.Add(new RaidBwlActionContext());
|
||||
actionContexts.Add(new RaidOnyxiaActionContext());
|
||||
actionContexts.Add(new RaidAq20ActionContext());
|
||||
actionContexts.Add(new RaidKarazhanActionContext());
|
||||
actionContexts.Add(new RaidNaxxActionContext());
|
||||
actionContexts.Add(new RaidOsActionContext());
|
||||
actionContexts.Add(new RaidEoEActionContext());
|
||||
actionContexts.Add(new RaidVoAActionContext());
|
||||
actionContexts.Add(new RaidUlduarActionContext());
|
||||
actionContexts.Add(new RaidOnyxiaActionContext());
|
||||
actionContexts.Add(new RaidIccActionContext());
|
||||
actionContexts.Add(new WotlkDungeonUKActionContext());
|
||||
actionContexts.Add(new WotlkDungeonNexActionContext());
|
||||
@@ -137,15 +140,16 @@ void AiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Tr
|
||||
triggerContexts.Add(new TriggerContext());
|
||||
triggerContexts.Add(new ChatTriggerContext());
|
||||
triggerContexts.Add(new WorldPacketTriggerContext());
|
||||
triggerContexts.Add(new RaidAq20TriggerContext());
|
||||
triggerContexts.Add(new RaidMcTriggerContext());
|
||||
triggerContexts.Add(new RaidBwlTriggerContext());
|
||||
triggerContexts.Add(new RaidOnyxiaTriggerContext());
|
||||
triggerContexts.Add(new RaidAq20TriggerContext());
|
||||
triggerContexts.Add(new RaidKarazhanTriggerContext());
|
||||
triggerContexts.Add(new RaidNaxxTriggerContext());
|
||||
triggerContexts.Add(new RaidOsTriggerContext());
|
||||
triggerContexts.Add(new RaidEoETriggerContext());
|
||||
triggerContexts.Add(new RaidVoATriggerContext());
|
||||
triggerContexts.Add(new RaidUlduarTriggerContext());
|
||||
triggerContexts.Add(new RaidOnyxiaTriggerContext());
|
||||
triggerContexts.Add(new RaidIccTriggerContext());
|
||||
triggerContexts.Add(new WotlkDungeonUKTriggerContext());
|
||||
triggerContexts.Add(new WotlkDungeonNexTriggerContext());
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
#ifndef _PLAYERBOT_RAIDSTRATEGYCONTEXT_H_
|
||||
#define _PLAYERBOT_RAIDSTRATEGYCONTEXT_H_
|
||||
|
||||
#include "RaidOnyxiaStrategy.h"
|
||||
#include "RaidUlduarStrategy.h"
|
||||
#include "Strategy.h"
|
||||
#include "RaidAq20Strategy.h"
|
||||
#include "RaidMcStrategy.h"
|
||||
#include "RaidBwlStrategy.h"
|
||||
#include "RaidKarazhanStrategy.h"
|
||||
#include "RaidNaxxStrategy.h"
|
||||
#include "RaidOsStrategy.h"
|
||||
#include "RaidEoEStrategy.h"
|
||||
#include "RaidMcStrategy.h"
|
||||
#include "RaidAq20Strategy.h"
|
||||
#include "RaidIccStrategy.h"
|
||||
#include "RaidVoAStrategy.h"
|
||||
#include "RaidUlduarStrategy.h"
|
||||
#include "RaidOnyxiaStrategy.h"
|
||||
#include "RaidIccStrategy.h"
|
||||
|
||||
class RaidStrategyContext : public NamedObjectContext<Strategy>
|
||||
{
|
||||
public:
|
||||
RaidStrategyContext() : NamedObjectContext<Strategy>(false, true)
|
||||
{
|
||||
// TODO should we give these prefixes (eg: "naxx" -> "raid naxx")? because if we don't it's going to end up
|
||||
// very crowded (with possible conflicts) once we have strats for all raids and some dungeons
|
||||
// (mc already very similiar to nc)
|
||||
creators["aq20"] = &RaidStrategyContext::aq20;
|
||||
creators["mc"] = &RaidStrategyContext::mc;
|
||||
creators["bwl"] = &RaidStrategyContext::bwl;
|
||||
creators["aq20"] = &RaidStrategyContext::aq20;
|
||||
creators["karazhan"] = &RaidStrategyContext::karazhan;
|
||||
creators["naxx"] = &RaidStrategyContext::naxx;
|
||||
creators["wotlk-os"] = &RaidStrategyContext::wotlk_os;
|
||||
creators["wotlk-eoe"] = &RaidStrategyContext::wotlk_eoe;
|
||||
creators["voa"] = &RaidStrategyContext::voa;
|
||||
creators["uld"] = &RaidStrategyContext::uld;
|
||||
creators["icc"] = &RaidStrategyContext::icc;
|
||||
creators["onyxia"] = &RaidStrategyContext::onyxia;
|
||||
creators["icc"] = &RaidStrategyContext::icc;
|
||||
}
|
||||
|
||||
private:
|
||||
static Strategy* aq20(PlayerbotAI* botAI) { return new RaidAq20Strategy(botAI); }
|
||||
static Strategy* mc(PlayerbotAI* botAI) { return new RaidMcStrategy(botAI); }
|
||||
static Strategy* bwl(PlayerbotAI* botAI) { return new RaidBwlStrategy(botAI); }
|
||||
static Strategy* aq20(PlayerbotAI* botAI) { return new RaidAq20Strategy(botAI); }
|
||||
static Strategy* karazhan(PlayerbotAI* botAI) { return new RaidKarazhanStrategy(botAI); }
|
||||
static Strategy* naxx(PlayerbotAI* botAI) { return new RaidNaxxStrategy(botAI); }
|
||||
static Strategy* wotlk_os(PlayerbotAI* botAI) { return new RaidOsStrategy(botAI); }
|
||||
static Strategy* wotlk_eoe(PlayerbotAI* botAI) { return new RaidEoEStrategy(botAI); }
|
||||
static Strategy* voa(PlayerbotAI* botAI) { return new RaidVoAStrategy(botAI); }
|
||||
static Strategy* onyxia(PlayerbotAI* botAI) { return new RaidOnyxiaStrategy(botAI); }
|
||||
static Strategy* uld(PlayerbotAI* botAI) { return new RaidUlduarStrategy(botAI); }
|
||||
static Strategy* icc(PlayerbotAI* botAI) { return new RaidIccStrategy(botAI); }
|
||||
static Strategy* onyxia(PlayerbotAI* botAI) { return new RaidOnyxiaStrategy(botAI); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
85
src/strategy/raids/karazhan/RaidKarazhanActionContext.h
Normal file
85
src/strategy/raids/karazhan/RaidKarazhanActionContext.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANACTIONS_CONTEXT_H
|
||||
#define _PLAYERBOT_RAIDKARAZHANACTIONS_CONTEXT_H
|
||||
|
||||
#include "RaidKarazhanActions.h"
|
||||
#include "NamedObjectContext.h"
|
||||
|
||||
class RaidKarazhanActionContext : public NamedObjectContext<Action>
|
||||
{
|
||||
public:
|
||||
RaidKarazhanActionContext()
|
||||
{
|
||||
creators["karazhan attumen the huntsman stack behind"] = &RaidKarazhanActionContext::karazhan_attumen_the_huntsman_stack_behind;
|
||||
|
||||
creators["karazhan moroes mark target"] = &RaidKarazhanActionContext::karazhan_moroes_mark_target;
|
||||
|
||||
creators["karazhan maiden of virtue position boss"] = &RaidKarazhanActionContext::karazhan_maiden_of_virtue_position_boss;
|
||||
creators["karazhan maiden of virtue position ranged"] = &RaidKarazhanActionContext::karazhan_maiden_of_virtue_position_ranged;
|
||||
|
||||
creators["karazhan big bad wolf position boss"] = &RaidKarazhanActionContext::karazhan_big_bad_wolf_position_boss;
|
||||
creators["karazhan big bad wolf run away"] = &RaidKarazhanActionContext::karazhan_big_bad_wolf_run_away;
|
||||
|
||||
creators["karazhan romulo and julianne mark target"] = &RaidKarazhanActionContext::karazhan_romulo_and_julianne_mark_target;
|
||||
|
||||
creators["karazhan wizard of oz mark target"] = &RaidKarazhanActionContext::karazhan_wizard_of_oz_mark_target;
|
||||
creators["karazhan wizard of oz scorch strawman"] = &RaidKarazhanActionContext::karazhan_wizard_of_oz_scorch_strawman;
|
||||
|
||||
creators["karazhan the curator mark target"] = &RaidKarazhanActionContext::karazhan_the_curator_mark_target;
|
||||
creators["karazhan the curator position boss"] = &RaidKarazhanActionContext::karazhan_the_curator_position_boss;
|
||||
creators["karazhan the curator spread ranged"] = &RaidKarazhanActionContext::karazhan_the_curator_spread_ranged;
|
||||
|
||||
creators["karazhan terestian illhoof mark target"] = &RaidKarazhanActionContext::karazhan_terestian_illhoof_mark_target;
|
||||
|
||||
creators["karazhan shade of aran arcane explosion run away"] = &RaidKarazhanActionContext::karazhan_shade_of_aran_arcane_explosion_run_away;
|
||||
creators["karazhan shade of aran flame wreath stop movement"] = &RaidKarazhanActionContext::karazhan_shade_of_aran_flame_wreath_stop_movement;
|
||||
creators["karazhan shade of aran mark conjured elemental"] = &RaidKarazhanActionContext::karazhan_shade_of_aran_mark_conjured_elemental;
|
||||
creators["karazhan shade of aran spread ranged"] = &RaidKarazhanActionContext::karazhan_shade_of_aran_spread_ranged;
|
||||
|
||||
creators["karazhan netherspite block red beam"] = &RaidKarazhanActionContext::karazhan_netherspite_block_red_beam;
|
||||
creators["karazhan netherspite block blue beam"] = &RaidKarazhanActionContext::karazhan_netherspite_block_blue_beam;
|
||||
creators["karazhan netherspite block green beam"] = &RaidKarazhanActionContext::karazhan_netherspite_block_green_beam;
|
||||
creators["karazhan netherspite avoid beam and void zone"] = &RaidKarazhanActionContext::karazhan_netherspite_avoid_beam_and_void_zone;
|
||||
creators["karazhan netherspite banish phase avoid void zone"] = &RaidKarazhanActionContext::karazhan_netherspite_banish_phase_avoid_void_zone;
|
||||
|
||||
creators["karazhan prince malchezaar non tank avoid hazard"] = &RaidKarazhanActionContext::karazhan_prince_malchezaar_non_tank_avoid_hazard;
|
||||
creators["karazhan prince malchezaar tank avoid hazard"] = &RaidKarazhanActionContext::karazhan_prince_malchezaar_tank_avoid_hazard;
|
||||
}
|
||||
|
||||
private:
|
||||
static Action* karazhan_attumen_the_huntsman_stack_behind(PlayerbotAI* botAI) { return new KarazhanAttumenTheHuntsmanStackBehindAction(botAI); }
|
||||
|
||||
static Action* karazhan_moroes_mark_target(PlayerbotAI* botAI) { return new KarazhanMoroesMarkTargetAction(botAI); }
|
||||
|
||||
static Action* karazhan_maiden_of_virtue_position_boss(PlayerbotAI* botAI) { return new KarazhanMaidenOfVirtuePositionBossAction(botAI); }
|
||||
static Action* karazhan_maiden_of_virtue_position_ranged(PlayerbotAI* botAI) { return new KarazhanMaidenOfVirtuePositionRangedAction(botAI); }
|
||||
|
||||
static Action* karazhan_big_bad_wolf_position_boss(PlayerbotAI* botAI) { return new KarazhanBigBadWolfPositionBossAction(botAI); }
|
||||
static Action* karazhan_big_bad_wolf_run_away(PlayerbotAI* botAI) { return new KarazhanBigBadWolfRunAwayAction(botAI); }
|
||||
|
||||
static Action* karazhan_romulo_and_julianne_mark_target(PlayerbotAI* botAI) { return new KarazhanRomuloAndJulianneMarkTargetAction(botAI); }
|
||||
|
||||
static Action* karazhan_wizard_of_oz_mark_target(PlayerbotAI* botAI) { return new KarazhanWizardOfOzMarkTargetAction(botAI); }
|
||||
static Action* karazhan_wizard_of_oz_scorch_strawman(PlayerbotAI* botAI) { return new KarazhanWizardOfOzScorchStrawmanAction(botAI); }
|
||||
|
||||
static Action* karazhan_the_curator_mark_target(PlayerbotAI* botAI) { return new KarazhanTheCuratorMarkTargetAction(botAI); }
|
||||
static Action* karazhan_the_curator_position_boss(PlayerbotAI* botAI) { return new KarazhanTheCuratorPositionBossAction(botAI); }
|
||||
static Action* karazhan_the_curator_spread_ranged(PlayerbotAI* botAI) { return new KarazhanTheCuratorSpreadRangedAction(botAI); }
|
||||
|
||||
static Action* karazhan_terestian_illhoof_mark_target(PlayerbotAI* botAI) { return new KarazhanTerestianIllhoofMarkTargetAction(botAI); }
|
||||
|
||||
static Action* karazhan_shade_of_aran_arcane_explosion_run_away(PlayerbotAI* botAI) { return new KarazhanShadeOfAranArcaneExplosionRunAwayAction(botAI); }
|
||||
static Action* karazhan_shade_of_aran_flame_wreath_stop_movement(PlayerbotAI* botAI) { return new KarazhanShadeOfAranFlameWreathStopMovementAction(botAI); }
|
||||
static Action* karazhan_shade_of_aran_mark_conjured_elemental(PlayerbotAI* botAI) { return new KarazhanShadeOfAranMarkConjuredElementalAction(botAI); }
|
||||
static Action* karazhan_shade_of_aran_spread_ranged(PlayerbotAI* botAI) { return new KarazhanShadeOfAranSpreadRangedAction(botAI); }
|
||||
|
||||
static Action* karazhan_netherspite_block_red_beam(PlayerbotAI* botAI) { return new KarazhanNetherspiteBlockRedBeamAction(botAI); }
|
||||
static Action* karazhan_netherspite_block_blue_beam(PlayerbotAI* botAI) { return new KarazhanNetherspiteBlockBlueBeamAction(botAI); }
|
||||
static Action* karazhan_netherspite_block_green_beam(PlayerbotAI* botAI) { return new KarazhanNetherspiteBlockGreenBeamAction(botAI); }
|
||||
static Action* karazhan_netherspite_avoid_beam_and_void_zone(PlayerbotAI* botAI) { return new KarazhanNetherspiteAvoidBeamAndVoidZoneAction(botAI); }
|
||||
static Action* karazhan_netherspite_banish_phase_avoid_void_zone(PlayerbotAI* botAI) { return new KarazhanNetherspiteBanishPhaseAvoidVoidZoneAction(botAI); }
|
||||
|
||||
static Action* karazhan_prince_malchezaar_non_tank_avoid_hazard(PlayerbotAI* botAI) { return new KarazhanPrinceMalchezaarNonTankAvoidHazardAction(botAI); }
|
||||
static Action* karazhan_prince_malchezaar_tank_avoid_hazard(PlayerbotAI* botAI) { return new KarazhanPrinceMalchezaarTankAvoidHazardAction(botAI); }
|
||||
};
|
||||
|
||||
#endif
|
||||
1271
src/strategy/raids/karazhan/RaidKarazhanActions.cpp
Normal file
1271
src/strategy/raids/karazhan/RaidKarazhanActions.cpp
Normal file
File diff suppressed because it is too large
Load Diff
218
src/strategy/raids/karazhan/RaidKarazhanActions.h
Normal file
218
src/strategy/raids/karazhan/RaidKarazhanActions.h
Normal file
@@ -0,0 +1,218 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANACTIONS_H
|
||||
#define _PLAYERBOT_RAIDKARAZHANACTIONS_H
|
||||
|
||||
#include "Action.h"
|
||||
#include "MovementActions.h"
|
||||
|
||||
class KarazhanAttumenTheHuntsmanStackBehindAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanAttumenTheHuntsmanStackBehindAction(PlayerbotAI* botAI, std::string const name = "karazhan attumen the huntsman stack behind") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanMoroesMarkTargetAction : public Action
|
||||
{
|
||||
public:
|
||||
KarazhanMoroesMarkTargetAction(PlayerbotAI* botAI, std::string const name = "karazhan moroes mark target") : Action(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class KarazhanMaidenOfVirtuePositionBossAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanMaidenOfVirtuePositionBossAction(PlayerbotAI* botAI, std::string const name = "karazhan maiden of virtue position boss") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanMaidenOfVirtuePositionRangedAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanMaidenOfVirtuePositionRangedAction(PlayerbotAI* botAI, std::string const name = "karazhan maiden of virtue position ranged") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanBigBadWolfPositionBossAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanBigBadWolfPositionBossAction(PlayerbotAI* botAI, std::string const name = "karazhan big bad wolf position boss") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanBigBadWolfRunAwayAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanBigBadWolfRunAwayAction(PlayerbotAI* botAI, std::string const name = "karazhan big bad wolf run away") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
|
||||
private:
|
||||
size_t currentIndex = 0;
|
||||
};
|
||||
|
||||
class KarazhanRomuloAndJulianneMarkTargetAction : public Action
|
||||
{
|
||||
public:
|
||||
KarazhanRomuloAndJulianneMarkTargetAction(PlayerbotAI* botAI, std::string const name = "karazhan romulo and julianne mark target") : Action(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class KarazhanWizardOfOzMarkTargetAction : public Action
|
||||
{
|
||||
public:
|
||||
KarazhanWizardOfOzMarkTargetAction(PlayerbotAI* botAI, std::string const name = "karazhan wizard of oz mark target") : Action(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class KarazhanWizardOfOzScorchStrawmanAction : public Action
|
||||
{
|
||||
public:
|
||||
KarazhanWizardOfOzScorchStrawmanAction(PlayerbotAI* botAI, std::string const name = "karazhan wizard of oz scorch strawman") : Action(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class KarazhanTheCuratorMarkTargetAction : public Action
|
||||
{
|
||||
public:
|
||||
KarazhanTheCuratorMarkTargetAction(PlayerbotAI* botAI, std::string const name = "karazhan the curator mark target") : Action(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class KarazhanTheCuratorPositionBossAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanTheCuratorPositionBossAction(PlayerbotAI* botAI, std::string const name = "karazhan the curator position boss") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanTheCuratorSpreadRangedAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanTheCuratorSpreadRangedAction(PlayerbotAI* botAI, std::string const name = "karazhan the curator spread ranged") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanTerestianIllhoofMarkTargetAction : public Action
|
||||
{
|
||||
public:
|
||||
KarazhanTerestianIllhoofMarkTargetAction(PlayerbotAI* botAI, std::string const name = "karazhan terestian illhoof mark target") : Action(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class KarazhanShadeOfAranArcaneExplosionRunAwayAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanShadeOfAranArcaneExplosionRunAwayAction(PlayerbotAI* botAI, std::string const name = "karazhan shade of aran arcane explosion run away") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanShadeOfAranFlameWreathStopMovementAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanShadeOfAranFlameWreathStopMovementAction(PlayerbotAI* botAI, std::string const name = "karazhan shade of aran flame wreath stop bot") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class KarazhanShadeOfAranMarkConjuredElementalAction : public Action
|
||||
{
|
||||
public:
|
||||
KarazhanShadeOfAranMarkConjuredElementalAction(PlayerbotAI* botAI, std::string const name = "karazhan shade of aran mark conjured elemental") : Action(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class KarazhanShadeOfAranSpreadRangedAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanShadeOfAranSpreadRangedAction(PlayerbotAI* botAI, std::string const name = "karazhan shade of aran spread ranged") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanNetherspiteBlockRedBeamAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanNetherspiteBlockRedBeamAction(PlayerbotAI* botAI, std::string const name = "karazhan netherspite block red beam") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanNetherspiteBlockBlueBeamAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanNetherspiteBlockBlueBeamAction(PlayerbotAI* botAI, std::string const name = "karazhan netherspite block blue beam") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanNetherspiteBlockGreenBeamAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanNetherspiteBlockGreenBeamAction(PlayerbotAI* botAI, std::string const name = "karazhan netherspite block green beam") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanNetherspiteAvoidBeamAndVoidZoneAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanNetherspiteAvoidBeamAndVoidZoneAction(PlayerbotAI* botAI, std::string const name = "karazhan netherspite avoid beam and void zone") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanNetherspiteBanishPhaseAvoidVoidZoneAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanNetherspiteBanishPhaseAvoidVoidZoneAction(PlayerbotAI* botAI, std::string const name = "karazhan netherspite banish phase avoid void zone") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanPrinceMalchezaarNonTankAvoidHazardAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanPrinceMalchezaarNonTankAvoidHazardAction(PlayerbotAI* botAI, std::string const name = "karazhan prince malchezaar non-tank avoid hazard") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class KarazhanPrinceMalchezaarTankAvoidHazardAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
KarazhanPrinceMalchezaarTankAvoidHazardAction(PlayerbotAI* botAI, std::string const name = "karazhan prince malchezaar tank avoid hazard") : MovementAction(botAI, name) {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
409
src/strategy/raids/karazhan/RaidKarazhanHelpers.cpp
Normal file
409
src/strategy/raids/karazhan/RaidKarazhanHelpers.cpp
Normal file
@@ -0,0 +1,409 @@
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include "RaidKarazhanHelpers.h"
|
||||
#include "RaidKarazhanActions.h"
|
||||
#include "AiObjectContext.h"
|
||||
#include "PlayerbotMgr.h"
|
||||
#include "Position.h"
|
||||
#include "Spell.h"
|
||||
|
||||
const Position KARAZHAN_MAIDEN_OF_VIRTUE_BOSS_POSITION = Position(-10945.881f, -2103.782f, 92.712f);
|
||||
const Position KARAZHAN_MAIDEN_OF_VIRTUE_RANGED_POSITION[8] =
|
||||
{
|
||||
{ -10931.178f, -2116.580f, 92.179f },
|
||||
{ -10925.828f, -2102.425f, 92.180f },
|
||||
{ -10933.089f, -2088.5017f, 92.180f },
|
||||
{ -10947.59f, -2082.8147f, 92.180f },
|
||||
{ -10960.912f, -2090.4368f, 92.179f },
|
||||
{ -10966.017f, -2105.288f, 92.175f },
|
||||
{ -10959.242f, -2119.6172f, 92.180f },
|
||||
{ -10944.495f, -2123.857f, 92.180f },
|
||||
};
|
||||
|
||||
const Position KARAZHAN_BIG_BAD_WOLF_BOSS_POSITION = Position(-10913.391f, -1773.508f, 90.477f);
|
||||
const Position KARAZHAN_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 KARAZHAN_THE_CURATOR_BOSS_POSITION = Position(-11139.463f, -1884.645f, 165.765f);
|
||||
|
||||
void RaidKarazhanHelpers::MarkTargetWithSkull(Unit* target)
|
||||
{
|
||||
if (!target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
constexpr uint8_t skullIconId = 7;
|
||||
ObjectGuid skullGuid = group->GetTargetIcon(skullIconId);
|
||||
|
||||
if (skullGuid != target->GetGUID())
|
||||
{
|
||||
group->SetTargetIcon(skullIconId, bot->GetGUID(), target->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Unit* RaidKarazhanHelpers::GetFirstAliveUnit(const std::vector<Unit*>& units)
|
||||
{
|
||||
for (Unit* unit : units)
|
||||
{
|
||||
if (unit && unit->IsAlive())
|
||||
{
|
||||
return unit;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Unit* RaidKarazhanHelpers::GetFirstAliveUnitByEntry(uint32 entry)
|
||||
{
|
||||
const GuidVector npcs = AI_VALUE(GuidVector, "nearest hostile npcs");
|
||||
|
||||
for (const auto& npcGuid : npcs)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(npcGuid);
|
||||
|
||||
if (unit && unit->IsAlive() && unit->GetEntry() == entry)
|
||||
{
|
||||
return unit;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Unit* RaidKarazhanHelpers::GetNearestPlayerInRadius(float radius)
|
||||
{
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* member = itr->GetSource();
|
||||
|
||||
if (!member || !member->IsAlive() || member == bot)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bot->GetExactDist2d(member) < radius)
|
||||
{
|
||||
return member;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool RaidKarazhanHelpers::IsFlameWreathActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "shade of aran");
|
||||
Spell* currentSpell = boss ? boss->GetCurrentSpell(CURRENT_GENERIC_SPELL) : nullptr;
|
||||
if (currentSpell && currentSpell->m_spellInfo && currentSpell->m_spellInfo->Id == SPELL_FLAME_WREATH)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* member = itr->GetSource();
|
||||
if (!member || !member->IsAlive())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (member->HasAura(SPELL_AURA_FLAME_WREATH))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Red beam blockers: tank bots, no Nether Exhaustion Red
|
||||
std::vector<Player*> RaidKarazhanHelpers::GetRedBlockers()
|
||||
{
|
||||
std::vector<Player*> redBlockers;
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* member = itr->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 ≤25 stacks of Blue Beam debuff
|
||||
std::vector<Player*> RaidKarazhanHelpers::GetBlueBlockers()
|
||||
{
|
||||
std::vector<Player*> blueBlockers;
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* member = itr->GetSource();
|
||||
if (!member || !member->IsAlive() || !GET_PLAYERBOT_AI(member))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool isDps = botAI->IsDps(member);
|
||||
bool isWarrior = member->getClass() == CLASS_WARRIOR;
|
||||
bool isRogue = member->getClass() == CLASS_ROGUE;
|
||||
bool hasExhaustion = member->HasAura(SPELL_NETHER_EXHAUSTION_BLUE);
|
||||
Aura* blueBuff = member->GetAura(SPELL_BLUE_BEAM_DEBUFF);
|
||||
bool overStack = blueBuff && blueBuff->GetStackAmount() >= 26;
|
||||
if (isDps && !isWarrior && !isRogue && !hasExhaustion && !overStack)
|
||||
{
|
||||
blueBlockers.push_back(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blueBlockers;
|
||||
}
|
||||
|
||||
// Green beam blockers:
|
||||
// (1) Rogue and non-tank Warrior bots, no Nether Exhaustion Green
|
||||
// (2) Healer bots, no Nether Exhaustion Green and ≤25 stacks of Green Beam debuff
|
||||
std::vector<Player*> RaidKarazhanHelpers::GetGreenBlockers()
|
||||
{
|
||||
std::vector<Player*> greenBlockers;
|
||||
if (Group* group = bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* member = itr->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() >= 26;
|
||||
bool isRogue = member->getClass() == CLASS_ROGUE;
|
||||
bool isDpsWarrior = member->getClass() == CLASS_WARRIOR && botAI->IsDps(member);
|
||||
bool eligibleRogueWarrior = (isRogue || isDpsWarrior) && !hasExhaustion;
|
||||
bool isHealer = botAI->IsHeal(member);
|
||||
bool eligibleHealer = isHealer && !hasExhaustion && !overStack;
|
||||
if (eligibleRogueWarrior || eligibleHealer)
|
||||
{
|
||||
greenBlockers.push_back(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return greenBlockers;
|
||||
}
|
||||
|
||||
Position RaidKarazhanHelpers::GetPositionOnBeam(Unit* boss, Unit* portal, float distanceFromBoss)
|
||||
{
|
||||
float bx = boss->GetPositionX();
|
||||
float by = boss->GetPositionY();
|
||||
float bz = boss->GetPositionZ();
|
||||
float px = portal->GetPositionX();
|
||||
float py = portal->GetPositionY();
|
||||
|
||||
float dx = px - bx;
|
||||
float dy = py - by;
|
||||
float length = sqrt(dx*dx + dy*dy);
|
||||
if (length == 0.0f)
|
||||
{
|
||||
return Position(bx, by, bz);
|
||||
}
|
||||
|
||||
dx /= length;
|
||||
dy /= length;
|
||||
float targetX = bx + dx * distanceFromBoss;
|
||||
float targetY = by + dy * distanceFromBoss;
|
||||
float targetZ = bz;
|
||||
|
||||
return Position(targetX, targetY, targetZ);
|
||||
}
|
||||
|
||||
std::tuple<Player*, Player*, Player*> RaidKarazhanHelpers::GetCurrentBeamBlockers()
|
||||
{
|
||||
static ObjectGuid currentRedBlocker;
|
||||
static ObjectGuid currentGreenBlocker;
|
||||
static ObjectGuid currentBlueBlocker;
|
||||
|
||||
Player* redBlocker = nullptr;
|
||||
Player* greenBlocker = nullptr;
|
||||
Player* blueBlocker = nullptr;
|
||||
|
||||
std::vector<Player*> redBlockers = GetRedBlockers();
|
||||
if (!redBlockers.empty())
|
||||
{
|
||||
auto it = std::find_if(redBlockers.begin(), redBlockers.end(), [](Player* p)
|
||||
{
|
||||
return p && p->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();
|
||||
if (!greenBlockers.empty())
|
||||
{
|
||||
auto it = std::find_if(greenBlockers.begin(), greenBlockers.end(), [](Player* p)
|
||||
{
|
||||
return p && p->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();
|
||||
if (!blueBlockers.empty())
|
||||
{
|
||||
auto it = std::find_if(blueBlockers.begin(), blueBlockers.end(), [](Player* p)
|
||||
{
|
||||
return p && p->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*> RaidKarazhanHelpers::GetAllVoidZones()
|
||||
{
|
||||
std::vector<Unit*> voidZones;
|
||||
const float radius = 30.0f;
|
||||
const GuidVector npcs = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest npcs")->Get();
|
||||
for (const auto& 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 RaidKarazhanHelpers::IsSafePosition(float x, float y, float z,
|
||||
const std::vector<Unit*>& hazards, float hazardRadius)
|
||||
{
|
||||
for (Unit* hazard : hazards)
|
||||
{
|
||||
float dist = std::sqrt(std::pow(x - hazard->GetPositionX(), 2) + std::pow(y - hazard->GetPositionY(), 2));
|
||||
if (dist < hazardRadius)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Unit*> RaidKarazhanHelpers::GetSpawnedInfernals() const
|
||||
{
|
||||
std::vector<Unit*> infernals;
|
||||
const GuidVector npcs = botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest npcs")->Get();
|
||||
for (const auto& npcGuid : npcs)
|
||||
{
|
||||
Unit* unit = botAI->GetUnit(npcGuid);
|
||||
if (unit && unit->GetEntry() == NPC_NETHERSPITE_INFERNAL)
|
||||
{
|
||||
infernals.push_back(unit);
|
||||
}
|
||||
}
|
||||
|
||||
return infernals;
|
||||
}
|
||||
|
||||
bool RaidKarazhanHelpers::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();
|
||||
float totalDist = std::sqrt(std::pow(tx - sx, 2) + std::pow(ty - sy, 2));
|
||||
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)
|
||||
{
|
||||
float hazardDist = std::sqrt(std::pow(checkX - hazard->GetPositionX(), 2) + std::pow(checkY - hazard->GetPositionY(), 2));
|
||||
if (hazardDist < hazardRadius)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
85
src/strategy/raids/karazhan/RaidKarazhanHelpers.h
Normal file
85
src/strategy/raids/karazhan/RaidKarazhanHelpers.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANHELPERS_H_
|
||||
#define _PLAYERBOT_RAIDKARAZHANHELPERS_H_
|
||||
|
||||
#include "AiObject.h"
|
||||
#include "Playerbots.h"
|
||||
#include "Position.h"
|
||||
|
||||
enum KarazhanSpells
|
||||
{
|
||||
// Maiden of Virtue
|
||||
SPELL_REPENTANCE = 29511,
|
||||
|
||||
// Opera Event
|
||||
SPELL_LITTLE_RED_RIDING_HOOD = 30756,
|
||||
|
||||
// Shade of Aran
|
||||
SPELL_FLAME_WREATH = 30004,
|
||||
SPELL_AURA_FLAME_WREATH = 29946,
|
||||
SPELL_ARCANE_EXPLOSION = 29973,
|
||||
SPELL_WARLOCK_BANISH = 18647, // Rank 2
|
||||
|
||||
// Netherspite
|
||||
SPELL_GREEN_BEAM_DEBUFF = 30422,
|
||||
SPELL_BLUE_BEAM_DEBUFF = 30423,
|
||||
SPELL_NETHER_EXHAUSTION_RED = 38637,
|
||||
SPELL_NETHER_EXHAUSTION_GREEN = 38638,
|
||||
SPELL_NETHER_EXHAUSTION_BLUE = 38639,
|
||||
SPELL_NETHERSPITE_BANISHED = 39833,
|
||||
|
||||
// Prince Malchezaar
|
||||
SPELL_ENFEEBLE = 30843,
|
||||
};
|
||||
|
||||
enum KarazhanNpcs
|
||||
{
|
||||
// Attumen the Huntsman
|
||||
NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED = 16152,
|
||||
|
||||
// Terestian Illhoof
|
||||
NPC_KILREK = 17229,
|
||||
NPC_DEMON_CHAINS = 17248,
|
||||
|
||||
// Shade of Aran
|
||||
NPC_CONJURED_ELEMENTAL = 17167,
|
||||
|
||||
// Netherspite
|
||||
NPC_VOID_ZONE = 16697,
|
||||
NPC_RED_PORTAL = 17369,
|
||||
NPC_BLUE_PORTAL = 17368,
|
||||
NPC_GREEN_PORTAL = 17367,
|
||||
|
||||
// Prince Malchezaar
|
||||
NPC_NETHERSPITE_INFERNAL = 17646,
|
||||
};
|
||||
|
||||
extern const Position KARAZHAN_MAIDEN_OF_VIRTUE_BOSS_POSITION;
|
||||
extern const Position KARAZHAN_MAIDEN_OF_VIRTUE_RANGED_POSITION[8];
|
||||
extern const Position KARAZHAN_BIG_BAD_WOLF_BOSS_POSITION;
|
||||
extern const Position KARAZHAN_BIG_BAD_WOLF_RUN_POSITION[4];
|
||||
extern const Position KARAZHAN_THE_CURATOR_BOSS_POSITION;
|
||||
|
||||
class RaidKarazhanHelpers : public AiObject
|
||||
{
|
||||
public:
|
||||
explicit RaidKarazhanHelpers(PlayerbotAI* botAI) : AiObject(botAI) {}
|
||||
|
||||
void MarkTargetWithSkull(Unit* /*target*/);
|
||||
Unit* GetFirstAliveUnit(const std::vector<Unit*>& /*units*/);
|
||||
Unit* GetFirstAliveUnitByEntry(uint32 /*entry*/);
|
||||
Unit* GetNearestPlayerInRadius(float /*radius*/ = 5.0f);
|
||||
bool IsFlameWreathActive();
|
||||
Position GetPositionOnBeam(Unit* boss, Unit* portal, float distanceFromBoss);
|
||||
std::vector<Player*> GetRedBlockers();
|
||||
std::vector<Player*> GetBlueBlockers();
|
||||
std::vector<Player*> GetGreenBlockers();
|
||||
std::tuple<Player*, Player*, Player*> GetCurrentBeamBlockers();
|
||||
std::vector<Unit*> GetAllVoidZones();
|
||||
bool IsSafePosition (float x, float y, float z,
|
||||
const std::vector<Unit*>& hazards, float hazardRadius);
|
||||
std::vector<Unit*> GetSpawnedInfernals() const;
|
||||
bool IsStraightPathSafe(const Position& start, const Position& target,
|
||||
const std::vector<Unit*>& hazards, float hazardRadius, float stepSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
266
src/strategy/raids/karazhan/RaidKarazhanMultipliers.cpp
Normal file
266
src/strategy/raids/karazhan/RaidKarazhanMultipliers.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
#include "RaidKarazhanMultipliers.h"
|
||||
#include "RaidKarazhanActions.h"
|
||||
#include "RaidKarazhanHelpers.h"
|
||||
#include "AiObjectContext.h"
|
||||
#include "AttackAction.h"
|
||||
#include "DruidBearActions.h"
|
||||
#include "DruidCatActions.h"
|
||||
#include "RogueActions.h"
|
||||
#include "WarriorActions.h"
|
||||
|
||||
static bool IsChargeAction(Action* action)
|
||||
{
|
||||
return dynamic_cast<CastChargeAction*>(action) ||
|
||||
dynamic_cast<CastInterceptAction*>(action) ||
|
||||
dynamic_cast<CastFeralChargeBearAction*>(action) ||
|
||||
dynamic_cast<CastFeralChargeCatAction*>(action);
|
||||
}
|
||||
|
||||
float KarazhanAttumenTheHuntsmanMultiplier::GetValue(Action* action)
|
||||
{
|
||||
RaidKarazhanHelpers karazhanHelper(botAI);
|
||||
Unit* boss = karazhanHelper.GetFirstAliveUnitByEntry(NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED);
|
||||
if (boss && !(botAI->IsTank(bot) && botAI->HasAggro(boss) && boss->GetVictim() == bot) &&
|
||||
(dynamic_cast<MovementAction*>(action) &&
|
||||
!dynamic_cast<KarazhanAttumenTheHuntsmanStackBehindAction*>(action)))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float KarazhanBigBadWolfMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "the big bad wolf");
|
||||
if (!boss)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if (bot->HasAura(SPELL_LITTLE_RED_RIDING_HOOD))
|
||||
{
|
||||
if ((dynamic_cast<MovementAction*>(action) && !dynamic_cast<KarazhanBigBadWolfRunAwayAction*>(action)) ||
|
||||
(dynamic_cast<AttackAction*>(action)))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float KarazhanShadeOfAranMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "shade of aran");
|
||||
if (!boss)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if (boss->HasUnitState(UNIT_STATE_CASTING) && boss->FindCurrentSpellBySpellId(SPELL_ARCANE_EXPLOSION))
|
||||
{
|
||||
if (IsChargeAction(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (dynamic_cast<MovementAction*>(action))
|
||||
{
|
||||
const float safeDistance = 20.0f;
|
||||
if (bot->GetDistance2d(boss) >= safeDistance)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool flameWreathActive = boss->HasAura(SPELL_FLAME_WREATH);
|
||||
if (!flameWreathActive && bot->GetGroup())
|
||||
{
|
||||
for (GroupReference* itr = bot->GetGroup()->GetFirstMember(); itr != nullptr; itr = itr->next())
|
||||
{
|
||||
Player* member = itr->GetSource();
|
||||
if (member && member->HasAura(SPELL_AURA_FLAME_WREATH))
|
||||
{
|
||||
flameWreathActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flameWreathActive)
|
||||
{
|
||||
if (dynamic_cast<MovementAction*>(action) || IsChargeAction(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float KarazhanNetherspiteBlueAndGreenBeamMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
if (!boss || !boss->IsAlive())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if (dynamic_cast<AvoidAoeAction*>(action) || dynamic_cast<CastKillingSpreeAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
RaidKarazhanHelpers karazhanHelper(botAI);
|
||||
auto [redBlocker /*unused*/, greenBlocker, blueBlocker] = karazhanHelper.GetCurrentBeamBlockers();
|
||||
bool isBlocker = (bot == greenBlocker || bot == blueBlocker);
|
||||
if (isBlocker)
|
||||
{
|
||||
Unit* bluePortal = bot->FindNearestCreature(NPC_BLUE_PORTAL, 150.0f);
|
||||
Unit* greenPortal = bot->FindNearestCreature(NPC_GREEN_PORTAL, 150.0f);
|
||||
bool inBeam = false;
|
||||
for (Unit* portal : {bluePortal, greenPortal})
|
||||
{
|
||||
if (!portal)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
float bx = boss->GetPositionX(), by = boss->GetPositionY();
|
||||
float px = portal->GetPositionX(), py = portal->GetPositionY();
|
||||
float dx = px - bx, dy = py - by;
|
||||
float length = sqrt(dx*dx + dy*dy);
|
||||
if (length == 0.0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dx /= length; dy /= length;
|
||||
float botdx = bot->GetPositionX() - bx, botdy = bot->GetPositionY() - by;
|
||||
float t = (botdx * dx + botdy * dy);
|
||||
float beamX = bx + dx * t, beamY = by + dy * t;
|
||||
float distToBeam = sqrt(pow(bot->GetPositionX() - beamX, 2) + pow(bot->GetPositionY() - beamY, 2));
|
||||
if (distToBeam < 0.3f && t > 0.0f && t < length)
|
||||
{
|
||||
inBeam = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (inBeam)
|
||||
{
|
||||
std::vector<Unit*> voidZones = karazhanHelper.GetAllVoidZones();
|
||||
bool inVoidZone = false;
|
||||
for (Unit* vz : voidZones)
|
||||
{
|
||||
if (bot->GetExactDist2d(vz) < 4.0f)
|
||||
{
|
||||
inVoidZone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!inVoidZone)
|
||||
{
|
||||
if (dynamic_cast<MovementAction*>(action) || IsChargeAction(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float KarazhanNetherspiteRedBeamMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
if (!boss || !boss->IsAlive())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if (dynamic_cast<AvoidAoeAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
RaidKarazhanHelpers karazhanHelper(botAI);
|
||||
auto [redBlocker, greenBlocker /*unused*/, blueBlocker /*unused*/] = karazhanHelper.GetCurrentBeamBlockers();
|
||||
static std::map<ObjectGuid, uint32> beamMoveTimes;
|
||||
static std::map<ObjectGuid, bool> lastBeamMoveSideways;
|
||||
ObjectGuid botGuid = bot->GetGUID();
|
||||
Unit* redPortal = bot->FindNearestCreature(NPC_RED_PORTAL, 150.0f);
|
||||
if (bot == redBlocker && boss && redPortal)
|
||||
{
|
||||
Position blockingPos = karazhanHelper.GetPositionOnBeam(boss, redPortal, 18.0f);
|
||||
float bx = boss->GetPositionX();
|
||||
float by = boss->GetPositionY();
|
||||
float px = redPortal->GetPositionX();
|
||||
float py = redPortal->GetPositionY();
|
||||
float dx = px - bx;
|
||||
float dy = py - by;
|
||||
float length = sqrt(dx*dx + dy*dy);
|
||||
if (length != 0.0f)
|
||||
{
|
||||
dx /= length;
|
||||
dy /= length;
|
||||
float perpDx = -dy;
|
||||
float perpDy = dx;
|
||||
Position sidewaysPos(blockingPos.GetPositionX() + perpDx * 3.0f,
|
||||
blockingPos.GetPositionY() + perpDy * 3.0f,
|
||||
blockingPos.GetPositionZ());
|
||||
|
||||
uint32 intervalSecs = 5;
|
||||
if (beamMoveTimes[botGuid] == 0)
|
||||
{
|
||||
beamMoveTimes[botGuid] = time(nullptr);
|
||||
lastBeamMoveSideways[botGuid] = false;
|
||||
}
|
||||
if (time(nullptr) - beamMoveTimes[botGuid] >= intervalSecs)
|
||||
{
|
||||
lastBeamMoveSideways[botGuid] = !lastBeamMoveSideways[botGuid];
|
||||
beamMoveTimes[botGuid] = time(nullptr);
|
||||
}
|
||||
Position targetPos = lastBeamMoveSideways[botGuid] ? sidewaysPos : blockingPos;
|
||||
float distToTarget = bot->GetExactDist2d(targetPos.GetPositionX(), targetPos.GetPositionY());
|
||||
const float positionTolerance = 1.5f;
|
||||
if (distToTarget < positionTolerance)
|
||||
{
|
||||
if (dynamic_cast<MovementAction*>(action) || IsChargeAction(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float KarazhanPrinceMalchezaarMultiplier::GetValue(Action* action)
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "prince malchezaar");
|
||||
if (!boss || !boss->IsAlive())
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if (dynamic_cast<AvoidAoeAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (botAI->IsMelee(bot) && bot->HasAura(SPELL_ENFEEBLE) &&
|
||||
!dynamic_cast<KarazhanPrinceMalchezaarNonTankAvoidHazardAction*>(action))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (botAI->IsRanged(bot) && bot->HasAura(SPELL_ENFEEBLE) &&
|
||||
(dynamic_cast<MovementAction*>(action) &&
|
||||
!dynamic_cast<KarazhanPrinceMalchezaarNonTankAvoidHazardAction*>(action)))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
48
src/strategy/raids/karazhan/RaidKarazhanMultipliers.h
Normal file
48
src/strategy/raids/karazhan/RaidKarazhanMultipliers.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANMULTIPLIERS_H
|
||||
#define _PLAYERBOT_RAIDKARAZHANMULTIPLIERS_H
|
||||
|
||||
#include "Multiplier.h"
|
||||
|
||||
class KarazhanAttumenTheHuntsmanMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
KarazhanAttumenTheHuntsmanMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "karazhan attumen the huntsman multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class KarazhanBigBadWolfMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
KarazhanBigBadWolfMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "karazhan big bad wolf multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class KarazhanShadeOfAranMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
KarazhanShadeOfAranMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "karazhan shade of aran multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class KarazhanNetherspiteBlueAndGreenBeamMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
KarazhanNetherspiteBlueAndGreenBeamMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "karazhan netherspite blue and green beam multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class KarazhanNetherspiteRedBeamMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
KarazhanNetherspiteRedBeamMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "karazhan netherspite red beam multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
class KarazhanPrinceMalchezaarMultiplier : public Multiplier
|
||||
{
|
||||
public:
|
||||
KarazhanPrinceMalchezaarMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "karazhan prince malchezaar multiplier") {}
|
||||
virtual float GetValue(Action* action);
|
||||
};
|
||||
|
||||
#endif
|
||||
81
src/strategy/raids/karazhan/RaidKarazhanStrategy.cpp
Normal file
81
src/strategy/raids/karazhan/RaidKarazhanStrategy.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "RaidKarazhanStrategy.h"
|
||||
#include "RaidKarazhanMultipliers.h"
|
||||
|
||||
void RaidKarazhanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode(
|
||||
"karazhan attumen the huntsman", NextAction::array(0,
|
||||
new NextAction("karazhan attumen the huntsman stack behind", ACTION_RAID + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"karazhan moroes", NextAction::array(0,
|
||||
new NextAction("karazhan moroes mark target", ACTION_RAID + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"karazhan maiden of virtue", NextAction::array(0,
|
||||
new NextAction("karazhan maiden of virtue position ranged", ACTION_RAID + 1),
|
||||
new NextAction("karazhan maiden of virtue position boss", ACTION_RAID + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"karazhan big bad wolf", NextAction::array(0,
|
||||
new NextAction("karazhan big bad wolf run away", ACTION_EMERGENCY + 6),
|
||||
new NextAction("karazhan big bad wolf position boss", ACTION_RAID + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"karazhan romulo and julianne", NextAction::array(0,
|
||||
new NextAction("karazhan romulo and julianne mark target", ACTION_RAID + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"karazhan wizard of oz", NextAction::array(0,
|
||||
new NextAction("karazhan wizard of oz scorch strawman", ACTION_RAID + 2),
|
||||
new NextAction("karazhan wizard of oz mark target", ACTION_RAID + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"karazhan the curator", NextAction::array(0,
|
||||
new NextAction("karazhan the curator spread ranged", ACTION_RAID + 2),
|
||||
new NextAction("karazhan the curator position boss", ACTION_RAID + 2),
|
||||
new NextAction("karazhan the curator mark target", ACTION_RAID + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"karazhan terestian illhoof", NextAction::array(0,
|
||||
new NextAction("karazhan terestian illhoof mark target", ACTION_RAID + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"karazhan shade of aran", NextAction::array(0,
|
||||
new NextAction("karazhan shade of aran flame wreath stop movement", ACTION_EMERGENCY + 7),
|
||||
new NextAction("karazhan shade of aran arcane explosion run away", ACTION_EMERGENCY + 6),
|
||||
new NextAction("karazhan shade of aran spread ranged", ACTION_RAID + 2),
|
||||
new NextAction("karazhan shade of aran mark conjured elemental", ACTION_RAID + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"karazhan netherspite", NextAction::array(0,
|
||||
new NextAction("karazhan netherspite block red beam", ACTION_EMERGENCY + 8),
|
||||
new NextAction("karazhan netherspite block blue beam", ACTION_EMERGENCY + 8),
|
||||
new NextAction("karazhan netherspite block green beam", ACTION_EMERGENCY + 8),
|
||||
new NextAction("karazhan netherspite avoid beam and void zone", ACTION_EMERGENCY + 7),
|
||||
new NextAction("karazhan netherspite banish phase avoid void zone", ACTION_RAID + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"karazhan prince malchezaar", NextAction::array(0,
|
||||
new NextAction("karazhan prince malchezaar non tank avoid hazard", ACTION_EMERGENCY + 6),
|
||||
new NextAction("karazhan prince malchezaar tank avoid hazard", ACTION_EMERGENCY + 6),
|
||||
nullptr)));
|
||||
}
|
||||
|
||||
void RaidKarazhanStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
||||
{
|
||||
multipliers.push_back(new KarazhanShadeOfAranMultiplier(botAI));
|
||||
multipliers.push_back(new KarazhanNetherspiteBlueAndGreenBeamMultiplier(botAI));
|
||||
multipliers.push_back(new KarazhanNetherspiteRedBeamMultiplier(botAI));
|
||||
multipliers.push_back(new KarazhanPrinceMalchezaarMultiplier(botAI));
|
||||
}
|
||||
18
src/strategy/raids/karazhan/RaidKarazhanStrategy.h
Normal file
18
src/strategy/raids/karazhan/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* ai) : Strategy(ai) {}
|
||||
|
||||
std::string const getName() override { return "karazhan"; }
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
39
src/strategy/raids/karazhan/RaidKarazhanTriggerContext.h
Normal file
39
src/strategy/raids/karazhan/RaidKarazhanTriggerContext.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANTRIGGERCONTEXT_H
|
||||
#define _PLAYERBOT_RAIDKARAZHANTRIGGERCONTEXT_H
|
||||
|
||||
#include "RaidKarazhanTriggers.h"
|
||||
#include "AiObjectContext.h"
|
||||
|
||||
class RaidKarazhanTriggerContext : public NamedObjectContext<Trigger>
|
||||
{
|
||||
public:
|
||||
RaidKarazhanTriggerContext()
|
||||
{
|
||||
creators["karazhan attumen the huntsman"] = &RaidKarazhanTriggerContext::karazhan_attumen_the_huntsman;
|
||||
creators["karazhan moroes"] = &RaidKarazhanTriggerContext::karazhan_moroes;
|
||||
creators["karazhan maiden of virtue"] = &RaidKarazhanTriggerContext::karazhan_maiden_of_virtue;
|
||||
creators["karazhan big bad wolf"] = &RaidKarazhanTriggerContext::karazhan_big_bad_wolf;
|
||||
creators["karazhan romulo and julianne"] = &RaidKarazhanTriggerContext::karazhan_romulo_and_julianne;
|
||||
creators["karazhan wizard of oz"] = &RaidKarazhanTriggerContext::karazhan_wizard_of_oz;
|
||||
creators["karazhan the curator"] = &RaidKarazhanTriggerContext::karazhan_the_curator;
|
||||
creators["karazhan terestian illhoof"] = &RaidKarazhanTriggerContext::karazhan_terestian_illhoof;
|
||||
creators["karazhan shade of aran"] = &RaidKarazhanTriggerContext::karazhan_shade_of_aran;
|
||||
creators["karazhan netherspite"] = &RaidKarazhanTriggerContext::karazhan_netherspite;
|
||||
creators["karazhan prince malchezaar"] = &RaidKarazhanTriggerContext::karazhan_prince_malchezaar;
|
||||
}
|
||||
|
||||
private:
|
||||
static Trigger* karazhan_attumen_the_huntsman(PlayerbotAI* botAI) { return new KarazhanAttumenTheHuntsmanTrigger(botAI); }
|
||||
static Trigger* karazhan_moroes(PlayerbotAI* botAI) { return new KarazhanMoroesTrigger(botAI); }
|
||||
static Trigger* karazhan_maiden_of_virtue(PlayerbotAI* botAI) { return new KarazhanMaidenOfVirtueTrigger(botAI); }
|
||||
static Trigger* karazhan_big_bad_wolf(PlayerbotAI* botAI) { return new KarazhanBigBadWolfTrigger(botAI); }
|
||||
static Trigger* karazhan_romulo_and_julianne(PlayerbotAI* botAI) { return new KarazhanRomuloAndJulianneTrigger(botAI); }
|
||||
static Trigger* karazhan_wizard_of_oz(PlayerbotAI* botAI) { return new KarazhanWizardOfOzTrigger(botAI); }
|
||||
static Trigger* karazhan_the_curator(PlayerbotAI* botAI) { return new KarazhanTheCuratorTrigger(botAI); }
|
||||
static Trigger* karazhan_terestian_illhoof(PlayerbotAI* botAI) { return new KarazhanTerestianIllhoofTrigger(botAI); }
|
||||
static Trigger* karazhan_shade_of_aran(PlayerbotAI* botAI) { return new KarazhanShadeOfAranTrigger(botAI); }
|
||||
static Trigger* karazhan_netherspite(PlayerbotAI* botAI) { return new KarazhanNetherspiteTrigger(botAI); }
|
||||
static Trigger* karazhan_prince_malchezaar(PlayerbotAI* botAI) { return new KarazhanPrinceMalchezaarTrigger(botAI); }
|
||||
};
|
||||
|
||||
#endif
|
||||
105
src/strategy/raids/karazhan/RaidKarazhanTriggers.cpp
Normal file
105
src/strategy/raids/karazhan/RaidKarazhanTriggers.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "RaidKarazhanTriggers.h"
|
||||
#include "RaidKarazhanHelpers.h"
|
||||
#include "RaidKarazhanActions.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
bool KarazhanAttumenTheHuntsmanTrigger::IsActive()
|
||||
{
|
||||
RaidKarazhanHelpers helpers(botAI);
|
||||
Unit* boss = helpers.GetFirstAliveUnitByEntry(NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED);
|
||||
|
||||
return boss && boss->IsAlive();
|
||||
}
|
||||
|
||||
bool KarazhanMoroesTrigger::IsActive()
|
||||
{
|
||||
Unit* moroes = AI_VALUE2(Unit*, "find target", "moroes");
|
||||
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");
|
||||
|
||||
return ((moroes && moroes->IsAlive()) ||
|
||||
(dorothea && dorothea->IsAlive()) ||
|
||||
(catriona && catriona->IsAlive()) ||
|
||||
(keira && keira->IsAlive()) ||
|
||||
(rafe && rafe->IsAlive()) ||
|
||||
(robin && robin->IsAlive()) ||
|
||||
(crispin && crispin->IsAlive()));
|
||||
}
|
||||
|
||||
bool KarazhanMaidenOfVirtueTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "maiden of virtue");
|
||||
|
||||
return boss && boss->IsAlive();
|
||||
}
|
||||
|
||||
bool KarazhanBigBadWolfTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "the big bad wolf");
|
||||
|
||||
return boss && boss->IsAlive();
|
||||
}
|
||||
|
||||
bool KarazhanRomuloAndJulianneTrigger::IsActive()
|
||||
{
|
||||
Unit* julianne = AI_VALUE2(Unit*, "find target", "julianne");
|
||||
Unit* romulo = AI_VALUE2(Unit*, "find target", "romulo");
|
||||
|
||||
return julianne && julianne->IsAlive() && romulo && romulo->IsAlive();
|
||||
}
|
||||
|
||||
bool KarazhanWizardOfOzTrigger::IsActive()
|
||||
{
|
||||
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");
|
||||
|
||||
return ((dorothee && dorothee->IsAlive()) ||
|
||||
(tito && tito->IsAlive()) ||
|
||||
(roar && roar->IsAlive()) ||
|
||||
(strawman && strawman->IsAlive()) ||
|
||||
(tinhead && tinhead->IsAlive()) ||
|
||||
(crone && crone->IsAlive()));
|
||||
}
|
||||
|
||||
bool KarazhanTheCuratorTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "the curator");
|
||||
|
||||
return boss && boss->IsAlive();
|
||||
}
|
||||
|
||||
bool KarazhanTerestianIllhoofTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "terestian illhoof");
|
||||
|
||||
return boss && boss->IsAlive();
|
||||
}
|
||||
|
||||
bool KarazhanShadeOfAranTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "shade of aran");
|
||||
|
||||
return boss && boss->IsAlive();
|
||||
}
|
||||
|
||||
bool KarazhanNetherspiteTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "netherspite");
|
||||
|
||||
return boss && boss->IsAlive();
|
||||
}
|
||||
|
||||
bool KarazhanPrinceMalchezaarTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "prince malchezaar");
|
||||
|
||||
return boss && boss->IsAlive();
|
||||
}
|
||||
83
src/strategy/raids/karazhan/RaidKarazhanTriggers.h
Normal file
83
src/strategy/raids/karazhan/RaidKarazhanTriggers.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#ifndef _PLAYERBOT_RAIDKARAZHANTRIGGERS_H
|
||||
#define _PLAYERBOT_RAIDKARAZHANTRIGGERS_H
|
||||
|
||||
#include "Trigger.h"
|
||||
|
||||
class KarazhanAttumenTheHuntsmanTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KarazhanAttumenTheHuntsmanTrigger(PlayerbotAI* botAI) : Trigger(botAI, "karazhan attumen the huntsman") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class KarazhanMoroesTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KarazhanMoroesTrigger(PlayerbotAI* botAI) : Trigger(botAI, "karazhan moroes") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class KarazhanMaidenOfVirtueTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KarazhanMaidenOfVirtueTrigger(PlayerbotAI* botAI) : Trigger(botAI, "karazhan maiden of virtue") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class KarazhanBigBadWolfTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KarazhanBigBadWolfTrigger(PlayerbotAI* botAI) : Trigger(botAI, "karazhan big bad wolf") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class KarazhanRomuloAndJulianneTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KarazhanRomuloAndJulianneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "karazhan romulo and julianne") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class KarazhanWizardOfOzTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KarazhanWizardOfOzTrigger(PlayerbotAI* botAI) : Trigger(botAI, "karazhan wizard of oz") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class KarazhanTheCuratorTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KarazhanTheCuratorTrigger(PlayerbotAI* botAI) : Trigger(botAI, "karazhan the curator") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class KarazhanTerestianIllhoofTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KarazhanTerestianIllhoofTrigger(PlayerbotAI* botAI) : Trigger(botAI, "karazhan terestian illhoof") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class KarazhanShadeOfAranTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KarazhanShadeOfAranTrigger(PlayerbotAI* botAI) : Trigger(botAI, "karazhan shade of aran") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class KarazhanNetherspiteTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KarazhanNetherspiteTrigger(PlayerbotAI* botAI) : Trigger(botAI, "karazhan netherspite") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class KarazhanPrinceMalchezaarTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
KarazhanPrinceMalchezaarTrigger(PlayerbotAI* botAI) : Trigger(botAI, "karazhan prince malchezaar") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user