From 6e5c86b84dc1bd9feef6c8e7a2adc1601406419d Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 8 Feb 2024 22:09:36 +0800 Subject: [PATCH] Naxx fourhorsemen strategy --- README.md | 3 +- src/PlayerbotAI.cpp | 30 ++++ .../raids/naxxramas/RaidNaxxActionContext.h | 8 +- .../raids/naxxramas/RaidNaxxActions.cpp | 170 +++++------------- .../raids/naxxramas/RaidNaxxActions.h | 33 ++-- .../raids/naxxramas/RaidNaxxBossHelper.h | 112 +++++++++++- .../raids/naxxramas/RaidNaxxMultipliers.cpp | 25 +-- .../raids/naxxramas/RaidNaxxMultipliers.h | 14 +- .../raids/naxxramas/RaidNaxxStrategy.cpp | 23 +-- .../raids/naxxramas/RaidNaxxTriggerContext.h | 8 +- .../raids/naxxramas/RaidNaxxTriggers.cpp | 29 ++- .../raids/naxxramas/RaidNaxxTriggers.h | 28 +-- src/strategy/values/InvalidTargetValue.cpp | 2 +- 13 files changed, 271 insertions(+), 214 deletions(-) diff --git a/README.md b/README.md index f657b34e..3c6383eb 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,7 @@ We've provided a simple method to clone the module: ```bash git clone https://github.com/liyunfan1223/azerothcore-wotlk.git --branch=Playerbot -cd azerothcore-wotlk -cd module +cd azerothcore-wotlk/modules git clone https://github.com/liyunfan1223/mod-playerbots.git --branch=master ``` diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index f4187184..8be4ee5f 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -1383,6 +1383,36 @@ bool PlayerbotAI::IsRangedDps(Player* player) return IsRanged(player) && IsDps(player); } +bool PlayerbotAI::IsHealAssistantOfIndex(Player* player, int index) +{ + Group* group = bot->GetGroup(); + if (!group) { + return false; + } + Group::MemberSlotList const& slots = group->GetMemberSlots(); + int counter = 0; + for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) { + Player* member = ref->GetSource(); + if (group->IsAssistant(member->GetGUID()) && IsHeal(member)) { + if (index == counter) { + return player == member; + } + counter++; + } + } + // not enough + for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) { + Player* member = ref->GetSource(); + if (!group->IsAssistant(member->GetGUID()) && IsHeal(member)) { + if (index == counter) { + return player == member; + } + counter++; + } + } + return false; +} + bool PlayerbotAI::IsRangedDpsAssistantOfIndex(Player* player, int index) { Group* group = bot->GetGroup(); diff --git a/src/strategy/raids/naxxramas/RaidNaxxActionContext.h b/src/strategy/raids/naxxramas/RaidNaxxActionContext.h index 9eb8bb3d..21539b8e 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxActionContext.h +++ b/src/strategy/raids/naxxramas/RaidNaxxActionContext.h @@ -28,8 +28,8 @@ class RaidNaxxActionContext : public NamedObjectContext 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["horseman attract alternatively"] = &RaidNaxxActionContext::horseman_attract_alternatively; + creators["horseman attack in order"] = &RaidNaxxActionContext::horseman_attack_in_order; creators["sapphiron ground position"] = &RaidNaxxActionContext::sapphiron_ground_position; creators["sapphiron flight position"] = &RaidNaxxActionContext::sapphiron_flight_position; @@ -60,8 +60,8 @@ class RaidNaxxActionContext : public NamedObjectContext // static Action* thaddius_move_polarity(PlayerbotAI* ai) { return new ThaddiusMovePolarityAction(ai); } static Action* razuvious_target(PlayerbotAI* ai) { return new RazuviousTargetAction(ai); } static Action* razuvious_use_obedience_crystal(PlayerbotAI* ai) { 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* horseman_attract_alternatively(PlayerbotAI* ai) { return new HorsemanAttractAlternativelyAction(ai); } + static Action* horseman_attack_in_order(PlayerbotAI* ai) { return new HorsemanAttactInOrderAction(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); } static Action* sapphiron_flight_position(PlayerbotAI* ai) { return new SapphironFlightPositionAction(ai); } diff --git a/src/strategy/raids/naxxramas/RaidNaxxActions.cpp b/src/strategy/raids/naxxramas/RaidNaxxActions.cpp index a71ba7e4..4ec48c46 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxActions.cpp +++ b/src/strategy/raids/naxxramas/RaidNaxxActions.cpp @@ -56,15 +56,6 @@ bool GrobbulusGoBehindAction::Execute(Event event) return MoveTo(bot->GetMapId(), rx, ry, z); } -// bool MoveToPointForceAction::Execute(Event event) -// { -// return MoveTo(bot->GetMapId(), x, y, bot->GetPositionZ(), true); -// } - - - - - uint32 RotateAroundTheCenterPointAction::FindNearestWaypoint() { float minDistance = 0; @@ -409,119 +400,53 @@ bool RazuviousTargetAction::Execute(Event event) return Attack(target); } -// bool HorsemanAttractAlternativelyAction::Execute(Event event) -// { -// Unit* sir = AI_VALUE2(Unit*, "find target", "sir zeliek"); -// Unit* lady = AI_VALUE2(Unit*, "find target", "lady blaumeux"); -// bool raid25 = bot->GetRaidDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL; -// if (!sir) { -// return false; -// } -// std::vector> position = { -// // left (sir zeliek) -// {2502.03f, -2910.90f}, -// // right (lady blaumeux) -// {2484.61f, -2947.07f}, -// }; -// float pos_z = 241.27f; -// BossAI* boss_ai = dynamic_cast(sir->GetAI()); -// EventMap* eventMap = boss_botAI->GetEvents(); -// const uint32 timer = eventMap->GetTimer(); -// if (lady) { -// BossAI* lady_ai = dynamic_cast(lady->GetAI()); -// EventMap* ladyEventMap = lady_botAI->GetEvents(); -// const uint32 voidZone = ladyEventMap->GetNextEventTime(5); -// if (!voidZone) { -// voidzone_counter = 0; -// } -// if (voidZone && last_voidzone != voidZone) { -// voidzone_counter = (voidzone_counter + 1) % 8; -// } -// last_voidzone = voidZone; -// } -// int pos_to_go; -// if (!lady) { -// pos_to_go = 0; -// } else { -// // 24 - 15 - 15 - ... -// if (timer <= 9000 || ((timer - 9000) / 67500) % 2 == 0) { -// pos_to_go = 0; -// } else { -// pos_to_go = 1; -// } -// if (botAI->IsRangedDpsAssistantOfIndex(bot, 0) || (raid25 && botAI->IsHealAssistantOfIndex(bot, 1))) { -// pos_to_go = 1 - pos_to_go; -// } -// } -// // bot->Yell("pos to go: " + std::to_string(pos_to_go), LANG_UNIVERSAL); -// float pos_x = position[pos_to_go].first, pos_y = position[pos_to_go].second; -// if (pos_to_go == 1) { -// float offset_x; -// float offset_y; -// if (voidzone_counter < 4) { -// offset_x = voidzone_counter * (-4.5f); -// offset_y = voidzone_counter * (4.5f); -// } -// if (voidzone_counter >= 4) { -// offset_x = (7 - voidzone_counter) * (-4.5f); -// offset_y = (7 - voidzone_counter) * (4.5f); -// offset_x += 4.5f; -// offset_y += 4.5f; -// } -// pos_x += offset_x; -// pos_y += offset_y; -// } -// if (MoveTo(bot->GetMapId(), pos_x, pos_y, pos_z)) { -// return true; -// } -// Unit* attackTarget; -// if (pos_to_go == 0) { -// attackTarget = sir; -// } else { -// attackTarget = lady; -// } -// if (context->GetValue("current target")->Get() != attackTarget) { -// return Attack(attackTarget); -// } -// return false; -// } +bool HorsemanAttractAlternativelyAction::Execute(Event event) +{ + if (!helper.UpdateBossAI()) { + return false; + } + helper.CalculatePosToGo(bot); + auto [posX, posY] = helper.CurrentAttractPos(); + if (MoveTo(bot->GetMapId(), posX, posY, helper.posZ)) { + return true; + } + Unit* attackTarget = helper.CurrentAttackTarget(); + if (context->GetValue("current target")->Get() != attackTarget) { + return Attack(attackTarget); + } + return false; +} -// bool HorsemanAttactInOrderAction::Execute(Event event) -// { -// Unit* target = nullptr; -// Unit* thane = AI_VALUE2(Unit*, "find target", "thane korth'azz"); -// Unit* baron = AI_VALUE2(Unit*, "find target", "baron rivendare"); -// Unit* lady = AI_VALUE2(Unit*, "find target", "lady blaumeux"); -// Unit* sir = AI_VALUE2(Unit*, "find target", "sir zeliek"); -// vector attack_order; -// if (botAI->IsAssistTank(bot)) { -// attack_order = {baron, thane, lady, sir}; -// } else { -// attack_order = {thane, baron, lady, sir}; -// } -// for (Unit* t : attack_order) { -// if (t) { -// target = t; -// break; -// } -// } -// if (target) { -// if (context->GetValue("current target")->Get() == target && botAI->GetCurrentState() == BOT_STATE_COMBAT) { -// return false; -// } -// if (!bot->IsWithinLOSInMap(target)) { -// return MoveNear(target, 10.0f); -// } -// return Attack(target); -// } -// return false; -// } - -// bool SapphironGroundMainTankPositionAction::Execute(Event event) -// { -// return MoveTo(533, 3512.07f, -5274.06f, 137.29f); -// // return MoveTo(533, 3498.58f, -5245.35f, 137.29f); -// } +bool HorsemanAttactInOrderAction::Execute(Event event) +{ + Unit* target = nullptr; + Unit* thane = AI_VALUE2(Unit*, "find target", "thane korth'azz"); + Unit* baron = AI_VALUE2(Unit*, "find target", "baron rivendare"); + Unit* lady = AI_VALUE2(Unit*, "find target", "lady blaumeux"); + Unit* sir = AI_VALUE2(Unit*, "find target", "sir zeliek"); + std::vector attack_order; + if (botAI->IsAssistTank(bot)) { + attack_order = {baron, thane, lady, sir}; + } else { + attack_order = {thane, baron, lady, sir}; + } + for (Unit* t : attack_order) { + if (t) { + target = t; + break; + } + } + if (target) { + if (context->GetValue("current target")->Get() == target && botAI->GetState() == BOT_STATE_COMBAT) { + return false; + } + if (!bot->IsWithinLOSInMap(target)) { + return MoveNear(target, 22.0f); + } + return Attack(target); + } + return false; +} bool SapphironGroundPositionAction::Execute(Event event) { @@ -982,9 +907,6 @@ bool GluthSlowdownAction::Execute(Event event) case CLASS_HUNTER: return botAI->CastSpell("frost trap", bot); break; - // case CLASS_MAGE: - // return botAI->CastSpell("frost nova", bot); - // break; default: break; } diff --git a/src/strategy/raids/naxxramas/RaidNaxxActions.h b/src/strategy/raids/naxxramas/RaidNaxxActions.h index 375b7410..6e36ffab 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxActions.h +++ b/src/strategy/raids/naxxramas/RaidNaxxActions.h @@ -145,24 +145,23 @@ class RazuviousTargetAction : public AttackAction RazuviousBossHelper helper; }; -// class HorsemanAttractAlternativelyAction : public AttackAction -// { -// public: -// HorsemanAttractAlternativelyAction(PlayerbotAI* ai) : AttackAction(ai, "horseman attract alternatively") { -// this->last_voidzone = 0; -// this->voidzone_counter = 0; -// } -// virtual bool Execute(Event event); -// protected: -// uint32 last_voidzone, voidzone_counter; -// }; +class HorsemanAttractAlternativelyAction : public AttackAction +{ + public: + HorsemanAttractAlternativelyAction(PlayerbotAI* ai) : AttackAction(ai, "horseman attract alternatively"), helper(ai) {} + bool Execute(Event event) override; + protected: + FourhorsemanBossHelper helper; +}; -// class HorsemanAttactInOrderAction : public AttackAction -// { -// public: -// HorsemanAttactInOrderAction(PlayerbotAI* ai) : AttackAction(ai, "horseman attact in order") {} -// virtual bool Execute(Event event); -// }; +class HorsemanAttactInOrderAction : public AttackAction +{ + public: + HorsemanAttactInOrderAction(PlayerbotAI* ai) : AttackAction(ai, "horseman attact in order"), helper(ai) {} + bool Execute(Event event) override; + protected: + FourhorsemanBossHelper helper; +}; // class SapphironGroundMainTankPositionAction : public MovementAction // { diff --git a/src/strategy/raids/naxxramas/RaidNaxxBossHelper.h b/src/strategy/raids/naxxramas/RaidNaxxBossHelper.h index 977412fa..26ee973d 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxBossHelper.h +++ b/src/strategy/raids/naxxramas/RaidNaxxBossHelper.h @@ -22,6 +22,9 @@ class GenericBossHelper : public AiObject { public: GenericBossHelper(PlayerbotAI* botAI, std::string name): AiObject(botAI), _name(name) {} virtual bool UpdateBossAI() { + if (!bot->IsInCombat()) { + _unit = nullptr; + } if(_unit && (!_unit->IsInWorld() || !_unit->IsAlive())) { _unit = nullptr; } @@ -46,10 +49,17 @@ class GenericBossHelper : public AiObject { _timer = _event_map->GetTimer(); return true; } + virtual void Reset() { + _unit = nullptr; + _target = nullptr; + _ai = nullptr; + _event_map = nullptr; + _timer = 0; + } protected: + std::string _name; Unit* _unit = nullptr; Creature* _target = nullptr; - std::string _name = nullptr; BossAiType *_ai = nullptr; EventMap* _event_map = nullptr; uint32 _timer = 0; @@ -187,4 +197,102 @@ class LoathebBossHelper: public GenericBossHelper LoathebBossHelper(PlayerbotAI *botAI): GenericBossHelper(botAI, "loatheb") {} }; -#endif \ No newline at end of file +class FourhorsemanBossHelper: public GenericBossHelper { + 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): GenericBossHelper(botAI, "sir zeliek") {} + bool UpdateBossAI() override { + if (!GenericBossHelper::UpdateBossAI()) { + return false; + } + if (!bot->IsInCombat()) { + Reset(); + } + sir = _unit; + lady = AI_VALUE2(Unit*, "find target", "lady blaumeux"); + if (!lady) { + return true; + } + ladyAI = dynamic_cast(lady->GetAI()); + if (!ladyAI) { + return true; + } + ladyEvent = &ladyAI->events; + const uint32 voidZone = ladyEvent->GetNextEventTime(EVENT_SECONDARY_SPELL); + if (voidZone && lastEventVoidZone != voidZone) { + voidZoneCounter++; + voidZoneCounter %= 8; + lastEventVoidZone = voidZone; + } + return true; + } + void Reset() override { + GenericBossHelper::Reset(); + sir = nullptr; + lady = nullptr; + ladyAI = nullptr; + ladyEvent = nullptr; + lastEventVoidZone = 0; + voidZoneCounter = 0; + posToGo = 0; + } + bool IsAttracter(Player* bot) { + Difficulty diff = bot->GetRaidDifficulty(); + if (diff == RAID_DIFFICULTY_25MAN_NORMAL) { + return botAI->IsRangedDpsAssistantOfIndex(bot, 0) || botAI->IsHealAssistantOfIndex(bot, 0) || + botAI->IsHealAssistantOfIndex(bot, 1) || botAI->IsHealAssistantOfIndex(bot, 2); + } + return botAI->IsRangedDpsAssistantOfIndex(bot, 0) || botAI->IsHealAssistantOfIndex(bot, 0); + } + void CalculatePosToGo(Player* bot) { + bool raid25 = bot->GetRaidDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL; + if (!lady) { + posToGo = 0; + } else { + // Interval: 24s - 15s - 15s - ... + posToGo = !(_timer <= 9000 || ((_timer - 9000) / 67500) % 2 == 0); + if (botAI->IsRangedDpsAssistantOfIndex(bot, 0) || (raid25 && botAI->IsHealAssistantOfIndex(bot, 1))) { + posToGo = 1 - posToGo; + } + } + } + std::pair CurrentAttractPos() + { + float posX = attractPos[posToGo].first, posY = attractPos[posToGo].second; + if (posToGo == 1) { + float offset_x; + float offset_y; + if (voidZoneCounter < 4) { + offset_x = voidZoneCounter * (-4.5f); + offset_y = voidZoneCounter * (4.5f); + } + if (voidZoneCounter >= 4) { + offset_x = (7 - voidZoneCounter) * (-4.5f); + offset_y = (7 - voidZoneCounter) * (4.5f); + offset_x += 4.5f; + offset_y += 4.5f; + } + posX += offset_x; + posY += offset_y; + } + return {posX, posY}; + } + Unit* CurrentAttackTarget() + { + if (posToGo == 0) { + return sir; + } + return lady; + } + protected: + Unit* sir = nullptr; + Unit* lady = nullptr; + boss_four_horsemen::boss_four_horsemenAI* ladyAI = nullptr; + EventMap* ladyEvent = nullptr; + uint32 lastEventVoidZone = 0; + uint32 voidZoneCounter = 0; + int posToGo = 0; +}; + +#endif diff --git a/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp b/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp index 3a29e106..2cc3c393 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp +++ b/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp @@ -210,18 +210,19 @@ float AnubrekhanGenericMultiplier::GetValue(Action* action) return 1.0f; } -// float FourhorsemanGenericMultiplier::GetValue(Action* action) -// { -// Unit* boss = AI_VALUE2(Unit*, "find target", "sir zeliek"); -// if (!boss) { -// return 1.0f; -// } -// if ((dynamic_cast(action) || -// dynamic_cast(action))) { -// return 0.0f; -// } -// return 1.0f; -// } +float FourhorsemanGenericMultiplier::GetValue(Action* action) +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "sir zeliek"); + if (!boss) { + return 1.0f; + } + context->GetValue("neglect threat")->Set(true); + if ((dynamic_cast(action) || + dynamic_cast(action))) { + return 0.0f; + } + return 1.0f; +} // float GothikGenericMultiplier::GetValue(Action* action) // { diff --git a/src/strategy/raids/naxxramas/RaidNaxxMultipliers.h b/src/strategy/raids/naxxramas/RaidNaxxMultipliers.h index 61506649..82ca328d 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxMultipliers.h +++ b/src/strategy/raids/naxxramas/RaidNaxxMultipliers.h @@ -69,14 +69,14 @@ public: virtual float GetValue(Action* action); }; -// class FourhorsemanGenericMultiplier : public Multiplier -// { -// public: -// FourhorsemanGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "fourhorseman generic") {} +class FourhorsemanGenericMultiplier : public Multiplier +{ +public: + FourhorsemanGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "fourhorseman generic") {} -// public: -// virtual float GetValue(Action* action); -// }; +public: + virtual float GetValue(Action* action); +}; // class GothikGenericMultiplier : public Multiplier // { diff --git a/src/strategy/raids/naxxramas/RaidNaxxStrategy.cpp b/src/strategy/raids/naxxramas/RaidNaxxStrategy.cpp index 24ea6844..fca2a6db 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxStrategy.cpp +++ b/src/strategy/raids/naxxramas/RaidNaxxStrategy.cpp @@ -4,10 +4,6 @@ void RaidNaxxStrategy::InitTriggers(std::vector &triggers) { - // triggers.push_back(new TriggerNode( - // "often", - // NextAction::array(0, new NextAction("try to get boss ai", ACTION_RAID), nullptr))); - // Grobbulus triggers.push_back(new TriggerNode( "mutating injection", @@ -41,8 +37,7 @@ void RaidNaxxStrategy::InitTriggers(std::vector &triggers) // Anub'Rekhan triggers.push_back(new TriggerNode( "anub'rekhan", - NextAction::array(0, - // new NextAction("anub'rekhan choose target", ACTION_RAID + 1), + NextAction::array(0, new NextAction("anub'rekhan position", ACTION_RAID + 1), nullptr))); @@ -76,14 +71,14 @@ void RaidNaxxStrategy::InitTriggers(std::vector &triggers) "razuvious nontank", NextAction::array(0, new NextAction("razuvious target", ACTION_RAID + 1), nullptr))); - // // four horseman - // triggers.push_back(new TriggerNode( - // "horseman attractors", - // NextAction::array(0, new NextAction("horseman attract alternatively", ACTION_RAID + 1), nullptr))); + // four horseman + triggers.push_back(new TriggerNode( + "horseman attractors", + NextAction::array(0, new NextAction("horseman attract alternatively", ACTION_RAID + 1), nullptr))); - // triggers.push_back(new TriggerNode( - // "horseman except attractors", - // NextAction::array(0, new NextAction("horseman attack in order", ACTION_RAID + 1), nullptr))); + triggers.push_back(new TriggerNode( + "horseman except attractors", + NextAction::array(0, new NextAction("horseman attack in order", ACTION_RAID + 1), nullptr))); // sapphiron triggers.push_back(new TriggerNode( @@ -126,7 +121,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 FourhorsemanGenericMultiplier(botAI)); // multipliers.push_back(new GothikGenericMultiplier(botAI)); multipliers.push_back(new GluthGenericMultiplier(botAI)); } diff --git a/src/strategy/raids/naxxramas/RaidNaxxTriggerContext.h b/src/strategy/raids/naxxramas/RaidNaxxTriggerContext.h index 4c8fe079..f6047bbc 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxTriggerContext.h +++ b/src/strategy/raids/naxxramas/RaidNaxxTriggerContext.h @@ -28,8 +28,8 @@ class RaidNaxxTriggerContext : public NamedObjectContext 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["horseman attractors"] = &RaidNaxxTriggerContext::horseman_attractors; + creators["horseman except attractors"] = &RaidNaxxTriggerContext::horseman_except_attractors; creators["sapphiron ground"] = &RaidNaxxTriggerContext::sapphiron_ground; creators["sapphiron flight"] = &RaidNaxxTriggerContext::sapphiron_flight; @@ -56,8 +56,8 @@ class RaidNaxxTriggerContext : public NamedObjectContext 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* horseman_attractors(PlayerbotAI* ai) { return new HorsemanAttractorsTrigger(ai); } + static Trigger* horseman_except_attractors(PlayerbotAI* ai) { return new HorsemanExceptAttractorsTrigger(ai); } static Trigger* sapphiron_ground(PlayerbotAI* ai) { return new SapphironGroundTrigger(ai); } static Trigger* sapphiron_flight(PlayerbotAI* ai) { return new SapphironFlightTrigger(ai); } static Trigger* kelthuzad(PlayerbotAI* ai) { return new KelthuzadTrigger(ai); } diff --git a/src/strategy/raids/naxxramas/RaidNaxxTriggers.cpp b/src/strategy/raids/naxxramas/RaidNaxxTriggers.cpp index 238e56c0..b2b5cb1d 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxTriggers.cpp +++ b/src/strategy/raids/naxxramas/RaidNaxxTriggers.cpp @@ -110,22 +110,21 @@ bool RazuviousNontankTrigger::IsActive() return helper.UpdateBossAI() && !(bot->getClass() == CLASS_PRIEST); } -// bool HorsemanAttractorsTrigger::IsActive() -// { -// Difficulty diff = bot->GetRaidDifficulty(); -// if (diff == RAID_DIFFICULTY_25MAN_NORMAL) { -// return BossPhaseTrigger::IsActive() && (botAI->IsRangedDpsAssistantOfIndex(bot, 0) || botAI->IsHealAssistantOfIndex(bot, 0) || -// botAI->IsHealAssistantOfIndex(bot, 1) || botAI->IsHealAssistantOfIndex(bot, 2)); -// } -// return BossPhaseTrigger::IsActive() && (botAI->IsRangedDpsAssistantOfIndex(bot, 0) || botAI->IsHealAssistantOfIndex(bot, 0)); -// } +bool HorsemanAttractorsTrigger::IsActive() +{ + if (!helper.UpdateBossAI()) { + return false; + } + return helper.IsAttracter(bot); +} -// bool HorsemanExceptAttractorsTrigger::IsActive() -// { -// return BossPhaseTrigger::IsActive() && -// !(botAI->IsRangedDpsAssistantOfIndex(bot, 0) || botAI->IsHealAssistantOfIndex(bot, 0) || -// botAI->IsHealAssistantOfIndex(bot, 1) || botAI->IsHealAssistantOfIndex(bot, 2)); -// } +bool HorsemanExceptAttractorsTrigger::IsActive() +{ + if (!helper.UpdateBossAI()) { + return false; + } + return !helper.IsAttracter(bot); +} bool SapphironGroundTrigger::IsActive() { diff --git a/src/strategy/raids/naxxramas/RaidNaxxTriggers.h b/src/strategy/raids/naxxramas/RaidNaxxTriggers.h index 1fc655bc..6e8ac4c8 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxTriggers.h +++ b/src/strategy/raids/naxxramas/RaidNaxxTriggers.h @@ -143,19 +143,23 @@ public: // ThaddiusPhaseThaddiusTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "thaddius", 1 << (4 - 1), "thaddius phase thaddius") {} // }; -// class HorsemanAttractorsTrigger : public BossPhaseTrigger -// { -// public: -// HorsemanAttractorsTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "sir zeliek", 0, "horseman attractors") {} -// virtual bool IsActive(); -// }; +class HorsemanAttractorsTrigger : public Trigger +{ + public: + HorsemanAttractorsTrigger(PlayerbotAI* ai) : Trigger(ai, "fourhorsemen"), helper(ai) {} + bool IsActive() override; + private: + FourhorsemanBossHelper helper; +}; -// class HorsemanExceptAttractorsTrigger : public BossPhaseTrigger -// { -// public: -// HorsemanExceptAttractorsTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "sir zeliek", 0, "horseman except attractors") {} -// virtual bool IsActive(); -// }; +class HorsemanExceptAttractorsTrigger : public Trigger +{ + public: + HorsemanExceptAttractorsTrigger(PlayerbotAI* ai) : Trigger(ai, "fourhorsemen"), helper(ai) {} + bool IsActive() override; + private: + FourhorsemanBossHelper helper; +}; class SapphironGroundTrigger : public Trigger { diff --git a/src/strategy/values/InvalidTargetValue.cpp b/src/strategy/values/InvalidTargetValue.cpp index cd2df0f5..fe2ab023 100644 --- a/src/strategy/values/InvalidTargetValue.cpp +++ b/src/strategy/values/InvalidTargetValue.cpp @@ -27,7 +27,7 @@ bool InvalidTargetValue::Calculate() target->isFeared() || target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsFriendlyTo(bot) || - !bot->IsWithinDistInMap(target, sPlayerbotAIConfig->sightDistance) || + // !bot->IsWithinDistInMap(target, sPlayerbotAIConfig->sightDistance) || !bot->IsWithinLOSInMap(target); }