From 7c49a7b6813261740ad753d6b2e1fd4bf0384ecf Mon Sep 17 00:00:00 2001 From: kadeshar Date: Thu, 6 Mar 2025 19:06:27 +0100 Subject: [PATCH] - Added tactic for Freya Nature bomb - Added tactic for Freya Eonar's gift --- .../raids/ulduar/RaidUlduarActionContext.h | 4 + .../raids/ulduar/RaidUlduarActions.cpp | 142 ++++++++++++++++++ src/strategy/raids/ulduar/RaidUlduarActions.h | 16 ++ .../raids/ulduar/RaidUlduarStrategy.cpp | 12 +- .../raids/ulduar/RaidUlduarTriggerContext.h | 4 + .../raids/ulduar/RaidUlduarTriggers.cpp | 46 ++++++ .../raids/ulduar/RaidUlduarTriggers.h | 22 +++ 7 files changed, 245 insertions(+), 1 deletion(-) diff --git a/src/strategy/raids/ulduar/RaidUlduarActionContext.h b/src/strategy/raids/ulduar/RaidUlduarActionContext.h index adc457ea..e3dcd97b 100644 --- a/src/strategy/raids/ulduar/RaidUlduarActionContext.h +++ b/src/strategy/raids/ulduar/RaidUlduarActionContext.h @@ -25,6 +25,8 @@ public: creators["razorscale harpoon action"] = &RaidUlduarActionContext::razorscale_harpoon_action; creators["razorscale fuse armor action"] = &RaidUlduarActionContext::razorscale_fuse_armor_action; creators["hodir move snowpacked icicle"] = &RaidUlduarActionContext::hodir_move_snowpacked_icicle; + creators["freya move away nature bomb"] = &RaidUlduarActionContext::freya_move_away_nature_bomb; + creators["freya mark eonars gift"] = &RaidUlduarActionContext::freya_mark_eonars_gift; } private: @@ -38,6 +40,8 @@ private: static Action* razorscale_harpoon_action(PlayerbotAI* ai) { return new RazorscaleHarpoonAction(ai); } static Action* razorscale_fuse_armor_action(PlayerbotAI* ai) { return new RazorscaleFuseArmorAction(ai); } static Action* hodir_move_snowpacked_icicle(PlayerbotAI* ai) { return new HodirMoveSnowpackedIcicleAction(ai); } + static Action* freya_move_away_nature_bomb(PlayerbotAI* ai) { return new FreyaMoveAwayNatureBombAction(ai); } + static Action* freya_mark_eonars_gift(PlayerbotAI* ai) { return new FreyaMarkEonarsGiftAction(ai); } }; #endif diff --git a/src/strategy/raids/ulduar/RaidUlduarActions.cpp b/src/strategy/raids/ulduar/RaidUlduarActions.cpp index 1a949161..92f222b2 100644 --- a/src/strategy/raids/ulduar/RaidUlduarActions.cpp +++ b/src/strategy/raids/ulduar/RaidUlduarActions.cpp @@ -18,6 +18,7 @@ #include "RaidUlduarBossHelper.h" #include "RaidUlduarScripts.h" #include "RaidUlduarStrategy.h" +#include "RaidUlduarTriggers.h" #include "RtiValue.h" #include "ScriptedCreature.h" #include "ServerFacade.h" @@ -398,6 +399,7 @@ bool FlameLeviathanEnterVehicleAction::AllMainVehiclesOnUse() int maxC = (diff == RAID_DIFFICULTY_10MAN_NORMAL || diff == RAID_DIFFICULTY_10MAN_HEROIC) ? 2 : 5; return demolisher >= maxC && siege >= maxC; } + bool RazorscaleAvoidDevouringFlameAction::Execute(Event event) { RazorscaleBossHelper razorscaleHelper(botAI); @@ -1187,3 +1189,143 @@ bool HodirMoveSnowpackedIcicleAction::Execute(Event event) return MoveTo(target->GetMapId(), target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), false, false, false, true, MovementPriority::MOVEMENT_NORMAL); } + +bool FreyaMoveAwayNatureBombAction::isUseful() +{ + // Check boss and it is alive + Unit* boss = AI_VALUE2(Unit*, "find target", "freya"); + if (!boss || !boss->IsAlive()) + { + return false; + } + + // Find the nearest Nature Bomb + GameObject* target = bot->FindNearestGameObject(GOBJECT_NATURE_BOMB, 12.0f); + if (!target) + return false; + + return true; +} + +bool FreyaMoveAwayNatureBombAction::Execute(Event event) +{ + GameObject* target = bot->FindNearestGameObject(GOBJECT_NATURE_BOMB, 12.0f); + if (!target) + return false; + + return FleePosition(target->GetPosition(), 13.0f); +} + +bool FreyaMarkEonarsGiftAction::isUseful() +{ + // Only tank bot can mark target + if (!botAI->IsTank(bot)) + { + return false; + } + + // Check Eonar's gift and it is alive + + // Target is not findable from threat table using AI_VALUE2(), + // therefore need to search manually for the unit id + GuidVector targets = AI_VALUE(GuidVector, "possible targets"); + Unit* target; + for (auto i = targets.begin(); i != targets.end(); ++i) + { + target = botAI->GetUnit(*i); + if (!target) + { + continue; + } + + uint32 creatureId = target->GetEntry(); + if (creatureId == NPC_EONARS_GIFT && target->IsAlive()) + { + break; + } + } + + // Check if Eonar's Gift is already set as the skull marker + Group* group = bot->GetGroup(); + if (!group) + { + return false; + } + + int8 skullIndex = 7; + ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex); + if (currentSkullTarget == target->GetGUID()) + { + return false; // Skull marker is already correctly set + } + + return true; +} + +bool FreyaMarkEonarsGiftAction::Execute(Event event) +{ + bool isMainTank = botAI->IsMainTank(bot); + Unit* mainTankUnit = AI_VALUE(Unit*, "main tank"); + Player* mainTank = mainTankUnit ? mainTankUnit->ToPlayer() : nullptr; + + GuidVector targets = AI_VALUE(GuidVector, "possible targets"); + Unit* target; + for (auto i = targets.begin(); i != targets.end(); ++i) + { + Unit* unit = botAI->GetUnit(*i); + if (!unit) + { + continue; + } + + uint32 creatureId = unit->GetEntry(); + if (creatureId == NPC_EONARS_GIFT && unit->IsAlive()) + { + target = unit; + } + } + + if (!target) + { + return false; + } + + if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a real player + { + // Iterate through the first 3 bot tanks to assign the Skull marker + for (int i = 0; i < 3; ++i) + { + if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank + { + Group* group = bot->GetGroup(); + if (group && target) + { + int8 skullIndex = 7; // Skull + ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex); + + // If there's no skull set yet, or the skull is on a different target, set the Eonar's Gift + if (!currentSkullTarget || (target->GetGUID() != currentSkullTarget)) + { + group->SetTargetIcon(skullIndex, bot->GetGUID(), target->GetGUID()); + } + } + break; // Stop after finding the first valid bot tank + } + } + } + else if (isMainTank) // Bot is the main tank + { + Group* group = bot->GetGroup(); + if (group) + { + int8 skullIndex = 7; // Skull + ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex); + + // If there's no skull set yet, or the skull is on a different target, set the Eonar's Gift + if (!currentSkullTarget || (target->GetGUID() != currentSkullTarget)) + { + group->SetTargetIcon(skullIndex, bot->GetGUID(), target->GetGUID()); + } + } + } +} diff --git a/src/strategy/raids/ulduar/RaidUlduarActions.h b/src/strategy/raids/ulduar/RaidUlduarActions.h index 2c1499a0..3c1a6504 100644 --- a/src/strategy/raids/ulduar/RaidUlduarActions.h +++ b/src/strategy/raids/ulduar/RaidUlduarActions.h @@ -114,4 +114,20 @@ public: bool isUseful() override; }; +class FreyaMoveAwayNatureBombAction : public MovementAction +{ +public: + FreyaMoveAwayNatureBombAction(PlayerbotAI* botAI) : MovementAction(botAI, "freya move away nature bomb") {} + bool Execute(Event event) override; + bool isUseful() override; +}; + +class FreyaMarkEonarsGiftAction : public MovementAction +{ +public: + FreyaMarkEonarsGiftAction(PlayerbotAI* botAI) : MovementAction(botAI, "freya mark eonars gift") {} + 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 6582fc4b..abbd5212 100644 --- a/src/strategy/raids/ulduar/RaidUlduarStrategy.cpp +++ b/src/strategy/raids/ulduar/RaidUlduarStrategy.cpp @@ -54,7 +54,17 @@ void RaidUlduarStrategy::InitTriggers(std::vector& triggers) NextAction::array(0, new NextAction("hodir move snowpacked icicle", ACTION_RAID + 5), nullptr))); triggers.push_back(new TriggerNode( "hodir biting cold", NextAction::array(0, new NextAction("intense cold jump", ACTION_RAID + 4), nullptr))); - + + // + // Freya + // + triggers.push_back( + new TriggerNode("freya tank near eonars gift", + NextAction::array(0, new NextAction("freya mark eonars gift", ACTION_RAID + 1), nullptr))); + + triggers.push_back( + new TriggerNode("freya near nature bomb", + NextAction::array(0, new NextAction("freya move away nature bomb", ACTION_RAID), nullptr))); } void RaidUlduarStrategy::InitMultipliers(std::vector& multipliers) diff --git a/src/strategy/raids/ulduar/RaidUlduarTriggerContext.h b/src/strategy/raids/ulduar/RaidUlduarTriggerContext.h index a7a1090b..6976b35c 100644 --- a/src/strategy/raids/ulduar/RaidUlduarTriggerContext.h +++ b/src/strategy/raids/ulduar/RaidUlduarTriggerContext.h @@ -26,6 +26,8 @@ public: creators["razorscale fuse armor trigger"] = &RaidUlduarTriggerContext::razorscale_fuse_armor_trigger; creators["hodir biting cold"] = &RaidUlduarTriggerContext::hodir_biting_cold; creators["hodir near snowpacked icicle"] = &RaidUlduarTriggerContext::hodir_near_snowpacked_icicle; + creators["freya near nature bomb"] = &RaidUlduarTriggerContext::freya_near_nature_bomb; + creators["freya tank near eonars gift"] = &RaidUlduarTriggerContext::freya_tank_near_eonars_gift; } private: @@ -40,6 +42,8 @@ private: static Trigger* razorscale_fuse_armor_trigger(PlayerbotAI* ai) { return new RazorscaleFuseArmorTrigger(ai); } static Trigger* hodir_biting_cold(PlayerbotAI* ai) { return new HodirBitingColdTrigger(ai); } static Trigger* hodir_near_snowpacked_icicle(PlayerbotAI* ai) { return new HodirNearSnowpackedIcicleTrigger(ai); } + static Trigger* freya_near_nature_bomb(PlayerbotAI* ai) { return new FreyaNearNatureBombTrigger(ai); } + static Trigger* freya_tank_near_eonars_gift(PlayerbotAI* ai) { return new FreyaTankNearEonarsGiftTrigger(ai); } }; #endif diff --git a/src/strategy/raids/ulduar/RaidUlduarTriggers.cpp b/src/strategy/raids/ulduar/RaidUlduarTriggers.cpp index e34be9fe..b358f0ee 100644 --- a/src/strategy/raids/ulduar/RaidUlduarTriggers.cpp +++ b/src/strategy/raids/ulduar/RaidUlduarTriggers.cpp @@ -262,3 +262,49 @@ bool HodirNearSnowpackedIcicleTrigger::IsActive() Creature* target = bot->FindNearestCreature(33174, 100.0f); return target != nullptr; } + +bool FreyaNearNatureBombTrigger::IsActive() +{ + // Check boss and it is alive + Unit* boss = AI_VALUE2(Unit*, "find target", "freya"); + if (!boss || !boss->IsAlive()) + { + return false; + } + + // Find the nearest Nature Bomb + GameObject* target = bot->FindNearestGameObject(GOBJECT_NATURE_BOMB, 12.0f); + return target != nullptr; +} + +bool FreyaTankNearEonarsGiftTrigger::IsActive() +{ + // Only tank bot can mark target + if (!botAI->IsTank(bot)) + { + return false; + } + + // Check Eonar's gift and it is alive + + // Target is not findable from threat table using AI_VALUE2(), + // therefore need to search manually for the unit id + GuidVector targets = AI_VALUE(GuidVector, "possible targets"); + + for (auto i = targets.begin(); i != targets.end(); ++i) + { + Unit* unit = botAI->GetUnit(*i); + if (!unit) + { + continue; + } + + uint32 creatureId = unit->GetEntry(); + if (creatureId == NPC_EONARS_GIFT && unit->IsAlive()) + { + return true; + } + } + + return false; +} diff --git a/src/strategy/raids/ulduar/RaidUlduarTriggers.h b/src/strategy/raids/ulduar/RaidUlduarTriggers.h index a03dfbb4..2d031874 100644 --- a/src/strategy/raids/ulduar/RaidUlduarTriggers.h +++ b/src/strategy/raids/ulduar/RaidUlduarTriggers.h @@ -7,6 +7,14 @@ #include "RaidUlduarBossHelper.h" #include "Trigger.h" +enum UlduarIDs +{ + // Freya + NPC_EONARS_GIFT = 33228, + + GOBJECT_NATURE_BOMB = 194902, +}; + // // Flame Levi // @@ -90,4 +98,18 @@ public: bool IsActive() override; }; +class FreyaNearNatureBombTrigger : public Trigger +{ +public: + FreyaNearNatureBombTrigger(PlayerbotAI* ai) : Trigger(ai, "freya near nature bomb") {} + bool IsActive() override; +}; + +class FreyaTankNearEonarsGiftTrigger : public Trigger +{ +public: + FreyaTankNearEonarsGiftTrigger(PlayerbotAI* ai) : Trigger(ai, "freya tank near eonars gift") {} + bool IsActive() override; +}; + #endif