diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index fd2b1d39..662fa866 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -1394,6 +1394,11 @@ bool PlayerbotAI::IsMainTank(Player* player) return false; } +bool PlayerbotAI::IsAssistTank(Player* player) +{ + return IsTank(player) && !IsMainTank(player); +} + namespace acore { class UnitByGuidInRangeCheck @@ -3892,4 +3897,17 @@ bool PlayerbotAI::IsInRealGuild() void PlayerbotAI::QueueChatResponse(uint8 msgtype, ObjectGuid guid1, ObjectGuid guid2, std::string message, std::string chanName, std::string name) { chatReplies.push(ChatQueuedReply(msgtype, guid1.GetCounter(), guid2.GetCounter(), message, chanName, name, time(nullptr) + urand(inCombat ? 10 : 5, inCombat ? 25 : 15))); +} + +bool PlayerbotAI::EqualLowercaseName(std::string s1, std::string s2) +{ + if (s1.length() != s2.length()) { + return false; + } + for (int i = 0; i < s1.length(); i++) { + if (tolower(s1[i]) != tolower(s2[i])) { + return false; + } + } + return true; } \ No newline at end of file diff --git a/src/PlayerbotAI.h b/src/PlayerbotAI.h index e86fab8a..4fa499d8 100644 --- a/src/PlayerbotAI.h +++ b/src/PlayerbotAI.h @@ -332,6 +332,7 @@ class PlayerbotAI : public PlayerbotAIBase bool IsHeal(Player* player); bool IsRanged(Player* player); bool IsMainTank(Player* player); + bool IsAssistTank(Player* player); Creature* GetCreature(ObjectGuid guid); Unit* GetUnit(ObjectGuid guid); Player* GetPlayer(ObjectGuid guid); @@ -433,10 +434,10 @@ class PlayerbotAI : public PlayerbotAIBase bool CanMove(); bool IsInRealGuild(); static std::vector dispel_whitelist; + bool EqualLowercaseName(std::string s1, std::string s2); private: void _fillGearScoreData(Player* player, Item* item, std::vector* gearScore, uint32& twoHandScore); bool IsTellAllowed(PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL); - protected: Player* bot; Player* master; diff --git a/src/strategy/actions/ActionContext.h b/src/strategy/actions/ActionContext.h index da824cab..9cdf0b66 100644 --- a/src/strategy/actions/ActionContext.h +++ b/src/strategy/actions/ActionContext.h @@ -250,8 +250,8 @@ class ActionContext : public NamedObjectContext // creators["kel'thuzad choose target"] = &ActionContext::kelthuzad_choose_target; // creators["kel'thuzad position"] = &ActionContext::kelthuzad_position; - // creators["anub'rekhan choose target"] = &ActionContext::anubrekhan_choose_target; - // creators["anub'rekhan position"] = &ActionContext::anubrekhan_position; + creators["anub'rekhan choose target"] = &ActionContext::anubrekhan_choose_target; + creators["anub'rekhan position"] = &ActionContext::anubrekhan_position; // creators["gluth choose target"] = &ActionContext::gluth_choose_target; // creators["gluth position"] = &ActionContext::gluth_position; @@ -441,8 +441,8 @@ class ActionContext : public NamedObjectContext // static Action* sapphiron_avoid_chill(PlayerbotAI* ai) { return new SapphironAvoidChillAction(ai); } // static Action* kelthuzad_choose_target(PlayerbotAI* ai) { return new KelthuzadChooseTargetAction(ai); } // static Action* kelthuzad_position(PlayerbotAI* ai) { return new KelthuzadPositionAction(ai); } - // static Action* anubrekhan_choose_target(PlayerbotAI* ai) { return new AnubrekhanChooseTargetAction(ai); } - // static Action* anubrekhan_position(PlayerbotAI* ai) { return new AnubrekhanPositionAction(ai); } + static Action* anubrekhan_choose_target(PlayerbotAI* ai) { return new AnubrekhanChooseTargetAction(ai); } + static Action* anubrekhan_position(PlayerbotAI* ai) { return new AnubrekhanPositionAction(ai); } // static Action* gluth_choose_target(PlayerbotAI* ai) { return new GluthChooseTargetAction(ai); } // static Action* gluth_position(PlayerbotAI* ai) { return new GluthPositionAction(ai); } // static Action* gluth_slowdown(PlayerbotAI* ai) { return new GluthSlowdownAction(ai); } diff --git a/src/strategy/actions/RaidNaxxAction.cpp b/src/strategy/actions/RaidNaxxAction.cpp index 7dc4def1..70289d23 100644 --- a/src/strategy/actions/RaidNaxxAction.cpp +++ b/src/strategy/actions/RaidNaxxAction.cpp @@ -5,6 +5,7 @@ #include "ScriptedCreature.h" #include "../../../../src/server/scripts/Northrend/Naxxramas/boss_heigan.h" #include "../../../../src/server/scripts/Northrend/Naxxramas/boss_grobbulus.h" +#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.h" using namespace std; @@ -852,92 +853,86 @@ bool HeiganDanceRangedAction::Execute(Event event) { // return false; // } -// bool AnubrekhanChooseTargetAction::Execute(Event event) -// { -// Unit* boss = AI_VALUE2(Unit*, "find target", "anub'rekhan"); -// if (!boss) { -// return false; -// } -// BossAI* boss_ai = dynamic_cast(boss->GetAI()); -// EventMap* eventMap = boss_botAI->GetEvents(); -// list attackers = context->GetValue >("attackers")->Get(); -// Unit* target = NULL; -// Unit *target_boss = NULL; -// vector target_guards; -// for (list::iterator i = attackers.begin(); i != attackers.end(); ++i) -// { -// Unit* unit = botAI->GetUnit(*i); -// if (!unit) -// continue; -// if (botAI->EqualLowercaseName(unit->GetName(), "crypt guard")) { -// target_guards.push_back(unit); -// // target_guard = unit; -// } -// if (botAI->EqualLowercaseName(unit->GetName(), "anub'rekhan")) { -// target_boss = unit; -// } -// } -// // vector targets; -// if (botAI->IsMainTank(bot)) { -// target = target_boss; -// } else { -// if (target_guards.size() == 0) { -// target = target_boss; -// } else { -// if (botAI->IsAssistTank(bot)) { -// for (Unit* t : target_guards) { -// if (target == NULL || (target->GetVictim() && target->GetVictim()->ToPlayer() && botAI->IsTank(target->GetVictim()->ToPlayer()))) { -// target = t; -// } -// } -// } else { -// for (Unit* t : target_guards) { -// if (target == NULL || target->GetHealthPct() > t->GetHealthPct()) { -// target = t; -// } -// } -// } -// } -// } -// if (context->GetValue("current target")->Get() == target) { -// return false; -// } -// // if (target) { -// // bot->Yell("Let\'s attack " + target->GetName(), LANG_UNIVERSAL); -// // } -// return Attack(target); -// } +bool AnubrekhanChooseTargetAction::Execute(Event event) +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "anub'rekhan"); + if (!boss) { + return false; + } + BossAI* boss_ai = dynamic_cast(boss->GetAI()); + GuidVector attackers = context->GetValue("attackers")->Get(); + Unit* target = NULL; + Unit *target_boss = NULL; + vector target_guards; + for (ObjectGuid const guid : attackers) + { + Unit* unit = botAI->GetUnit(guid); + if (!unit) + continue; + if (botAI->EqualLowercaseName(unit->GetName(), "crypt guard")) { + target_guards.push_back(unit); + } + if (botAI->EqualLowercaseName(unit->GetName(), "anub'rekhan")) { + target_boss = unit; + } + } + if (botAI->IsMainTank(bot)) { + target = target_boss; + } else { + if (target_guards.size() == 0) { + target = target_boss; + } else { + if (botAI->IsAssistTank(bot)) { + for (Unit* t : target_guards) { + if (target == NULL || (target->GetVictim() && target->GetVictim()->ToPlayer() && botAI->IsTank(target->GetVictim()->ToPlayer()))) { + target = t; + } + } + } else { + for (Unit* t : target_guards) { + if (target == NULL || target->GetHealthPct() > t->GetHealthPct()) { + target = t; + } + } + } + } + } + if (context->GetValue("current target")->Get() == target) { + return false; + } + return Attack(target); +} -// bool AnubrekhanPositionAction::Execute(Event event) -// { -// Unit* boss = AI_VALUE2(Unit*, "find target", "anub'rekhan"); -// if (!boss) { -// return false; -// } -// BossAI* b_ai = dynamic_cast(boss->GetAI()); -// if (!b_ai) { -// return false; -// } -// EventMap *eventMap = b_botAI->GetEvents(); -// uint8 phase_mask = eventMap->GetPhaseMask(); -// uint32 locust = eventMap->GetNextEventTime(2); -// uint32 timer = eventMap->GetTimer(); -// if (phase_mask == 2 || (locust && locust - timer <= 5000)) { -// if (botAI->IsMainTank(bot)) { -// uint32 nearest = FindNearestWaypoint(); -// uint32 next_point; -// if (phase_mask == 2) { -// next_point = (nearest + 1) % intervals; -// } else { -// next_point = nearest; -// } -// return MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, bot->GetPositionZ()); -// } else { -// return MoveInside(533, 3272.49f, -3476.27f, bot->GetPositionZ(), 3.0f); -// } -// } -// return false; -// } +bool AnubrekhanPositionAction::Execute(Event event) +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "anub'rekhan"); + if (!boss) { + return false; + } + boss_anubrekhan::boss_anubrekhanAI* boss_ai = dynamic_cast(boss->GetAI()); + if (!boss_ai) { + return false; + } + EventMap *eventMap = &boss_ai->events; + uint32 locust = eventMap->GetNextEventTime(2); + uint32 timer = eventMap->GetTimer(); + bool inPhase = botAI->HasAura("locust swarm", boss) || boss->GetCurrentSpell(CURRENT_GENERIC_SPELL); + if (inPhase || (locust && locust - timer <= 5000)) { + if (botAI->IsMainTank(bot)) { + uint32 nearest = FindNearestWaypoint(); + uint32 next_point; + if (inPhase) { + next_point = (nearest + 1) % intervals; + } else { + next_point = nearest; + } + return MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, bot->GetPositionZ()); + } else { + return MoveInside(533, 3272.49f, -3476.27f, bot->GetPositionZ(), 3.0f); + } + } + return false; +} // bool GluthChooseTargetAction::Execute(Event event) // { diff --git a/src/strategy/actions/RaidNaxxAction.h b/src/strategy/actions/RaidNaxxAction.h index 6f41a564..c466607c 100644 --- a/src/strategy/actions/RaidNaxxAction.h +++ b/src/strategy/actions/RaidNaxxAction.h @@ -267,19 +267,19 @@ protected: // virtual bool Execute(Event event); // }; -// class AnubrekhanChooseTargetAction : public AttackAction -// { -// public: -// AnubrekhanChooseTargetAction(PlayerbotAI* ai) : AttackAction(ai, "anub'rekhan choose target") {} -// virtual bool Execute(Event event); -// }; +class AnubrekhanChooseTargetAction : public AttackAction +{ +public: + AnubrekhanChooseTargetAction(PlayerbotAI* ai) : AttackAction(ai, "anub'rekhan choose target") {} + virtual bool Execute(Event event); +}; -// class AnubrekhanPositionAction : public RotateAroundTheCenterPointAction -// { -// public: -// AnubrekhanPositionAction(PlayerbotAI* ai) : RotateAroundTheCenterPointAction(ai, "anub'rekhan position", 3272.49f, -3476.27f, 45.0f, 16) {} -// virtual bool Execute(Event event); -// }; +class AnubrekhanPositionAction : public RotateAroundTheCenterPointAction +{ +public: + AnubrekhanPositionAction(PlayerbotAI* ai) : RotateAroundTheCenterPointAction(ai, "anub'rekhan position", 3272.49f, -3476.27f, 45.0f, 16) {} + virtual bool Execute(Event event); +}; // class GluthChooseTargetAction : public AttackAction // { diff --git a/src/strategy/generic/RaidStrategy.cpp b/src/strategy/generic/RaidStrategy.cpp index ff53b964..cda6417f 100644 --- a/src/strategy/generic/RaidStrategy.cpp +++ b/src/strategy/generic/RaidStrategy.cpp @@ -18,6 +18,7 @@ #include "WarriorActions.h" #include #include "../../../../src/server/scripts/Northrend/Naxxramas/boss_heigan.h" +#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.h" float HeiganDanceMultiplier::GetValue(Action* action) { @@ -206,27 +207,29 @@ float HeiganDanceMultiplier::GetValue(Action* action) // return 1.0f; // } -// float AnubrekhanGenericMultiplier::GetValue(Action* action) -// { -// Unit* boss = AI_VALUE2(Unit*, "find target", "anub'rekhan"); -// if (!boss) { -// return 1.0f; -// } -// if ((dynamic_cast(action) || -// dynamic_cast(action) || -// dynamic_cast(action))) { -// return 0.0f; -// } -// BossAI* boss_ai = dynamic_cast(boss->GetAI()); -// EventMap* eventMap = boss_botAI->GetEvents(); -// uint32 curr_phase = eventMap->GetPhaseMask(); -// if (curr_phase == 2) { -// if (dynamic_cast(action)) { -// return 0.0f; -// } -// } -// return 1.0f; -// } +float AnubrekhanGenericMultiplier::GetValue(Action* action) +{ + Unit* boss = AI_VALUE2(Unit*, "find target", "anub'rekhan"); + if (!boss) { + return 1.0f; + } + if ( + // (dynamic_cast(action) || + // dynamic_cast(action) || + // dynamic_cast(action) || + dynamic_cast(action)) { + return 0.0f; + } + // BossAI* boss_ai = dynamic_cast(boss->GetAI()); + // EventMap* eventMap = boss_ai->GetEvents(); + // uint32 curr_phase = eventMap->GetPhaseMask(); + if (botAI->HasAura("locust swarm", boss)) { + if (dynamic_cast(action)) { + return 0.0f; + } + } + return 1.0f; +} // float FourhorsemanGenericMultiplier::GetValue(Action* action) // { @@ -382,13 +385,13 @@ void RaidNaxxGenericStrategy::InitTriggers(std::vector &triggers) // new NextAction("kel'thuzad position", ACTION_RAID + 1), // NULL))); - // // Anub'Rekhan - // triggers.push_back(new TriggerNode( - // "anub'rekhan", - // NextAction::array(0, - // new NextAction("anub'rekhan choose target", ACTION_RAID + 1), - // new NextAction("anub'rekhan position", ACTION_RAID + 1), - // NULL))); + // Anub'Rekhan + triggers.push_back(new TriggerNode( + "anub'rekhan", + NextAction::array(0, + // new NextAction("anub'rekhan choose target", ACTION_RAID + 1), + new NextAction("anub'rekhan position", ACTION_RAID + 1), + NULL))); // // Gluth // triggers.push_back(new TriggerNode( @@ -420,7 +423,7 @@ void RaidNaxxGenericStrategy::InitMultipliers(std::vector &multipli // multipliers.push_back(new SapphironGenericMultiplier(ai)); // multipliers.push_back(new InstructorRazuviousGenericMultiplier(ai)); // multipliers.push_back(new KelthuzadGenericMultiplier(ai)); - // multipliers.push_back(new AnubrekhanGenericMultiplier(ai)); + multipliers.push_back(new AnubrekhanGenericMultiplier(botAI)); // multipliers.push_back(new FourhorsemanGenericMultiplier(ai)); // multipliers.push_back(new GothikGenericMultiplier(ai)); // multipliers.push_back(new GluthGenericMultiplier(ai)); diff --git a/src/strategy/generic/RaidStrategy.h b/src/strategy/generic/RaidStrategy.h index 3fff6459..1ae887aa 100644 --- a/src/strategy/generic/RaidStrategy.h +++ b/src/strategy/generic/RaidStrategy.h @@ -59,14 +59,14 @@ public: // virtual float GetValue(Action* action); // }; -// class AnubrekhanGenericMultiplier : public Multiplier -// { -// public: -// AnubrekhanGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "anubrekhan generic") {} +class AnubrekhanGenericMultiplier : public Multiplier +{ +public: + AnubrekhanGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "anubrekhan generic") {} -// public: -// virtual float GetValue(Action* action); -// }; +public: + virtual float GetValue(Action* action); +}; // class FourhorsemanGenericMultiplier : public Multiplier // { diff --git a/src/strategy/triggers/RaidNaxxTrigger.cpp b/src/strategy/triggers/RaidNaxxTrigger.cpp index 113ff528..0bc1899d 100644 --- a/src/strategy/triggers/RaidNaxxTrigger.cpp +++ b/src/strategy/triggers/RaidNaxxTrigger.cpp @@ -42,21 +42,22 @@ bool BossEventTrigger::IsActive() return false; } -// bool BossPhaseTrigger::IsActive() -// { -// Unit* boss = AI_VALUE2(Unit*, "find target", boss_name); -// if (!boss) { -// return false; -// } -// if (this->phase_mask == 0) { -// return true; -// } -// BossAI* boss_ai = dynamic_cast(boss->GetAI()); -// EventMap* eventMap = boss_botAI->GetEvents(); -// uint8 phase_mask = eventMap->GetPhaseMask(); -// // bot->Yell("phase mask detected: " + to_string(phase_mask) + " compare with " + to_string(this->phase_mask), LANG_UNIVERSAL); -// return phase_mask == this->phase_mask; -// } +template +bool BossPhaseTrigger::IsActive() +{ + Unit* boss = AI_VALUE2(Unit*, "find target", boss_name); + if (!boss) { + return false; + } + if (this->phase_mask == 0) { + return true; + } + T* boss_ai = dynamic_cast(boss->GetAI()); + EventMap* eventMap = &boss_ai->events; + uint8 phase_mask = eventMap->GetPhaseMask(); + // bot->Yell("phase mask detected: " + to_string(phase_mask) + " compare with " + to_string(this->phase_mask), LANG_UNIVERSAL); + return phase_mask == this->phase_mask; +} bool GrobbulusCloudTrigger::IsActive() { @@ -165,4 +166,5 @@ bool HeiganRangedTrigger::IsActive() // return true; // } -template bool BossEventTrigger::IsActive(); \ No newline at end of file +template bool BossEventTrigger::IsActive(); +template bool BossPhaseTrigger::IsActive(); \ No newline at end of file diff --git a/src/strategy/triggers/RaidNaxxTrigger.h b/src/strategy/triggers/RaidNaxxTrigger.h index 90984b3d..297b8eb8 100644 --- a/src/strategy/triggers/RaidNaxxTrigger.h +++ b/src/strategy/triggers/RaidNaxxTrigger.h @@ -7,6 +7,7 @@ #include "PlayerbotAIConfig.h" #include "GenericTriggers.h" #include "../../../../src/server/scripts/Northrend/Naxxramas/boss_grobbulus.h" +#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.h" using namespace std; @@ -48,6 +49,7 @@ protected: uint32 boss_entry, event_id, last_event_time; }; +template class BossPhaseTrigger : public Trigger { public: @@ -172,11 +174,11 @@ public: // KelthuzadTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "kel'thuzad", 0, "kel'thuzad trigger") {} // }; -// class AnubrekhanTrigger : public BossPhaseTrigger -// { -// public: -// AnubrekhanTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "anub'rekhan", 0, "anub'rekhan trigger") {} -// }; +class AnubrekhanTrigger : public BossPhaseTrigger +{ +public: + AnubrekhanTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "anub'rekhan", 0, "anub'rekhan trigger") {} +}; // class KelthuzadPhaseTwoTrigger : public BossPhaseTrigger // { diff --git a/src/strategy/triggers/TriggerContext.h b/src/strategy/triggers/TriggerContext.h index b6f6afc8..3b37a250 100644 --- a/src/strategy/triggers/TriggerContext.h +++ b/src/strategy/triggers/TriggerContext.h @@ -219,7 +219,7 @@ class TriggerContext : public NamedObjectContext // creators["kel'thuzad"] = &TriggerContext::kelthuzad; // creators["kel'thuzad phase two"] = &TriggerContext::kelthuzad_phase_two; - // creators["anub'rekhan"] = &TriggerContext::anubrekhan; + creators["anub'rekhan"] = &TriggerContext::anubrekhan; // creators["gluth"] = &TriggerContext::gluth; // creators["gluth main tank mortal wound"] = &TriggerContext::gluth_main_tank_mortal_wound; @@ -386,7 +386,7 @@ class TriggerContext : public NamedObjectContext // static Trigger* sapphiron_ground_chill(PlayerbotAI* ai) { return new SapphironGroundChillTrigger(ai); } // static Trigger* kelthuzad(PlayerbotAI* ai) { return new KelthuzadTrigger(ai); } // static Trigger* kelthuzad_phase_two(PlayerbotAI* ai) { return new KelthuzadPhaseTwoTrigger(ai); } - // static Trigger* anubrekhan(PlayerbotAI* ai) { return new AnubrekhanTrigger(ai); } + static Trigger* anubrekhan(PlayerbotAI* ai) { return new AnubrekhanTrigger(ai); } // static Trigger* gluth(PlayerbotAI* ai) { return new GluthTrigger(ai); } // static Trigger* gluth_main_tank_mortal_wound(PlayerbotAI* ai) { return new GluthMainTankMortalWoundTrigger(ai); } // static Trigger* loatheb(PlayerbotAI* ai) { return new LoathebTrigger(ai); }