From a695ac77fa3658081a86e1542e25571fe7e52609 Mon Sep 17 00:00:00 2001 From: kadeshar Date: Fri, 13 Mar 2026 22:22:11 +0100 Subject: [PATCH] Small fixes to naxxramas strategy (#2201) # Pull Request Small fixes to naxxramas strategy --- ## Complexity & Impact Does this change add new decision branches? - - [x] No - - [ ] Yes (**explain below**) Does this change increase per-bot or per-tick processing? - - [x] No - - [ ] Yes (**describe and justify impact**) Could this logic scale poorly under load? - - [x] No - - [ ] Yes (**explain why**) --- ## Defaults & Configuration Does this change modify default bot behavior? - - [x] No - - [ ] Yes (**explain why**) If this introduces more advanced or AI-heavy logic: - - [x] Lightweight mode remains the default - - [ ] More complex behavior is optional and thereby configurable --- ## AI Assistance Was AI assistance (e.g. ChatGPT or similar tools) used while working on this change? - - [x] No - - [ ] Yes (**explain below**) If yes, please specify: Copilot CLI to code review --- ## Final Checklist - - [x] Stability is not compromised - - [x] Performance impact is understood, tested, and acceptable - - [x] Added logic complexity is justified and explained - - [x] Documentation updated if needed --- src/Ai/Raid/Naxxramas/Action/RaidNaxxActions.h | 16 ++++++++-------- .../Action/RaidNaxxActions_Anubrekhan.cpp | 12 ++++-------- ...eman.cpp => RaidNaxxActions_FourHorsemen.cpp} | 6 +++--- .../Action/RaidNaxxActions_Sapphiron.cpp | 1 - .../Action/RaidNaxxActions_Thaddius.cpp | 4 ++-- .../Naxxramas/Multiplier/RaidNaxxMultipliers.cpp | 2 +- .../Naxxramas/Multiplier/RaidNaxxMultipliers.h | 8 ++++---- src/Ai/Raid/Naxxramas/RaidNaxxActionContext.h | 13 +++++-------- src/Ai/Raid/Naxxramas/RaidNaxxTriggerContext.h | 8 ++++---- .../Raid/Naxxramas/Strategy/RaidNaxxStrategy.cpp | 12 ++++++------ .../Raid/Naxxramas/Trigger/RaidNaxxTriggers.cpp | 4 ++-- src/Ai/Raid/Naxxramas/Trigger/RaidNaxxTriggers.h | 12 ++++++------ src/Ai/Raid/Naxxramas/Util/RaidNaxxBossHelper.h | 9 +++++---- src/Ai/Raid/Naxxramas/Util/RaidNaxxSpellIds.h | 1 + 14 files changed, 51 insertions(+), 57 deletions(-) rename src/Ai/Raid/Naxxramas/Action/{RaidNaxxActions_FourHorseman.cpp => RaidNaxxActions_FourHorsemen.cpp} (87%) diff --git a/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions.h b/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions.h index d5bfe0bc..f2712d74 100644 --- a/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions.h +++ b/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions.h @@ -37,10 +37,10 @@ public: uint32 GetCurrWaypoint() override; }; -class GrobblulusMoveCenterAction : public MoveInsideAction +class GrobbulusMoveCenterAction : public MoveInsideAction { public: - GrobblulusMoveCenterAction(PlayerbotAI* ai) : MoveInsideAction(ai, 3281.23f, -3310.38f, 5.0f) {} + GrobbulusMoveCenterAction(PlayerbotAI* ai) : MoveInsideAction(ai, 3281.23f, -3310.38f, 5.0f) {} }; class GrobbulusMoveAwayAction : public MovementAction @@ -173,26 +173,26 @@ private: RazuviousBossHelper helper; }; -class HorsemanAttractAlternativelyAction : public AttackAction +class FourHorsemenAttractAlternativelyAction : public AttackAction { public: - HorsemanAttractAlternativelyAction(PlayerbotAI* ai) : AttackAction(ai, "horseman attract alternatively"), helper(ai) + FourHorsemenAttractAlternativelyAction(PlayerbotAI* ai) : AttackAction(ai, "four horsemen attract alternatively"), helper(ai) { } bool Execute(Event event) override; protected: - FourhorsemanBossHelper helper; + FourHorsemenBossHelper helper; }; -class HorsemanAttactInOrderAction : public AttackAction +class FourHorsemenAttackInOrderAction : public AttackAction { public: - HorsemanAttactInOrderAction(PlayerbotAI* ai) : AttackAction(ai, "horseman attact in order"), helper(ai) {} + FourHorsemenAttackInOrderAction(PlayerbotAI* ai) : AttackAction(ai, "four horsemen attack in order"), helper(ai) {} bool Execute(Event event) override; protected: - FourhorsemanBossHelper helper; + FourHorsemenBossHelper helper; }; // class SapphironGroundMainTankPositionAction : public MovementAction diff --git a/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Anubrekhan.cpp b/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Anubrekhan.cpp index 7ff77ead..4391ba76 100644 --- a/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Anubrekhan.cpp +++ b/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Anubrekhan.cpp @@ -1,7 +1,6 @@ -#include "RaidNaxxActions.h" - #include "ObjectGuid.h" #include "Playerbots.h" +#include "RaidNaxxActions.h" bool AnubrekhanChooseTargetAction::Execute(Event /*event*/) { @@ -66,13 +65,10 @@ bool AnubrekhanPositionAction::Execute(Event /*event*/) { uint32 nearest = FindNearestWaypoint(); uint32 next_point; - if (inPhase) - next_point = (nearest + 1) % intervals; - else - next_point = nearest; + next_point = (nearest + 1) % intervals; - return MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, bot->GetPositionZ(), false, false, - false, false, MovementPriority::MOVEMENT_COMBAT); + return MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, + bot->GetPositionZ(), false, false, false, false, MovementPriority::MOVEMENT_COMBAT); } else return MoveInside(533, 3272.49f, -3476.27f, bot->GetPositionZ(), 3.0f, MovementPriority::MOVEMENT_COMBAT); diff --git a/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_FourHorseman.cpp b/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_FourHorsemen.cpp similarity index 87% rename from src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_FourHorseman.cpp rename to src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_FourHorsemen.cpp index 56736388..291b225e 100644 --- a/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_FourHorseman.cpp +++ b/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_FourHorsemen.cpp @@ -2,7 +2,7 @@ #include "Playerbots.h" -bool HorsemanAttractAlternativelyAction::Execute(Event /*event*/) +bool FourHorsemenAttractAlternativelyAction::Execute(Event /*event*/) { if (!helper.UpdateBossAI()) return false; @@ -13,13 +13,13 @@ bool HorsemanAttractAlternativelyAction::Execute(Event /*event*/) return true; Unit* attackTarget = helper.CurrentAttackTarget(); - if (context->GetValue("current target")->Get() != attackTarget) + if (attackTarget && context->GetValue("current target")->Get() != attackTarget) return Attack(attackTarget); return false; } -bool HorsemanAttactInOrderAction::Execute(Event /*event*/) +bool FourHorsemenAttackInOrderAction::Execute(Event /*event*/) { if (!helper.UpdateBossAI()) return false; diff --git a/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Sapphiron.cpp b/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Sapphiron.cpp index af906da8..5fb6d868 100644 --- a/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Sapphiron.cpp +++ b/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Sapphiron.cpp @@ -70,7 +70,6 @@ bool SapphironFlightPositionAction::MoveToNearestIcebolt() if (!group) return false; - Group::MemberSlotList const& slots = group->GetMemberSlots(); Player* playerWithIcebolt = nullptr; float minDistance; for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) diff --git a/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Thaddius.cpp b/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Thaddius.cpp index 0935f054..145604da 100644 --- a/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Thaddius.cpp +++ b/src/Ai/Raid/Naxxramas/Action/RaidNaxxActions_Thaddius.cpp @@ -13,7 +13,7 @@ bool ThaddiusAttackNearestPetAction::isUseful() return false; Unit* target = helper.GetNearestPet(); - if (!bot->IsWithinDistInMap(target, 50.0f)) + if (!target || !bot->IsWithinDistInMap(target, 50.0f)) return false; return true; @@ -22,7 +22,7 @@ bool ThaddiusAttackNearestPetAction::isUseful() bool ThaddiusAttackNearestPetAction::Execute(Event /*event*/) { Unit* target = helper.GetNearestPet(); - if (!bot->IsWithinLOSInMap(target)) + if (!target || !bot->IsWithinLOSInMap(target)) return MoveTo(target, 0, MovementPriority::MOVEMENT_COMBAT); if (AI_VALUE(Unit*, "current target") != target) diff --git a/src/Ai/Raid/Naxxramas/Multiplier/RaidNaxxMultipliers.cpp b/src/Ai/Raid/Naxxramas/Multiplier/RaidNaxxMultipliers.cpp index d34b48e6..39e7668f 100644 --- a/src/Ai/Raid/Naxxramas/Multiplier/RaidNaxxMultipliers.cpp +++ b/src/Ai/Raid/Naxxramas/Multiplier/RaidNaxxMultipliers.cpp @@ -245,7 +245,7 @@ float AnubrekhanGenericMultiplier::GetValue(Action* action) return 1.0f; } -float FourhorsemanGenericMultiplier::GetValue(Action* action) +float FourHorsemenGenericMultiplier::GetValue(Action* action) { Unit* boss = AI_VALUE2(Unit*, "find target", "sir zeliek"); if (!boss) diff --git a/src/Ai/Raid/Naxxramas/Multiplier/RaidNaxxMultipliers.h b/src/Ai/Raid/Naxxramas/Multiplier/RaidNaxxMultipliers.h index af702f60..f51420a2 100644 --- a/src/Ai/Raid/Naxxramas/Multiplier/RaidNaxxMultipliers.h +++ b/src/Ai/Raid/Naxxramas/Multiplier/RaidNaxxMultipliers.h @@ -1,6 +1,6 @@ -#ifndef _PLAYERRBOT_RAIDNAXXMULTIPLIERS_H -#define _PLAYERRBOT_RAIDNAXXMULTIPLIERS_H +#ifndef _PLAYERBOT_RAIDNAXXMULTIPLIERS_H +#define _PLAYERBOT_RAIDNAXXMULTIPLIERS_H #include "Multiplier.h" #include "RaidNaxxBossHelper.h" @@ -84,10 +84,10 @@ public: virtual float GetValue(Action* action); }; -class FourhorsemanGenericMultiplier : public Multiplier +class FourHorsemenGenericMultiplier : public Multiplier { public: - FourhorsemanGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "fourhorseman generic") {} + FourHorsemenGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "four horsemen generic") {} public: virtual float GetValue(Action* action); diff --git a/src/Ai/Raid/Naxxramas/RaidNaxxActionContext.h b/src/Ai/Raid/Naxxramas/RaidNaxxActionContext.h index 45941d67..4aaf9462 100644 --- a/src/Ai/Raid/Naxxramas/RaidNaxxActionContext.h +++ b/src/Ai/Raid/Naxxramas/RaidNaxxActionContext.h @@ -31,8 +31,8 @@ public: creators["razuvious use obedience crystal"] = &RaidNaxxActionContext::razuvious_use_obedience_crystal; creators["razuvious target"] = &RaidNaxxActionContext::razuvious_target; - creators["horseman attract alternatively"] = &RaidNaxxActionContext::horseman_attract_alternatively; - creators["horseman attack in order"] = &RaidNaxxActionContext::horseman_attack_in_order; + creators["four horsemen attract alternatively"] = &RaidNaxxActionContext::four_horsemen_attract_alternatively; + creators["four horsemen attack in order"] = &RaidNaxxActionContext::four_horsemen_attack_in_order; creators["sapphiron ground position"] = &RaidNaxxActionContext::sapphiron_ground_position; creators["sapphiron flight position"] = &RaidNaxxActionContext::sapphiron_flight_position; @@ -56,7 +56,7 @@ public: private: static Action* go_behind_the_boss(PlayerbotAI* ai) { return new GrobbulusGoBehindAction(ai); } static Action* rotate_grobbulus(PlayerbotAI* ai) { return new GrobbulusRotateAction(ai); } - static Action* grobbulus_move_center(PlayerbotAI* ai) { return new GrobblulusMoveCenterAction(ai); } + static Action* grobbulus_move_center(PlayerbotAI* ai) { return new GrobbulusMoveCenterAction(ai); } static Action* grobbulus_move_away(PlayerbotAI* ai) { return new GrobbulusMoveAwayAction(ai); } //static Action* heigan_dance_melee(PlayerbotAI* ai) { return new HeiganDanceMeleeAction(ai); } //static Action* heigan_dance_ranged(PlayerbotAI* ai) { return new HeiganDanceRangedAction(ai); } @@ -70,11 +70,8 @@ private: { return new RazuviousUseObedienceCrystalAction(ai); } - static Action* horseman_attract_alternatively(PlayerbotAI* ai) - { - return new HorsemanAttractAlternativelyAction(ai); - } - static Action* horseman_attack_in_order(PlayerbotAI* ai) { return new HorsemanAttactInOrderAction(ai); } + static Action* four_horsemen_attract_alternatively(PlayerbotAI* ai) { return new FourHorsemenAttractAlternativelyAction(ai); } + static Action* four_horsemen_attack_in_order(PlayerbotAI* ai) { return new FourHorsemenAttackInOrderAction(ai); } // static Action* sapphiron_ground_main_tank_position(PlayerbotAI* ai) { return new // SapphironGroundMainTankPositionAction(ai); } static Action* sapphiron_ground_position(PlayerbotAI* ai) { return new SapphironGroundPositionAction(ai); } diff --git a/src/Ai/Raid/Naxxramas/RaidNaxxTriggerContext.h b/src/Ai/Raid/Naxxramas/RaidNaxxTriggerContext.h index d980b476..4d1557d5 100644 --- a/src/Ai/Raid/Naxxramas/RaidNaxxTriggerContext.h +++ b/src/Ai/Raid/Naxxramas/RaidNaxxTriggerContext.h @@ -30,8 +30,8 @@ public: creators["razuvious tank"] = &RaidNaxxTriggerContext::razuvious_tank; creators["razuvious nontank"] = &RaidNaxxTriggerContext::razuvious_nontank; - creators["horseman attractors"] = &RaidNaxxTriggerContext::horseman_attractors; - creators["horseman except attractors"] = &RaidNaxxTriggerContext::horseman_except_attractors; + creators["four horsemen attractors"] = &RaidNaxxTriggerContext::four_horsemen_attractors; + creators["four horsemen except attractors"] = &RaidNaxxTriggerContext::four_horsemen_except_attractors; creators["sapphiron ground"] = &RaidNaxxTriggerContext::sapphiron_ground; creators["sapphiron flight"] = &RaidNaxxTriggerContext::sapphiron_flight; @@ -66,8 +66,8 @@ private: static Trigger* razuvious_tank(PlayerbotAI* ai) { return new RazuviousTankTrigger(ai); } static Trigger* razuvious_nontank(PlayerbotAI* ai) { return new RazuviousNontankTrigger(ai); } - static Trigger* horseman_attractors(PlayerbotAI* ai) { return new HorsemanAttractorsTrigger(ai); } - static Trigger* horseman_except_attractors(PlayerbotAI* ai) { return new HorsemanExceptAttractorsTrigger(ai); } + static Trigger* four_horsemen_attractors(PlayerbotAI* ai) { return new FourHorsemenAttractorsTrigger(ai); } + static Trigger* four_horsemen_except_attractors(PlayerbotAI* ai) { return new FourHorsemenExceptAttractorsTrigger(ai); } static Trigger* sapphiron_ground(PlayerbotAI* ai) { return new SapphironGroundTrigger(ai); } static Trigger* sapphiron_flight(PlayerbotAI* ai) { return new SapphironFlightTrigger(ai); } diff --git a/src/Ai/Raid/Naxxramas/Strategy/RaidNaxxStrategy.cpp b/src/Ai/Raid/Naxxramas/Strategy/RaidNaxxStrategy.cpp index e0c3421d..51f59f75 100644 --- a/src/Ai/Raid/Naxxramas/Strategy/RaidNaxxStrategy.cpp +++ b/src/Ai/Raid/Naxxramas/Strategy/RaidNaxxStrategy.cpp @@ -97,13 +97,13 @@ void RaidNaxxStrategy::InitTriggers(std::vector& triggers) { NextAction("razuvious target", ACTION_RAID + 1) } )); - // four horseman - triggers.push_back(new TriggerNode("horseman attractors", - { NextAction("horseman attract alternatively", ACTION_RAID + 1) } + // four horsemen + triggers.push_back(new TriggerNode("four horsemen attractors", + { NextAction("four horsemen attract alternatively", ACTION_RAID + 1) } )); - triggers.push_back(new TriggerNode("horseman except attractors", - { NextAction("horseman attack in order", ACTION_RAID + 1) } + triggers.push_back(new TriggerNode("four horsemen except attractors", + { NextAction("four horsemen attack in order", ACTION_RAID + 1) } )); // sapphiron @@ -150,7 +150,7 @@ void RaidNaxxStrategy::InitMultipliers(std::vector& multipliers) multipliers.push_back(new InstructorRazuviousGenericMultiplier(botAI)); multipliers.push_back(new KelthuzadGenericMultiplier(botAI)); multipliers.push_back(new AnubrekhanGenericMultiplier(botAI)); - multipliers.push_back(new FourhorsemanGenericMultiplier(botAI)); + multipliers.push_back(new FourHorsemenGenericMultiplier(botAI)); // multipliers.push_back(new GothikGenericMultiplier(botAI)); multipliers.push_back(new GluthGenericMultiplier(botAI)); } diff --git a/src/Ai/Raid/Naxxramas/Trigger/RaidNaxxTriggers.cpp b/src/Ai/Raid/Naxxramas/Trigger/RaidNaxxTriggers.cpp index f4fb38e1..3f0fc98b 100644 --- a/src/Ai/Raid/Naxxramas/Trigger/RaidNaxxTriggers.cpp +++ b/src/Ai/Raid/Naxxramas/Trigger/RaidNaxxTriggers.cpp @@ -114,7 +114,7 @@ bool RazuviousNontankTrigger::IsActive() return helper.UpdateBossAI() && !(bot->getClass() == CLASS_PRIEST); } -bool HorsemanAttractorsTrigger::IsActive() +bool FourHorsemenAttractorsTrigger::IsActive() { if (!helper.UpdateBossAI()) return false; @@ -122,7 +122,7 @@ bool HorsemanAttractorsTrigger::IsActive() return helper.IsAttracter(bot); } -bool HorsemanExceptAttractorsTrigger::IsActive() +bool FourHorsemenExceptAttractorsTrigger::IsActive() { if (!helper.UpdateBossAI()) return false; diff --git a/src/Ai/Raid/Naxxramas/Trigger/RaidNaxxTriggers.h b/src/Ai/Raid/Naxxramas/Trigger/RaidNaxxTriggers.h index 6f7727cf..c48cadd7 100644 --- a/src/Ai/Raid/Naxxramas/Trigger/RaidNaxxTriggers.h +++ b/src/Ai/Raid/Naxxramas/Trigger/RaidNaxxTriggers.h @@ -186,24 +186,24 @@ private: ThaddiusBossHelper helper; }; -class HorsemanAttractorsTrigger : public Trigger +class FourHorsemenAttractorsTrigger : public Trigger { public: - HorsemanAttractorsTrigger(PlayerbotAI* ai) : Trigger(ai, "fourhorsemen attractors"), helper(ai) {} + FourHorsemenAttractorsTrigger(PlayerbotAI* ai) : Trigger(ai, "four horsemen attractors"), helper(ai) {} bool IsActive() override; private: - FourhorsemanBossHelper helper; + FourHorsemenBossHelper helper; }; -class HorsemanExceptAttractorsTrigger : public Trigger +class FourHorsemenExceptAttractorsTrigger : public Trigger { public: - HorsemanExceptAttractorsTrigger(PlayerbotAI* ai) : Trigger(ai, "fourhorsemen except attractors"), helper(ai) {} + FourHorsemenExceptAttractorsTrigger(PlayerbotAI* ai) : Trigger(ai, "four horsemen except attractors"), helper(ai) {} bool IsActive() override; private: - FourhorsemanBossHelper helper; + FourHorsemenBossHelper helper; }; class SapphironGroundTrigger : public Trigger diff --git a/src/Ai/Raid/Naxxramas/Util/RaidNaxxBossHelper.h b/src/Ai/Raid/Naxxramas/Util/RaidNaxxBossHelper.h index 9b87bb58..a13a5b89 100644 --- a/src/Ai/Raid/Naxxramas/Util/RaidNaxxBossHelper.h +++ b/src/Ai/Raid/Naxxramas/Util/RaidNaxxBossHelper.h @@ -202,7 +202,7 @@ public: } bool FindPosToAvoidChill(std::vector& dest) { - Aura* aura = NaxxSpellIds::GetAnyAura(bot, {NaxxSpellIds::Chill25}); + Aura* aura = NaxxSpellIds::GetAnyAura(bot, {NaxxSpellIds::Chill10, NaxxSpellIds::Chill25}); if (!aura) { // Fallback to name for custom spell data. @@ -363,13 +363,13 @@ private: Unit* _unit = nullptr; }; -class FourhorsemanBossHelper : public AiObject +class FourHorsemenBossHelper : public AiObject { public: const float posZ = 241.27f; const std::pair attractPos[2] = {{2502.03f, -2910.90f}, {2484.61f, -2947.07f}}; // left (sir zeliek), right (lady blaumeux) - FourhorsemanBossHelper(PlayerbotAI* botAI) : AiObject(botAI) {} + FourHorsemenBossHelper(PlayerbotAI* botAI) : AiObject(botAI) {} bool UpdateBossAI() { if (!bot->IsInCombat()) @@ -497,7 +497,8 @@ public: if (feugen && feugen->IsAlive()) unit = feugen; - if (stalagg && stalagg->IsAlive() && (!feugen || bot->GetDistance(stalagg) < bot->GetDistance(feugen))) + if (stalagg && stalagg->IsAlive() && + (!feugen || !feugen->IsAlive() || bot->GetDistance(stalagg) < bot->GetDistance(feugen))) unit = stalagg; return unit; diff --git a/src/Ai/Raid/Naxxramas/Util/RaidNaxxSpellIds.h b/src/Ai/Raid/Naxxramas/Util/RaidNaxxSpellIds.h index 53299e7e..94c013eb 100644 --- a/src/Ai/Raid/Naxxramas/Util/RaidNaxxSpellIds.h +++ b/src/Ai/Raid/Naxxramas/Util/RaidNaxxSpellIds.h @@ -58,6 +58,7 @@ namespace NaxxSpellIds // Sapphiron static constexpr uint32 Icebolt10 = 28522; static constexpr uint32 Icebolt25 = 28526; + static constexpr uint32 Chill10 = 28547; static constexpr uint32 Chill25 = 55699; /* // Fight