diff --git a/src/strategy/raids/ulduar/RaidUlduarActionContext.h b/src/strategy/raids/ulduar/RaidUlduarActionContext.h index ddcbc523..2c8ceaad 100644 --- a/src/strategy/raids/ulduar/RaidUlduarActionContext.h +++ b/src/strategy/raids/ulduar/RaidUlduarActionContext.h @@ -45,7 +45,13 @@ public: creators["freya nature resistance action"] = &RaidUlduarActionContext::freya_nature_resistance_action; creators["freya mark dps target action"] = &RaidUlduarActionContext::freya_mark_dps_target_action; creators["freya move to healing spore action"] = &RaidUlduarActionContext::freya_move_to_healing_spore_action; + creators["thorim frost resistance action"] = &RaidUlduarActionContext::thorim_frost_resistance_action; creators["thorim nature resistance action"] = &RaidUlduarActionContext::thorim_nature_resistance_action; + creators["thorim unbalancing strike action"] = &RaidUlduarActionContext::thorim_unbalancing_strike_action; + creators["thorim mark dps target action"] = &RaidUlduarActionContext::thorim_mark_dps_target_action; + creators["thorim arena positioning action"] = &RaidUlduarActionContext::thorim_arena_positioning_action; + creators["thorim gauntlet positioning action"] = &RaidUlduarActionContext::thorim_gauntlet_positioning_action; + creators["thorim phase 2 positioning action"] = &RaidUlduarActionContext::thorim_phase2_positioning_action; creators["mimiron fire resistance action"] = &RaidUlduarActionContext::mimiron_fire_resistance_action; } @@ -79,7 +85,13 @@ private: static Action* freya_nature_resistance_action(PlayerbotAI* ai) { return new BossNatureResistanceAction(ai, "freya"); } static Action* freya_mark_dps_target_action(PlayerbotAI* ai) { return new FreyaMarkDpsTargetAction(ai); } static Action* freya_move_to_healing_spore_action(PlayerbotAI* ai) { return new FreyaMoveToHealingSporeAction(ai); } + static Action* thorim_frost_resistance_action(PlayerbotAI* ai) { return new BossFrostResistanceAction(ai, "thorim"); } static Action* thorim_nature_resistance_action(PlayerbotAI* ai) { return new BossNatureResistanceAction(ai, "thorim"); } + static Action* thorim_unbalancing_strike_action(PlayerbotAI* ai) { return new ThorimUnbalancingStrikeAction(ai); } + static Action* thorim_mark_dps_target_action(PlayerbotAI* ai) { return new ThorimMarkDpsTargetAction(ai); } + static Action* thorim_arena_positioning_action(PlayerbotAI* ai) { return new ThorimArenaPositioningAction(ai); } + static Action* thorim_gauntlet_positioning_action(PlayerbotAI* ai) { return new ThorimGauntletPositioningAction(ai); } + static Action* thorim_phase2_positioning_action(PlayerbotAI* ai) { return new ThorimPhase2PositioningAction(ai); } static Action* mimiron_fire_resistance_action(PlayerbotAI* ai) { return new BossFireResistanceAction(ai, "mimiron"); } }; diff --git a/src/strategy/raids/ulduar/RaidUlduarActions.cpp b/src/strategy/raids/ulduar/RaidUlduarActions.cpp index 6190a128..bcbe678a 100644 --- a/src/strategy/raids/ulduar/RaidUlduarActions.cpp +++ b/src/strategy/raids/ulduar/RaidUlduarActions.cpp @@ -1,6 +1,8 @@ #include "RaidUlduarActions.h" +#include + #include #include "AiObjectContext.h" @@ -25,6 +27,9 @@ #include "Unit.h" #include "Vehicle.h" +const std::string ADD_STRATEGY_CHAR = "+"; +const std::string REMOVE_STRATEGY_CHAR = "-"; + const std::vector availableVehicles = {NPC_VEHICLE_CHOPPER, NPC_SALVAGED_DEMOLISHER, NPC_SALVAGED_DEMOLISHER_TURRET, NPC_SALVAGED_SIEGE_ENGINE, NPC_SALVAGED_SIEGE_ENGINE_TURRET}; @@ -35,6 +40,8 @@ const std::vector corners = { const Position ULDUAR_KOLOGARN_RESTORE_POSITION = Position(1764.3749f, -24.02903f, 448.0f, 0.00087690353f); const Position ULDUAR_KOLOGARN_EYEBEAM_LEFT_POSITION = Position(1781.2051f, 9.34402f, 449.0f, 0.00087690353f); const Position ULDUAR_KOLOGARN_EYEBEAM_RIGHT_POSITION = Position(1763.2561f, -24.44305f, 449.0f, 0.00087690353f); +const Position ULDUAR_THORIM_JUMP_START_POINT = Position(2137.137f, -291.19025f, 438.24753f, 1.7059844f); +const Position ULDUAR_THORIM_JUMP_END_POINT = Position(2137.8818f, -278.18942f, 419.66653f); bool FlameLeviathanVehicleAction::Execute(Event event) { @@ -1688,7 +1695,7 @@ bool FreyaMarkDpsTargetAction::Execute(Event event) Unit* mainTankUnit = AI_VALUE(Unit*, "main tank"); Player* mainTank = mainTankUnit ? mainTankUnit->ToPlayer() : nullptr; int8 squareIndex = 5; // Square - int8 skullIndex = 7; // Skull + int8 skullIndex = 7; // Skull if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a real player { @@ -1769,3 +1776,393 @@ bool FreyaMoveToHealingSporeAction::Execute(Event event) return MoveTo(nearestSpore->GetMapId(), nearestSpore->GetPositionX(), nearestSpore->GetPositionY(), nearestSpore->GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT); } + +bool ThorimUnbalancingStrikeAction::isUseful() +{ + ThorimUnbalancingStrikeTrigger thorimUnbalancingStrikeTrigger(botAI); + return thorimUnbalancingStrikeTrigger.IsActive(); +} + +bool ThorimUnbalancingStrikeAction::Execute(Event event) +{ + bot->RemoveAura(SPELL_UNBALANCING_STRIKE); + return true; +} + +bool ThorimMarkDpsTargetAction::isUseful() +{ + ThorimMarkDpsTargetTrigger thorimMarkDpsTargetTrigger(botAI); + return thorimMarkDpsTargetTrigger.IsActive(); +} + +bool ThorimMarkDpsTargetAction::Execute(Event event) +{ + Unit* targetToMark = nullptr; + + Group* group = bot->GetGroup(); + if (!group) + return false; + + ObjectGuid currentMoonTarget = group->GetTargetIcon(moonIndex); + Unit* currentMoonUnit = botAI->GetUnit(currentMoonTarget); + Unit* boss = AI_VALUE2(Unit*, "find target", "thorim"); + if (!currentMoonUnit && boss && boss->IsAlive() && boss->GetPositionZ() > ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD) + { + group->SetTargetIcon(moonIndex, bot->GetGUID(), boss->GetGUID()); + } + + if (currentMoonUnit && boss && currentMoonUnit->GetEntry() == boss->GetEntry() && + boss->GetPositionZ() < ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD) + { + group->SetTargetIcon(skullIndex, bot->GetGUID(), boss->GetGUID()); + return true; + } + + if (botAI->IsMainTank(bot)) + { + ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex); + Unit* currentSkullUnit = botAI->GetUnit(currentSkullTarget); + if (currentSkullUnit && !currentSkullUnit->IsAlive()) + { + currentSkullUnit = nullptr; + } + + Unit* acolyte = AI_VALUE2(Unit*, "find target", "dark rune acolyte"); + Unit* evoker = AI_VALUE2(Unit*, "find target", "dark rune evoker"); + + if (acolyte && acolyte->IsAlive() && bot->GetDistance(acolyte) < 50.0f && + (!currentSkullUnit || currentSkullUnit->GetEntry() != acolyte->GetEntry())) + targetToMark = acolyte; + else if (evoker && evoker->IsAlive() && bot->GetDistance(evoker) < 50.0f && + (!currentSkullUnit || currentSkullUnit->GetEntry() != evoker->GetEntry())) + targetToMark = evoker; + else + return false; + } + else if (botAI->IsAssistTankOfIndex(bot, 0)) + { + ObjectGuid currentCrossTarget = group->GetTargetIcon(crossIndex); + Unit* currentCrossUnit = botAI->GetUnit(currentCrossTarget); + if (currentCrossUnit && !currentCrossUnit->IsAlive()) + { + currentCrossUnit = nullptr; + } + + Unit* acolyte = AI_VALUE2(Unit*, "find target", "dark rune acolyte"); + Unit* runicColossus = AI_VALUE2(Unit*, "find target", "runic colossus"); + Unit* ancientRuneGiant = AI_VALUE2(Unit*, "find target", "ancient rune giant"); + Unit* ironHonorGuard = AI_VALUE2(Unit*, "find target", "iron ring guard"); + Unit* ironRingGuard = AI_VALUE2(Unit*, "find target", "iron honor guard"); + + if (acolyte && acolyte->IsAlive() && (!currentCrossUnit || currentCrossUnit->GetEntry() != acolyte->GetEntry())) + targetToMark = acolyte; + else if (runicColossus && runicColossus->IsAlive() && + (!currentCrossUnit || currentCrossUnit->GetEntry() != runicColossus->GetEntry())) + targetToMark = runicColossus; + else if (ancientRuneGiant && ancientRuneGiant->IsAlive() && + (!currentCrossUnit || currentCrossUnit->GetEntry() != ancientRuneGiant->GetEntry())) + targetToMark = ancientRuneGiant; + else if (ironHonorGuard && ironHonorGuard->IsAlive() && + (!currentCrossUnit || currentCrossUnit->GetEntry() != ironHonorGuard->GetEntry())) + targetToMark = ironHonorGuard; + else if (ironRingGuard && ironRingGuard->IsAlive() && + (!currentCrossUnit || currentCrossUnit->GetEntry() != ironRingGuard->GetEntry())) + targetToMark = ironRingGuard; + else + return false; + } + + if (!targetToMark) + return false; // No target to mark + + if (botAI->IsMainTank(bot)) + { + group->SetTargetIcon(skullIndex, bot->GetGUID(), targetToMark->GetGUID()); + return true; + } + + if (botAI->IsAssistTankOfIndex(bot, 0)) + { + group->SetTargetIcon(crossIndex, bot->GetGUID(), targetToMark->GetGUID()); + return true; + } + + return false; +} + +bool ThorimArenaPositioningAction::isUseful() +{ + ThorimArenaPositioningTrigger thorimArenaPositioningTrigger(botAI); + return thorimArenaPositioningTrigger.IsActive(); +} + +bool ThorimArenaPositioningAction::Execute(Event event) +{ + FollowMasterStrategy followMasterStrategy(botAI); + + MoveTo(bot->GetMapId(), ULDUAR_THORIM_NEAR_ARENA_CENTER.GetPositionX(), + ULDUAR_THORIM_NEAR_ARENA_CENTER.GetPositionY(), ULDUAR_THORIM_NEAR_ARENA_CENTER.GetPositionZ(), false, false, + false, true, MovementPriority::MOVEMENT_COMBAT, true); + + if (botAI->HasStrategy(followMasterStrategy.getName(), BotState::BOT_STATE_NON_COMBAT)) + { + botAI->ChangeStrategy(REMOVE_STRATEGY_CHAR + followMasterStrategy.getName(), BotState::BOT_STATE_NON_COMBAT); + } + + return true; +} + +bool ThorimGauntletPositioningAction::isUseful() +{ + ThorimGauntletPositioningTrigger thorimGauntletPositioningTrigger(botAI); + return thorimGauntletPositioningTrigger.IsActive(); +} + +bool ThorimGauntletPositioningAction::Execute(Event event) +{ + FollowMasterStrategy followMasterStrategy(botAI); + + Unit* master = botAI->GetMaster(); + + std::string const rti = AI_VALUE(std::string, "rti"); + if (rti != "cross") + { + botAI->GetAiObjectContext()->GetValue("rti")->Set("cross"); + } + + if (master->GetDistance(ULDUAR_THORIM_NEAR_ENTRANCE_POSITION) < 10.0f && (bot->GetDistance2d(master) > 5.0f)) + { + if (MoveTo(bot->GetMapId(), master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), false, + false, false, true, MovementPriority::MOVEMENT_NORMAL, true)) + { + if (!botAI->HasStrategy(followMasterStrategy.getName(), BotState::BOT_STATE_NON_COMBAT)) + { + botAI->ChangeStrategy(ADD_STRATEGY_CHAR + followMasterStrategy.getName(), + BotState::BOT_STATE_NON_COMBAT); + } + + return true; + } + } + + if (master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_1) < 6.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_2) < 6.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_5_YARDS_1) < 5.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_1) < 10.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_2) < 10.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_3) < 10.0f) + { + float distance1 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_1); + float distance2 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_2); + float distance3 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_5_YARDS_1); + float distance4 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_1); + float distance5 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_2); + float distance6 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_3); + + float smallestDistance = std::min({distance1, distance2, distance3, distance4, distance5, distance6}); + + Position targetPosition; + + if (smallestDistance == distance1) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_1.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_1.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_1.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_NORMAL, true); + } + else if (smallestDistance == distance2) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_2.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_2.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_2.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_COMBAT); + } + else if (smallestDistance == distance3) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_5_YARDS_1.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_5_YARDS_1.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_5_YARDS_1.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_NORMAL, true); + } + else if (smallestDistance == distance4) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_1.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_1.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_1.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_NORMAL, true); + } + else if (smallestDistance == distance5) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_2.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_2.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_2.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_NORMAL, true); + } + else if (smallestDistance == distance6) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_3.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_3.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_3.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_NORMAL, true); + } + else + return false; + } + + if (master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_1) < 6.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_2) < 6.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_5_YARDS_1) < 5.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_1) < 10.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_2) < 10.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_3) < 10.0f) + { + float distance1 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_1); + float distance2 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_2); + float distance3 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_5_YARDS_1); + float distance4 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_1); + float distance5 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_2); + float distance6 = master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_3); + + float smallestDistance = std::min({distance1, distance2, distance3, distance4, distance5, distance6}); + + Position targetPosition; + + if (smallestDistance == distance1) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_1.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_1.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_1.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_NORMAL, true); + } + else if (smallestDistance == distance2) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_2.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_2.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_2.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_COMBAT); + } + else if (smallestDistance == distance3) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_5_YARDS_1.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_5_YARDS_1.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_5_YARDS_1.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_NORMAL, true); + } + else if (smallestDistance == distance4) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_1.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_1.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_1.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_NORMAL, true); + } + else if (smallestDistance == distance5) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_2.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_2.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_2.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_NORMAL, true); + } + else if (smallestDistance == distance6) + { + return MoveTo(bot->GetMapId(), ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_3.GetPositionX(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_3.GetPositionY(), + ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_3.GetPositionZ(), false, false, false, true, + MovementPriority::MOVEMENT_NORMAL, true); + } + else + return false; + } + + Unit* boss = AI_VALUE2(Unit*, "find target", "thorim"); + if (boss && boss->IsAlive() && bot->GetPositionZ() > ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD && + boss->GetPositionZ() < ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD) + { + MoveTo(bot->GetMapId(), ULDUAR_THORIM_JUMP_START_POINT.GetPositionX(), + ULDUAR_THORIM_JUMP_START_POINT.GetPositionY(), ULDUAR_THORIM_JUMP_START_POINT.GetPositionZ(), false, + false, false, true, MovementPriority::MOVEMENT_NORMAL, true); + + if (bot->GetDistance(ULDUAR_THORIM_JUMP_START_POINT) > 0.5f) + return false; + + JumpTo(bot->GetMapId(), ULDUAR_THORIM_JUMP_END_POINT.GetPositionX(), + ULDUAR_THORIM_JUMP_END_POINT.GetPositionY(), ULDUAR_THORIM_JUMP_END_POINT.GetPositionZ(), + MovementPriority::MOVEMENT_COMBAT); + } + + return false; +} + +bool ThorimFallFromFloorAction::Execute(Event event) +{ + Player* master = botAI->GetMaster(); + + return bot->TeleportTo(bot->GetMapId(), master->GetPositionX(), master->GetPositionY(), master->GetPositionZ(), + master->GetOrientation()); +} + +bool ThorimFallFromFloorAction::isUseful() +{ + ThorimFallFromFloorTrigger thorimFallFromFloorTrigger(botAI); + return thorimFallFromFloorTrigger.IsActive(); +} + +bool ThorimPhase2PositioningAction::Execute(Event event) +{ + Position targetPosition; + bool backward = false; + + if (botAI->IsMainTank(bot)) + { + targetPosition = ULDUAR_THORIM_PHASE2_TANK_SPOT; + backward = true; + } + else + { + Group* group = bot->GetGroup(); + if (!group) + return false; + + uint32 memberPositionNumber = 0; + for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) + { + Player* member = gref->GetSource(); + if (!member) + continue; + + if (botAI->IsRanged(member) || botAI->IsHeal(member)) + { + if (bot->GetGUID() == member->GetGUID()) + break; + + memberPositionNumber++; + + if (memberPositionNumber == 3) + memberPositionNumber = 0; + } + } + + if (memberPositionNumber == 0) + targetPosition = ULDUAR_THORIM_PHASE2_RANGE1_SPOT; + + if (memberPositionNumber == 1) + targetPosition = ULDUAR_THORIM_PHASE2_RANGE2_SPOT; + + if (memberPositionNumber == 2) + targetPosition = ULDUAR_THORIM_PHASE2_RANGE3_SPOT; + } + + MoveTo(bot->GetMapId(), targetPosition.GetPositionX(), targetPosition.GetPositionY(), + targetPosition.GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_COMBAT, true, + backward); + + if (bot->GetDistance(targetPosition) > 1.0f) + return false; + + return true; +} + +bool ThorimPhase2PositioningAction::isUseful() +{ + ThorimPhase2PositioningTrigger thorimPhase2PositioningTrigger(botAI); + return thorimPhase2PositioningTrigger.IsActive(); +} diff --git a/src/strategy/raids/ulduar/RaidUlduarActions.h b/src/strategy/raids/ulduar/RaidUlduarActions.h index 31677e6f..a2022b42 100644 --- a/src/strategy/raids/ulduar/RaidUlduarActions.h +++ b/src/strategy/raids/ulduar/RaidUlduarActions.h @@ -217,4 +217,57 @@ public: bool isUseful() override; }; +class ThorimUnbalancingStrikeAction : public Action +{ +public: + ThorimUnbalancingStrikeAction(PlayerbotAI* ai) : Action(ai, "thorim unbalancing strike action") {} + + bool Execute(Event event) override; + bool isUseful() override; +}; + +class ThorimMarkDpsTargetAction : public Action +{ +public: + ThorimMarkDpsTargetAction(PlayerbotAI* ai) : Action(ai, "thorim mark dps target action") {} + + bool Execute(Event event) override; + bool isUseful() override; +}; + +class ThorimArenaPositioningAction : public MovementAction +{ +public: + ThorimArenaPositioningAction(PlayerbotAI* ai) : MovementAction(ai, "thorim arena positioning action") {} + + bool Execute(Event event) override; + bool isUseful() override; +}; + +class ThorimGauntletPositioningAction : public MovementAction +{ +public: + ThorimGauntletPositioningAction(PlayerbotAI* ai) : MovementAction(ai, "thorim gauntlet positioning action") {} + + bool Execute(Event event) override; + bool isUseful() override; +}; + +class ThorimFallFromFloorAction : public Action +{ +public: + ThorimFallFromFloorAction(PlayerbotAI* botAI) : Action(botAI, "thorim fall from floor action") {} + bool Execute(Event event) override; + bool isUseful() override; +}; + +class ThorimPhase2PositioningAction : public MovementAction +{ +public: + ThorimPhase2PositioningAction(PlayerbotAI* ai) : MovementAction(ai, "thorim phase 2 positioning action") {} + + bool Execute(Event event) override; + bool isUseful() override; +}; + #endif diff --git a/src/strategy/raids/ulduar/RaidUlduarStrategy.cpp b/src/strategy/raids/ulduar/RaidUlduarStrategy.cpp index cb1b9a65..1eda1560 100644 --- a/src/strategy/raids/ulduar/RaidUlduarStrategy.cpp +++ b/src/strategy/raids/ulduar/RaidUlduarStrategy.cpp @@ -152,6 +152,34 @@ void RaidUlduarStrategy::InitTriggers(std::vector& triggers) "thorim nature resistance trigger", NextAction::array(0, new NextAction("thorim nature resistance action", ACTION_RAID), nullptr))); + triggers.push_back(new TriggerNode( + "thorim frost resistance trigger", + NextAction::array(0, new NextAction("thorim frost resistance action", ACTION_RAID), nullptr))); + + triggers.push_back(new TriggerNode( + "thorim unbalancing strike trigger", + NextAction::array(0, new NextAction("thorim unbalancing strike action", ACTION_RAID), nullptr))); + + triggers.push_back(new TriggerNode( + "thorim mark dps target trigger", + NextAction::array(0, new NextAction("thorim mark dps target action", ACTION_RAID), nullptr))); + + triggers.push_back(new TriggerNode( + "thorim gauntlet positioning trigger", + NextAction::array(0, new NextAction("thorim gauntlet positioning action", ACTION_RAID), nullptr))); + + triggers.push_back(new TriggerNode( + "thorim arena positioning trigger", + NextAction::array(0, new NextAction("thorim arena positioning action", ACTION_RAID), nullptr))); + + triggers.push_back(new TriggerNode( + "thorim fall from floor trigger", + NextAction::array(0, new NextAction("thorim fall from floor action", ACTION_RAID + 1), nullptr))); + + triggers.push_back(new TriggerNode( + "thorim phase 2 positioning trigger", + NextAction::array(0, new NextAction("thorim phase 2 positioning action", ACTION_RAID), nullptr))); + // // Mimiron // diff --git a/src/strategy/raids/ulduar/RaidUlduarTriggerContext.h b/src/strategy/raids/ulduar/RaidUlduarTriggerContext.h index eda5b7d0..aa3a4d4f 100644 --- a/src/strategy/raids/ulduar/RaidUlduarTriggerContext.h +++ b/src/strategy/raids/ulduar/RaidUlduarTriggerContext.h @@ -46,7 +46,14 @@ public: creators["freya nature resistance trigger"] = &RaidUlduarTriggerContext::freya_nature_resistance_trigger; creators["freya mark dps target trigger"] = &RaidUlduarTriggerContext::freya_mark_dps_target_trigger; creators["freya move to healing spore trigger"] = &RaidUlduarTriggerContext::freya_move_to_healing_spore_trigger; + creators["thorim frost resistance trigger"] = &RaidUlduarTriggerContext::thorim_frost_resistance_trigger; creators["thorim nature resistance trigger"] = &RaidUlduarTriggerContext::thorim_nature_resistance_trigger; + creators["thorim unbalancing strike trigger"] = &RaidUlduarTriggerContext::thorim_unbalancing_strike_trigger; + creators["thorim mark dps target trigger"] = &RaidUlduarTriggerContext::thorim_mark_dps_target_trigger; + creators["thorim arena positioning trigger"] = &RaidUlduarTriggerContext::thorim_arena_positioning_trigger; + creators["thorim gauntlet positioning trigger"] = &RaidUlduarTriggerContext::thorim_gauntlet_positioning_trigger; + creators["thorim fall from floor trigger"] = &RaidUlduarTriggerContext::thorim_fall_from_floor_trigger; + creators["thorim phase 2 positioning trigger"] = &RaidUlduarTriggerContext::thorim_phase2_positioning_trigger; creators["mimiron fire resistance trigger"] = &RaidUlduarTriggerContext::mimiron_fire_resistance_trigger; } @@ -81,7 +88,14 @@ private: static Trigger* freya_nature_resistance_trigger(PlayerbotAI* ai) { return new BossNatureResistanceTrigger(ai, "freya"); } static Trigger* freya_mark_dps_target_trigger(PlayerbotAI* ai) { return new FreyaMarkDpsTargetTrigger(ai); } static Trigger* freya_move_to_healing_spore_trigger(PlayerbotAI* ai) { return new FreyaMoveToHealingSporeTrigger(ai); } + static Trigger* thorim_frost_resistance_trigger(PlayerbotAI* ai) { return new BossFrostResistanceTrigger(ai, "thorim"); } static Trigger* thorim_nature_resistance_trigger(PlayerbotAI* ai) { return new BossNatureResistanceTrigger(ai, "thorim"); } + static Trigger* thorim_unbalancing_strike_trigger(PlayerbotAI* ai) { return new ThorimUnbalancingStrikeTrigger(ai); } + static Trigger* thorim_mark_dps_target_trigger(PlayerbotAI* ai) { return new ThorimMarkDpsTargetTrigger(ai); } + static Trigger* thorim_arena_positioning_trigger(PlayerbotAI* ai) { return new ThorimArenaPositioningTrigger(ai); } + static Trigger* thorim_gauntlet_positioning_trigger(PlayerbotAI* ai) { return new ThorimGauntletPositioningTrigger(ai); } + static Trigger* thorim_fall_from_floor_trigger(PlayerbotAI* ai) { return new ThorimFallFromFloorTrigger(ai); } + static Trigger* thorim_phase2_positioning_trigger(PlayerbotAI* ai) { return new ThorimPhase2PositioningTrigger(ai); } static Trigger* mimiron_fire_resistance_trigger(PlayerbotAI* ai) { return new BossFireResistanceTrigger(ai, "mimiron"); } }; diff --git a/src/strategy/raids/ulduar/RaidUlduarTriggers.cpp b/src/strategy/raids/ulduar/RaidUlduarTriggers.cpp index 67d863f6..c7cd6443 100644 --- a/src/strategy/raids/ulduar/RaidUlduarTriggers.cpp +++ b/src/strategy/raids/ulduar/RaidUlduarTriggers.cpp @@ -724,3 +724,373 @@ bool FreyaMoveToHealingSporeTrigger::IsActive() // If the nearest spore is farther than 6 yards, a move is required return nearestDistance > 6.0f; } + +bool ThorimUnbalancingStrikeTrigger::IsActive() +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "thorim"); + + // Check boss and it is alive + if (!boss || !boss->IsAlive()) + return false; + + return bot->HasAura(SPELL_UNBALANCING_STRIKE); +} + +bool ThorimMarkDpsTargetTrigger::IsActive() +{ + if (bot->GetDistance(ULDUAR_THORIM_NEAR_ARENA_CENTER) > 110.0f) + return false; + + Group* group = bot->GetGroup(); + if (!group) + return false; + + if (botAI->IsMainTank(bot)) + { + ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex); + Unit* currentSkullUnit = botAI->GetUnit(currentSkullTarget); + if (currentSkullUnit && !currentSkullUnit->IsAlive()) + { + currentSkullUnit = nullptr; + } + + Unit* acolyte = AI_VALUE2(Unit*, "find target", "dark rune acolyte"); + Unit* evoker = AI_VALUE2(Unit*, "find target", "dark rune evoker"); + + if (acolyte && acolyte->IsAlive() && bot->GetDistance(acolyte) < 50.0f && + (!currentSkullUnit || currentSkullUnit->GetEntry() != acolyte->GetEntry())) + return true; + + if (evoker && evoker->IsAlive() && bot->GetDistance(evoker) < 50.0f && + (!currentSkullUnit || currentSkullUnit->GetEntry() != evoker->GetEntry())) + return true; + + Unit* boss = AI_VALUE2(Unit*, "find target", "thorim"); + + // Check boss and it is alive + if (!boss || !boss->IsAlive()) + return false; + + + if (boss->GetPositionZ() < ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD && (!currentSkullUnit || !currentSkullUnit->IsAlive())) + { + group->SetTargetIcon(skullIndex, bot->GetGUID(), boss->GetGUID()); + return true; + } + + return false; + } + else if (botAI->IsAssistTankOfIndex(bot, 0)) + { + Player* mainTank = nullptr; + for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) + { + Player* member = gref->GetSource(); + if (member && botAI->IsMainTank(member)) + { + mainTank = member; + break; + } + } + + if (mainTank && bot->GetDistance(mainTank) < 30.0f) + return false; + + ObjectGuid currentCrossTarget = group->GetTargetIcon(crossIndex); + Unit* currentCrossUnit = botAI->GetUnit(currentCrossTarget); + if (currentCrossUnit && !currentCrossUnit->IsAlive()) + { + currentCrossUnit = nullptr; + } + + Unit* acolyte = AI_VALUE2(Unit*, "find target", "dark rune acolyte"); + if (currentCrossUnit && currentCrossUnit->GetEntry() == NPC_DARK_RUNE_ACOLYTE_I) + return false; + + Unit* runicColossus = AI_VALUE2(Unit*, "find target", "runic colossus"); + Unit* ancientRuneGiant = AI_VALUE2(Unit*, "find target", "ancient rune giant"); + Unit* ironHonorGuard = AI_VALUE2(Unit*, "find target", "iron ring guard"); + Unit* ironRingGuard = AI_VALUE2(Unit*, "find target", "iron honor guard"); + + if (acolyte && acolyte->IsAlive() && (!currentCrossUnit || currentCrossUnit->GetEntry() != acolyte->GetEntry())) + return true; + + if (currentCrossUnit && currentCrossUnit->GetEntry() == NPC_RUNIC_COLOSSUS) + return false; + if (runicColossus && runicColossus->IsAlive() && + (!currentCrossUnit || currentCrossUnit->GetEntry() != runicColossus->GetEntry())) + return true; + + if (currentCrossUnit && currentCrossUnit->GetEntry() == NPC_ANCIENT_RUNE_GIANT) + return false; + if (ancientRuneGiant && ancientRuneGiant->IsAlive() && + (!currentCrossUnit || currentCrossUnit->GetEntry() != ancientRuneGiant->GetEntry())) + return true; + + return false; + } + + return false; +} + +bool ThorimGauntletPositioningTrigger::IsActive() +{ + if (bot->GetDistance(ULDUAR_THORIM_NEAR_ARENA_CENTER) > 110.0f) + return false; + + Difficulty raidDifficulty = bot->GetRaidDifficulty(); + + Group* group = bot->GetGroup(); + if (!group) + return false; + uint32 requiredAssistTankQuantity = 1; + uint32 requiredHealerQuantity = 0; + uint32 requiredDpsQuantity = 0; + + if (raidDifficulty == Difficulty::RAID_DIFFICULTY_10MAN_NORMAL) + { + requiredDpsQuantity = 3; + requiredHealerQuantity = 1; + } + else if (raidDifficulty == Difficulty::RAID_DIFFICULTY_25MAN_NORMAL) + { + requiredDpsQuantity = 7; + requiredHealerQuantity = 2; + } + + for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) + { + Player* member = gref->GetSource(); + if (!member) + continue; + + if (requiredDpsQuantity > 0 && botAI->IsDps(member)) + { + requiredDpsQuantity--; + if (bot->GetGUID() == member->GetGUID()) + break; + } + + if (requiredAssistTankQuantity > 0 && botAI->IsAssistTankOfIndex(member, 0)) + { + requiredAssistTankQuantity--; + if (bot->GetGUID() == member->GetGUID()) + break; + } + + if (requiredHealerQuantity > 0 && botAI->IsHeal(member)) + { + requiredHealerQuantity--; + if (bot->GetGUID() == member->GetGUID()) + break; + } + + if (requiredDpsQuantity == 0 && requiredAssistTankQuantity == 0 && requiredHealerQuantity == 0) + return false; + } + + Unit* master = botAI->GetMaster(); + if (master->GetDistance(ULDUAR_THORIM_NEAR_ENTRANCE_POSITION) < 10.0f && (bot->GetDistance2d(master) > 5.0f)) + { + return true; + } + + if ((master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_1) < 6.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_2) < 6.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_5_YARDS_1) < 5.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_1) < 10.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_2) < 10.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_3) < 10.0f) && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_1) > 6.0f && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_2) > 6.0f && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_5_YARDS_1) > 5.0f && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_1) > 10.0f && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_2) > 10.0f && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_3) > 10.0f) + { + if (bot->GetPositionZ() > ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD) + return false; + + return true; + } + + if ((master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_1) < 6.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_2) < 6.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_5_YARDS_1) < 5.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_1) < 10.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_2) < 10.0f || + master->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_3) < 10.0f) && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_1) > 6.0f && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_2) > 6.0f && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_5_YARDS_1) > 5.0f && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_1) > 10.0f && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_2) > 10.0f && + bot->GetDistance(ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_3) > 10.0f) + { + if (bot->GetPositionZ() > ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD) + return false; + + return true; + } + + Unit* boss = AI_VALUE2(Unit*, "find target", "thorim"); + if (boss && boss->IsAlive() && bot->GetPositionZ() > ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD && + boss->GetPositionZ() < ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD) + { + return true; + } + + return false; +} + +bool ThorimArenaPositioningTrigger::IsActive() +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "thorim"); + + // Check boss and it is alive + if (!boss || !boss->IsAlive()) + return false; + + if (boss->GetPositionZ() < ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD) + return false; + + Difficulty raidDifficulty = bot->GetRaidDifficulty(); + + Group* group = bot->GetGroup(); + if (!group) + return false; + uint32 requiredAssistTankQuantity = 1; + uint32 requiredHealerQuantity = 0; + uint32 requiredDpsQuantity = 0; + + if (raidDifficulty == Difficulty::RAID_DIFFICULTY_10MAN_NORMAL) + { + requiredDpsQuantity = 3; + requiredHealerQuantity = 1; + } + else if (raidDifficulty == Difficulty::RAID_DIFFICULTY_25MAN_NORMAL) + { + requiredDpsQuantity = 7; + requiredHealerQuantity = 2; + } + + for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) + { + Player* member = gref->GetSource(); + if (!member) + continue; + + if (requiredDpsQuantity > 0 && botAI->IsDps(member)) + { + requiredDpsQuantity--; + if (bot->GetGUID() == member->GetGUID()) + return false; + } + + if (requiredAssistTankQuantity > 0 && botAI->IsAssistTankOfIndex(member, 0)) + { + requiredAssistTankQuantity--; + if (bot->GetGUID() == member->GetGUID()) + return false; + } + + if (requiredHealerQuantity > 0 && botAI->IsHeal(member)) + { + requiredHealerQuantity--; + if (bot->GetGUID() == member->GetGUID()) + return false; + } + + if (requiredDpsQuantity == 0 && requiredAssistTankQuantity == 0 && requiredHealerQuantity == 0) + break; + } + + GuidVector targets = AI_VALUE(GuidVector, "possible targets"); + Unit* target = nullptr; + for (auto i = targets.begin(); i != targets.end(); ++i) + { + target = botAI->GetUnit(*i); + if (!target || !target->IsAlive()) + continue; + + uint32 entry = target->GetEntry(); + + if (entry == NPC_DARK_RUNE_ACOLYTE_I || entry == NPC_CAPTURED_MERCENARY_SOLDIER_ALLY || + entry == NPC_CAPTURED_MERCENARY_SOLDIER_HORDE || entry == NPC_CAPTURED_MERCENARY_CAPTAIN_ALLY || + entry == NPC_CAPTURED_MERCENARY_CAPTAIN_HORDE || entry == NPC_JORMUNGAR_BEHEMOT || + entry == NPC_DARK_RUNE_WARBRINGER || entry == NPC_DARK_RUNE_EVOKER || entry == NPC_DARK_RUNE_CHAMPION || + entry == NPC_DARK_RUNE_COMMONER) + return false; + } + + if (bot && bot->GetDistance(ULDUAR_THORIM_NEAR_ARENA_CENTER) > 5.0f) + return true; + + return false; +} + +bool ThorimFallFromFloorTrigger::IsActive() +{ + if (bot->GetDistance(ULDUAR_THORIM_NEAR_ARENA_CENTER) > 110.0f) + return false; + + // Check if bot is on the floor + return bot->GetPositionZ() < ULDUAR_THORIM_AXIS_Z_PATHING_ISSUE_DETECT; +} + +bool ThorimPhase2PositioningTrigger::IsActive() +{ + if (!botAI->IsRanged(bot) && !botAI->IsMainTank(bot)) + return false; + + Unit* boss = AI_VALUE2(Unit*, "find target", "thorim"); + + // Check boss and it is alive + if (!boss || !boss->IsAlive()) + return false; + + if (boss->GetPositionZ() > ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD) + return false; + + if (botAI->IsMainTank(bot)) + { + if (bot->GetDistance(ULDUAR_THORIM_PHASE2_TANK_SPOT) > 1.0f && boss->GetVictim() == bot) + return true; + + return false; + } + + Group* group = bot->GetGroup(); + if (!group) + return false; + + uint32 memberPositionNumber = 0; + for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next()) + { + Player* member = gref->GetSource(); + if (!member) + continue; + + if (botAI->IsRanged(member)) + { + if (bot->GetGUID() == member->GetGUID()) + break; + + memberPositionNumber++; + + if (memberPositionNumber == 3) + memberPositionNumber = 0; + } + } + + if (memberPositionNumber == 0 && bot->GetDistance(ULDUAR_THORIM_PHASE2_RANGE1_SPOT) > 1.0f) + return true; + + if (memberPositionNumber == 1 && bot->GetDistance(ULDUAR_THORIM_PHASE2_RANGE2_SPOT) > 1.0f) + return true; + + if (memberPositionNumber == 2 && bot->GetDistance(ULDUAR_THORIM_PHASE2_RANGE3_SPOT) > 1.0f) + return true; + + return false; +} diff --git a/src/strategy/raids/ulduar/RaidUlduarTriggers.h b/src/strategy/raids/ulduar/RaidUlduarTriggers.h index 8306d899..04c93825 100644 --- a/src/strategy/raids/ulduar/RaidUlduarTriggers.h +++ b/src/strategy/raids/ulduar/RaidUlduarTriggers.h @@ -44,6 +44,24 @@ enum UlduarIDs NPC_EONARS_GIFT = 33228, GOBJECT_NATURE_BOMB = 194902, + //Thorim + NPC_DARK_RUNE_ACOLYTE_I = 32886, + NPC_CAPTURED_MERCENARY_SOLDIER_ALLY = 32885, + NPC_CAPTURED_MERCENARY_SOLDIER_HORDE = 32883, + NPC_CAPTURED_MERCENARY_CAPTAIN_ALLY = 32908, + NPC_CAPTURED_MERCENARY_CAPTAIN_HORDE = 32907, + NPC_JORMUNGAR_BEHEMOT = 32882, + NPC_DARK_RUNE_WARBRINGER = 32877, + NPC_DARK_RUNE_EVOKER = 32878, + NPC_DARK_RUNE_CHAMPION = 32876, + NPC_DARK_RUNE_COMMONER = 32904, + NPC_IRON_RING_GUARD = 32874, + NPC_RUNIC_COLOSSUS = 32872, + NPC_ANCIENT_RUNE_GIANT = 32873, + NPC_DARK_RUNE_ACOLYTE_G = 33110, + NPC_IRON_HONOR_GUARD = 32875, + SPELL_UNBALANCING_STRIKE = 62130, + // Buffs SPELL_FROST_TRAP = 13809 }; @@ -54,6 +72,28 @@ const int8 moonIndex = 4; // Moon const float ULDUAR_KOLOGARN_AXIS_Z_PATHING_ISSUE_DETECT = 420.0f; const float ULDUAR_KOLOGARN_EYEBEAM_RADIUS = 3.0f; +const float ULDUAR_THORIM_AXIS_Z_FLOOR_THRESHOLD = 429.6094f; +const float ULDUAR_THORIM_AXIS_Z_PATHING_ISSUE_DETECT = 410.0f; + + +const Position ULDUAR_THORIM_NEAR_ARENA_CENTER = Position(2134.9854f, -263.11853f, 419.8465f); +const Position ULDUAR_THORIM_NEAR_ENTRANCE_POSITION = Position(2172.4355f, -258.27957f, 418.47162f); +const Position ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_1 = Position(2237.6187f, -265.08844f, 412.17548f); +const Position ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_6_YARDS_2 = Position(2237.2498f, -275.81122f, 412.17548f); +const Position ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_5_YARDS_1 = Position(2236.895f, -294.62448f, 412.1348f); +const Position ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_1 = Position(2242.1162f, -310.15308f, 412.1348f); +const Position ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_2 = Position(2242.018f, -318.66003f, 412.1348f); +const Position ULDUAR_THORIM_GAUNTLET_LEFT_SIDE_10_YARDS_3 = Position(2242.1904f, -329.0533f, 412.1348f); +const Position ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_1 = Position(2219.5417f, -264.77167f, 412.17548f); +const Position ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_6_YARDS_2 = Position(2217.446f, -275.85248f, 412.17548f); +const Position ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_5_YARDS_1 = Position(2217.8877f, -295.01193f, 412.13434f); +const Position ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_1 = Position(2212.193f, -307.44992f, 412.1348f); +const Position ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_2 = Position(2212.1353f, -318.20795f, 412.1348f); +const Position ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_3 = Position(2212.1956f, -328.0144f, 412.1348f); +const Position ULDUAR_THORIM_PHASE2_TANK_SPOT = Position(2134.8572f, -287.0291f, 419.4935f); +const Position ULDUAR_THORIM_PHASE2_RANGE1_SPOT = Position(2112.8752f, -267.69305f, 419.52814f); +const Position ULDUAR_THORIM_PHASE2_RANGE2_SPOT = Position(2129.09f, -277.142f, 419.67462f); +const Position ULDUAR_THORIM_PHASE2_RANGE3_SPOT = Position(2156.798f, -267.57434f, 419.52722f); // // Flame Levi @@ -241,4 +281,49 @@ public: bool IsActive() override; }; +// +// Thorim +// +class ThorimUnbalancingStrikeTrigger : public Trigger +{ +public: + ThorimUnbalancingStrikeTrigger(PlayerbotAI* ai) : Trigger(ai, "thorim unbalancing strike trigger") {} + bool IsActive() override; +}; + +class ThorimMarkDpsTargetTrigger : public Trigger +{ +public: + ThorimMarkDpsTargetTrigger(PlayerbotAI* ai) : Trigger(ai, "thorim mark dps target trigger") {} + bool IsActive() override; +}; + +class ThorimGauntletPositioningTrigger : public Trigger +{ +public: + ThorimGauntletPositioningTrigger(PlayerbotAI* ai) : Trigger(ai, "thorim gauntlet positioning trigger") {} + bool IsActive() override; +}; + +class ThorimArenaPositioningTrigger : public Trigger +{ +public: + ThorimArenaPositioningTrigger(PlayerbotAI* ai) : Trigger(ai, "thorim arena positioning trigger") {} + bool IsActive() override; +}; + +class ThorimFallFromFloorTrigger : public Trigger +{ +public: + ThorimFallFromFloorTrigger(PlayerbotAI* ai) : Trigger(ai, "thorim fall from floor trigger") {} + bool IsActive() override; +}; + +class ThorimPhase2PositioningTrigger : public Trigger +{ +public: + ThorimPhase2PositioningTrigger(PlayerbotAI* ai) : Trigger(ai, "thorim phase 2 positioning trigger") {} + bool IsActive() override; +}; + #endif