From 9c1bb63d1094a940c48dfbdf0175246eeec1fdcf Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Tue, 18 Jul 2023 21:00:49 +0800 Subject: [PATCH] razuvious strategy --- src/PlayerbotAI.cpp | 12 +- src/strategy/actions/FollowActions.cpp | 8 +- src/strategy/actions/MovementActions.cpp | 8 + src/strategy/actions/MovementActions.h | 1 + src/strategy/generic/ThreatStrategy.cpp | 4 + src/strategy/paladin/TankPaladinStrategy.cpp | 10 +- .../raids/naxxramas/RaidNaxxActionContext.h | 8 +- .../raids/naxxramas/RaidNaxxActions.cpp | 236 +++++++++--------- .../raids/naxxramas/RaidNaxxActions.h | 28 ++- .../raids/naxxramas/RaidNaxxBossHelper.h | 33 +-- .../raids/naxxramas/RaidNaxxMultipliers.cpp | 46 ++-- .../raids/naxxramas/RaidNaxxMultipliers.h | 16 +- .../raids/naxxramas/RaidNaxxStrategy.cpp | 49 ++-- .../raids/naxxramas/RaidNaxxTriggerContext.h | 8 +- .../raids/naxxramas/RaidNaxxTriggers.cpp | 32 +-- .../raids/naxxramas/RaidNaxxTriggers.h | 64 ++--- src/strategy/shaman/GenericShamanStrategy.cpp | 4 +- src/strategy/shaman/HealShamanStrategy.cpp | 4 + src/strategy/triggers/GenericTriggers.h | 6 +- src/strategy/values/ThreatValues.h | 12 + src/strategy/values/ValueContext.h | 2 + 21 files changed, 326 insertions(+), 265 deletions(-) diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 19a77269..b42adbcb 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -248,9 +248,9 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal) // check activity AllowActivity(); - if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) { - return; - } + // if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) { + // return; + // } Spell* currentSpell = bot->GetCurrentSpell(CURRENT_GENERIC_SPELL); if (currentSpell && currentSpell->getState() == SPELL_STATE_CASTING && currentSpell->GetCastTime()) { @@ -2007,6 +2007,12 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, return false; } + if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr) { + LOG_DEBUG("playerbot", "CanCastSpell() target name: {}, spellid: {}, bot name: {}, failed because has current channeled spell", + target->GetName(), spellid, bot->GetName()); + return false; + } + if (bot->HasSpellCooldown(spellid)) { if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { LOG_DEBUG("playerbots", "Can cast spell failed. Spell not has cooldown. - target name: {}, spellid: {}, bot name: {}", diff --git a/src/strategy/actions/FollowActions.cpp b/src/strategy/actions/FollowActions.cpp index 0c36c62d..93a617f6 100644 --- a/src/strategy/actions/FollowActions.cpp +++ b/src/strategy/actions/FollowActions.cpp @@ -7,6 +7,7 @@ #include "Formations.h" #include "Playerbots.h" #include "ServerFacade.h" +#include bool FollowAction::Execute(Event event) { @@ -23,8 +24,8 @@ bool FollowAction::Execute(Event event) WorldLocation loc = formation->GetLocation(); if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1) return false; - - moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ()); + + moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ() + 2.0f); } if (Pet* pet = bot->GetPet()) @@ -47,6 +48,9 @@ bool FollowAction::Execute(Event event) bool FollowAction::isUseful() { + if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr) { + return false; + } Formation* formation = AI_VALUE(Formation*, "formation"); std::string const target = formation->GetTargetName(); diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 8c13a979..97ed460b 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1255,6 +1255,14 @@ bool FleeAction::Execute(Event event) return MoveAway(AI_VALUE(Unit*, "current target")); } +bool FleeAction::isUseful() +{ + if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr) { + return false; + } + return true; +} + bool FleeWithPetAction::Execute(Event event) { if (Pet* pet = bot->GetPet()) diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index 49cfc299..e6502666 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -48,6 +48,7 @@ class FleeAction : public MovementAction FleeAction(PlayerbotAI* botAI, float distance = sPlayerbotAIConfig->spellDistance) : MovementAction(botAI, "flee"), distance(distance) { } bool Execute(Event event) override; + bool isUseful() override; private: float distance; diff --git a/src/strategy/generic/ThreatStrategy.cpp b/src/strategy/generic/ThreatStrategy.cpp index 19531b3e..4b2d39ed 100644 --- a/src/strategy/generic/ThreatStrategy.cpp +++ b/src/strategy/generic/ThreatStrategy.cpp @@ -8,6 +8,10 @@ float ThreatMultiplier::GetValue(Action* action) { + if (AI_VALUE(bool, "neglect threat")) { + return 1.0f; + } + if (!action || action->getThreatType() == Action::ActionThreatType::None) return 1.0f; diff --git a/src/strategy/paladin/TankPaladinStrategy.cpp b/src/strategy/paladin/TankPaladinStrategy.cpp index 62797db4..c0e13064 100644 --- a/src/strategy/paladin/TankPaladinStrategy.cpp +++ b/src/strategy/paladin/TankPaladinStrategy.cpp @@ -53,15 +53,11 @@ void TankPaladinStrategy::InitTriggers(std::vector& triggers) "devotion aura", NextAction::array(0, new NextAction("devotion aura", 90.0f), NULL))); - // triggers.push_back(new TriggerNode("judgement of light", NextAction::array(0, new NextAction("judgement of light", ACTION_HIGH + 6), nullptr))); - // triggers.push_back(new TriggerNode("medium mana", NextAction::array(0, new NextAction("judgement of wisdom", ACTION_HIGH + 6), nullptr))); - // triggers.push_back(new TriggerNode("judgement", NextAction::array(0, new NextAction("judgement", ACTION_HIGH + 6), nullptr))); - // triggers.push_back(new TriggerNode("judgement", NextAction::array(0, new NextAction("exorcism", ACTION_HIGH + 6), nullptr))); - triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("hammer of the righteous", ACTION_HIGH + 8), new NextAction("avenger's shield", ACTION_HIGH + 7), nullptr))); - triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 1), new NextAction("avenger's shield", ACTION_HIGH + 3), NULL))); + triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("avenger's shield", ACTION_HIGH + 5), nullptr))); + triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 7), new NextAction("avenger's shield", ACTION_HIGH + 6), NULL))); // triggers.push_back(new TriggerNode("avenger's shield", NextAction::array(0, new NextAction("avenger's shield", ACTION_HIGH + 7), nullptr))); triggers.push_back(new TriggerNode("lose aggro", NextAction::array(0, new NextAction("hand of reckoning", ACTION_HIGH + 7), nullptr))); - triggers.push_back(new TriggerNode("holy shield", NextAction::array(0, new NextAction("holy shield", ACTION_HIGH + 7), nullptr))); + triggers.push_back(new TriggerNode("holy shield", NextAction::array(0, new NextAction("holy shield", ACTION_HIGH + 4), nullptr))); // triggers.push_back(new TriggerNode("blessing", NextAction::array(0, new NextAction("blessing of sanctuary", ACTION_HIGH + 9), nullptr))); triggers.push_back(new TriggerNode("target critical health", NextAction::array(0, new NextAction("hammer of wrath", ACTION_CRITICAL_HEAL), nullptr))); triggers.push_back(new TriggerNode( diff --git a/src/strategy/raids/naxxramas/RaidNaxxActionContext.h b/src/strategy/raids/naxxramas/RaidNaxxActionContext.h index f9841dae..816f797b 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxActionContext.h +++ b/src/strategy/raids/naxxramas/RaidNaxxActionContext.h @@ -25,8 +25,8 @@ class RaidNaxxActionContext : public NamedObjectContext // creators["thaddius move to platform"] = &RaidNaxxActionContext::thaddius_move_to_platform; // creators["thaddius move polarity"] = &RaidNaxxActionContext::thaddius_move_polarity; - // creators["razuvious use obedience crystal"] = &RaidNaxxActionContext::razuvious_use_obedience_crystal; - // creators["razuvious target"] = &RaidNaxxActionContext::razuvious_target; + 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; @@ -60,8 +60,8 @@ class RaidNaxxActionContext : public NamedObjectContext // static Action* thaddius_ranged_to_place(PlayerbotAI* ai) { return new ThaddiusRangedToPlaceAction(ai); } // static Action* thaddius_move_to_platform(PlayerbotAI* ai) { return new ThaddiusMoveToPlatformAction(ai); } // 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* 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* sapphiron_ground_main_tank_position(PlayerbotAI* ai) { return new SapphironGroundMainTankPositionAction(ai); } diff --git a/src/strategy/raids/naxxramas/RaidNaxxActions.cpp b/src/strategy/raids/naxxramas/RaidNaxxActions.cpp index b3d658cf..33548acf 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxActions.cpp +++ b/src/strategy/raids/naxxramas/RaidNaxxActions.cpp @@ -288,121 +288,129 @@ bool HeiganDanceRangedAction::Execute(Event event) { // return MoveTo(bot->GetMapId(), position[idx].first, position[idx].second, bot->GetPositionZ()); // } -// bool RazuviousUseObedienceCrystalAction::Execute(Event event) -// { - -// if (Unit* charm = bot->GetCharm()) { -// Unit* target = AI_VALUE2(Unit*, "find target", "instructor razuvious"); -// if (!target) { -// return false; -// } -// charm->GetMotionMaster()->MoveChase(target); -// charm->Attack(target, true); -// charm->SetFacingToObject(target); -// Aura* forceObedience = botAI->GetAura("force obedience", charm); -// uint32 duration_time; -// if (!forceObedience) { -// forceObedience = botAI->GetAura("mind control", charm); -// duration_time = 60000; -// } else { -// duration_time = 90000; -// } -// if (!forceObedience) { -// return false; -// } -// if (charm->GetDistance(target) <= 0.51f) { -// // taunt -// bool tauntUseful = true; -// if (forceObedience->GetDuration() <= (duration_time - 5000)) { -// if (target->GetVictim() && botAI->HasAura(29061, target->GetVictim())) { -// tauntUseful = false; -// } -// if (forceObedience->GetDuration() <= 3000) { -// tauntUseful = false; -// } -// } -// if (forceObedience->GetDuration() >= (duration_time - 500)) { -// tauntUseful = false; -// } -// if ( tauntUseful && !charm->GetSpellHistory()->HasCooldown(29060) ) { -// // shield -// if (!charm->GetSpellHistory()->HasCooldown(29061)) { -// charm->CastSpell(charm, 29061, true); -// charm->GetSpellHistory()->AddCooldown(29061, 0, Seconds(30)); -// } -// charm->CastSpell(target, 29060, true); -// charm->GetSpellHistory()->AddCooldown(29060, 0, Seconds(20)); -// } -// // strike -// if (!charm->GetSpellHistory()->HasCooldown(61696)) { -// charm->CastSpell(target, 61696, true); -// charm->GetSpellHistory()->AddCooldown(61696, 0, Seconds(4)); -// } -// } -// } else { -// Difficulty diff = bot->GetRaidDifficulty(); -// if (diff == RAID_DIFFICULTY_10MAN_NORMAL) { -// list npcs = AI_VALUE(list, "nearest npcs"); -// for (list::iterator i = npcs.begin(); i != npcs.end(); i++) -// { -// Creature* unit = botAI->GetCreature(*i); -// if (!unit) { -// continue; -// } -// if (botAI->IsMainTank(bot) && unit->GetSpawnId() != 128352) { -// continue; -// } -// if (!botAI->IsMainTank(bot) && unit->GetSpawnId() != 128353) { -// continue; -// } -// if (MoveTo(unit)) { -// return true; -// } -// Creature *creature = bot->GetNPCIfCanInteractWith(*i, UNIT_NPC_FLAG_SPELLCLICK); -// if (!creature) -// continue; -// creature->HandleSpellClick(bot); -// return true; -// } -// } else { -// list attackers = context->GetValue >("attackers")->Get(); -// Unit* target = nullptr; -// for (list::iterator i = attackers.begin(); i != attackers.end(); ++i) { -// Unit* unit = botAI->GetUnit(*i); -// if (!unit) -// continue; -// if (botAI->EqualLowercaseName(unit->GetName(), "death knight understudy")) { -// target = unit; -// break; -// } -// } -// if (target) { -// if (bot->GetDistance2d(target) > sPlayerbotAIConfig.spellDistance) { -// return MoveNear(target, sPlayerbotAIConfig.spellDistance); -// } else { -// return botAI->CastSpell("mind control", target); -// } -// } -// } -// } -// return false; -// } +bool RazuviousUseObedienceCrystalAction::Execute(Event event) +{ + if (!helper.UpdateBossAI()) { + return false; + } + // bot->GetCharm + if (Unit* charm = bot->GetCharm()) { + Unit* target = AI_VALUE2(Unit*, "find target", "instructor razuvious"); + if (!target) { + return false; + } + if (charm->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == NULL_MOTION_TYPE) { + charm->GetMotionMaster()->Clear(); + charm->GetMotionMaster()->MoveChase(target); + charm->GetAI()->AttackStart(target); + } + Aura* forceObedience = botAI->GetAura("force obedience", charm); + uint32 duration_time; + if (!forceObedience) { + forceObedience = botAI->GetAura("mind control", charm); + duration_time = 60000; + } else { + duration_time = 90000; + } + if (!forceObedience) { + return false; + } + if (charm->GetDistance(target) <= 0.51f) { + // taunt + bool tauntUseful = true; + if (forceObedience->GetDuration() <= (duration_time - 5000)) { + if (target->GetVictim() && botAI->HasAura(29061, target->GetVictim())) { + tauntUseful = false; + } + if (forceObedience->GetDuration() <= 3000) { + tauntUseful = false; + } + } + if (forceObedience->GetDuration() >= (duration_time - 500)) { + tauntUseful = false; + } + if ( tauntUseful && !charm->HasSpellCooldown(29060) ) { + // shield + if (!charm->HasSpellCooldown(29061)) { + charm->CastSpell(charm, 29061, true); + charm->AddSpellCooldown(29061, 0, 30 * 1000); + } + charm->CastSpell(target, 29060, true); + charm->AddSpellCooldown(29060, 0, 20 * 1000); + } + // strike + if (!charm->HasSpellCooldown(61696)) { + charm->CastSpell(target, 61696, true); + charm->AddSpellCooldown(61696, 0, 4 * 1000); + } + } + } else { + Difficulty diff = bot->GetRaidDifficulty(); + if (diff == RAID_DIFFICULTY_10MAN_NORMAL) { + GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs"); + for (auto i = npcs.begin(); i != npcs.end(); i++) + { + Creature* unit = botAI->GetCreature(*i); + if (!unit) { + continue; + } + if (botAI->IsMainTank(bot) && unit->GetSpawnId() != 128352) { + continue; + } + if (!botAI->IsMainTank(bot) && unit->GetSpawnId() != 128353) { + continue; + } + if (MoveTo(unit)) { + return true; + } + Creature *creature = bot->GetNPCIfCanInteractWith(*i, UNIT_NPC_FLAG_SPELLCLICK); + if (!creature) + continue; + creature->HandleSpellClick(bot); + return true; + } + } else { + GuidVector attackers = context->GetValue("attackers")->Get(); + Unit* target = nullptr; + for (auto i = attackers.begin(); i != attackers.end(); ++i) { + Unit* unit = botAI->GetUnit(*i); + if (!unit) + continue; + if (botAI->EqualLowercaseName(unit->GetName(), "death knight understudy")) { + target = unit; + break; + } + } + if (target) { + if (bot->GetDistance2d(target) > sPlayerbotAIConfig->spellDistance) { + return MoveNear(target, sPlayerbotAIConfig->spellDistance); + } else { + return botAI->CastSpell("mind control", target); + } + } + } + } + return false; +} -// bool RazuviousTargetAction::Execute(Event event) -// { -// Unit* razuvious = AI_VALUE2(Unit*, "find target", "instructor razuvious"); -// Unit* understudy = AI_VALUE2(Unit*, "find target", "death knight understudy"); -// Unit* target = nullptr; -// if (botAI->IsTank(bot)) { -// target = understudy; -// } else { -// target = razuvious; -// } -// if (AI_VALUE(Unit*, "current target") == target) { -// return false; -// } -// return Attack(target); -// } +bool RazuviousTargetAction::Execute(Event event) +{ + if (!helper.UpdateBossAI()) { + return false; + } + Unit* razuvious = AI_VALUE2(Unit*, "find target", "instructor razuvious"); + Unit* understudy = AI_VALUE2(Unit*, "find target", "death knight understudy"); + Unit* target = nullptr; + if (botAI->IsTank(bot)) { + target = understudy; + } else { + target = razuvious; + } + if (AI_VALUE(Unit*, "current target") == target) { + return false; + } + return Attack(target); +} // bool HorsemanAttractAlternativelyAction::Execute(Event event) // { diff --git a/src/strategy/raids/naxxramas/RaidNaxxActions.h b/src/strategy/raids/naxxramas/RaidNaxxActions.h index 00655254..83c0fa6a 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxActions.h +++ b/src/strategy/raids/naxxramas/RaidNaxxActions.h @@ -127,19 +127,23 @@ protected: // virtual bool isUseful(); // }; -// class RazuviousUseObedienceCrystalAction : public MovementAction -// { -// public: -// RazuviousUseObedienceCrystalAction(PlayerbotAI* ai) : MovementAction(ai, "razuvious use obedience crystal") {} -// virtual bool Execute(Event event); -// }; +class RazuviousUseObedienceCrystalAction : public MovementAction +{ + public: + RazuviousUseObedienceCrystalAction(PlayerbotAI* ai) : MovementAction(ai, "razuvious use obedience crystal"), helper(ai) {} + bool Execute(Event event) override; + private: + RazuviousBossHelper helper; +}; -// class RazuviousTargetAction : public AttackAction -// { -// public: -// RazuviousTargetAction(PlayerbotAI* ai) : AttackAction(ai, "razuvious target") {} -// virtual bool Execute(Event event); -// }; +class RazuviousTargetAction : public AttackAction +{ + public: + RazuviousTargetAction(PlayerbotAI* ai) : AttackAction(ai, "razuvious target"), helper(ai) {} + bool Execute(Event event) override; + private: + RazuviousBossHelper helper; +}; // class HorsemanAttractAlternativelyAction : public AttackAction // { diff --git a/src/strategy/raids/naxxramas/RaidNaxxBossHelper.h b/src/strategy/raids/naxxramas/RaidNaxxBossHelper.h index 6250c515..ed6f72bb 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxBossHelper.h +++ b/src/strategy/raids/naxxramas/RaidNaxxBossHelper.h @@ -18,22 +18,14 @@ const uint32 NAXX_MAP_ID = 533; template class GenericBossHelper : public AiObject { - -}; - -class KelthuzadBossHelper: public AiObject { public: - std::pair center = {3716.19f, -5106.58f}; - std::pair tank_pos = {3709.19f, -5104.86f}; - std::pair assist_tank_pos = {3746.05f, -5112.74f}; - KelthuzadBossHelper(PlayerbotAI *botAI): AiObject(botAI) {} - + GenericBossHelper(PlayerbotAI* botAI, std::string name): AiObject(botAI), name_(name) {} bool UpdateBossAI() { - Unit* target = AI_VALUE2(Unit*, "find target", "kel'thuzad"); + Unit* target = AI_VALUE2(Unit*, "find target", name_); if (!target) { return false; } - ai_ = dynamic_cast(target->GetAI()); + ai_ = dynamic_cast(target->GetAI()); if (!ai_) { return false; } @@ -43,6 +35,18 @@ class KelthuzadBossHelper: public AiObject { } return true; } + protected: + std::string name_; + BossAiType *ai_; + EventMap* event_map_; +}; + +class KelthuzadBossHelper: public GenericBossHelper { + public: + KelthuzadBossHelper(PlayerbotAI *botAI): GenericBossHelper(botAI, "kel'thuzad") {} + std::pair center = {3716.19f, -5106.58f}; + std::pair tank_pos = {3709.19f, -5104.86f}; + std::pair assist_tank_pos = {3746.05f, -5112.74f}; bool IsPhaseOne() { return event_map_->GetNextEventTime(KELTHUZAD_EVENT_PHASE_2) != 0; } @@ -63,10 +67,11 @@ class KelthuzadBossHelper: public AiObject { } return shadow_fissure; } - private: - boss_kelthuzad::boss_kelthuzadAI *ai_; - EventMap* event_map_; }; +class RazuviousBossHelper: public GenericBossHelper { + public: + RazuviousBossHelper(PlayerbotAI *botAI): GenericBossHelper(botAI, "instructor razuvious") {} +}; #endif \ No newline at end of file diff --git a/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp b/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp index 7db6acc1..8137760e 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp +++ b/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp @@ -16,6 +16,7 @@ #include "DruidActions.h" #include "PaladinActions.h" #include "WarriorActions.h" +#include "DruidBearActions.h" float HeiganDanceMultiplier::GetValue(Action* action) { @@ -63,7 +64,7 @@ float HeiganDanceMultiplier::GetValue(Action* action) // } // context->GetValue("neglect threat")->Set(true); // if (botAI->GetCurrentState() == BOT_STATE_COMBAT && -// (dynamic_cast(action) || +// (dynamic_cast(action) || // dynamic_cast(action) || // dynamic_cast(action) || // dynamic_cast(action))) { @@ -91,7 +92,7 @@ float HeiganDanceMultiplier::GetValue(Action* action) // uint32 curr_phase = eventMap->GetPhaseMask(); // // pet phase // if (curr_phase == 2 && -// ( dynamic_cast(action) || +// ( dynamic_cast(action) || // dynamic_cast(action) || // dynamic_cast(action) || // dynamic_cast(action) || @@ -148,24 +149,23 @@ float HeiganDanceMultiplier::GetValue(Action* action) // return 1.0f; // } -// float InstructorRazuviousGenericMultiplier::GetValue(Action* action) -// { -// Unit* boss = AI_VALUE2(Unit*, "find target", "instructor razuvious"); -// if (!boss) { -// return 1.0f; -// } -// context->GetValue("neglect threat")->Set(true); -// if (botAI->GetCurrentState() == BOT_STATE_COMBAT && -// (dynamic_cast(action) || -// dynamic_cast(action) || -// dynamic_cast(action) || -// dynamic_cast(action) || -// dynamic_cast(action) || -// dynamic_cast(action))) { -// return 0.0f; -// } -// return 1.0f; -// } +float InstructorRazuviousGenericMultiplier::GetValue(Action* action) +{ + if (!helper.UpdateBossAI()) { + return 1.0f; + } + context->GetValue("neglect threat")->Set(true); + if (botAI->GetState() == BOT_STATE_COMBAT && + (dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action) || + dynamic_cast(action))) { + return 0.0f; + } + return 1.0f; +} float KelthuzadGenericMultiplier::GetValue(Action* action) { @@ -205,7 +205,7 @@ float AnubrekhanGenericMultiplier::GetValue(Action* action) return 1.0f; } if ( - // (dynamic_cast(action) || + // (dynamic_cast(action) || // dynamic_cast(action) || // dynamic_cast(action) || dynamic_cast(action)) { @@ -228,7 +228,7 @@ float AnubrekhanGenericMultiplier::GetValue(Action* action) // if (!boss) { // return 1.0f; // } -// if ((dynamic_cast(action) || +// if ((dynamic_cast(action) || // dynamic_cast(action))) { // return 0.0f; // } @@ -262,7 +262,7 @@ float AnubrekhanGenericMultiplier::GetValue(Action* action) // if (!boss) { // return 1.0f; // } -// if ((dynamic_cast(action) || +// if ((dynamic_cast(action) || // dynamic_cast(action) || // dynamic_cast(action) || // dynamic_cast(action) || diff --git a/src/strategy/raids/naxxramas/RaidNaxxMultipliers.h b/src/strategy/raids/naxxramas/RaidNaxxMultipliers.h index 1673a0a0..88c9e2bd 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxMultipliers.h +++ b/src/strategy/raids/naxxramas/RaidNaxxMultipliers.h @@ -41,14 +41,14 @@ public: // virtual float GetValue(Action* action); // }; -// class InstructorRazuviousGenericMultiplier : public Multiplier -// { -// public: -// InstructorRazuviousGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "instructor razuvious generic") {} - -// public: -// virtual float GetValue(Action* action); -// }; +class InstructorRazuviousGenericMultiplier : public Multiplier +{ + public: + InstructorRazuviousGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "instructor razuvious generic"), helper(ai) {} + virtual float GetValue(Action* action); + private: + RazuviousBossHelper helper; +}; class KelthuzadGenericMultiplier : public Multiplier { diff --git a/src/strategy/raids/naxxramas/RaidNaxxStrategy.cpp b/src/strategy/raids/naxxramas/RaidNaxxStrategy.cpp index 5080fcf5..39c02ec2 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxStrategy.cpp +++ b/src/strategy/raids/naxxramas/RaidNaxxStrategy.cpp @@ -30,6 +30,22 @@ void RaidNaxxStrategy::InitTriggers(std::vector &triggers) "heigan ranged", NextAction::array(0, new NextAction("heigan dance ranged", ACTION_RAID + 1), NULL))); + // Kel'Thuzad + triggers.push_back(new TriggerNode( + "kel'thuzad", + NextAction::array(0, + new NextAction("kel'thuzad choose target", ACTION_RAID + 1), + 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))); + // Thaddius // triggers.push_back(new TriggerNode( // "thaddius phase pet", @@ -51,14 +67,14 @@ void RaidNaxxStrategy::InitTriggers(std::vector &triggers) // "thaddius phase thaddius", // NextAction::array(0, new NextAction("thaddius move polarity", ACTION_RAID + 1), NULL))); - // // Instructor Razuvious - // triggers.push_back(new TriggerNode( - // "razuvious tank", - // NextAction::array(0, new NextAction("razuvious use obedience crystal", ACTION_RAID + 1), NULL))); + // Instructor Razuvious + triggers.push_back(new TriggerNode( + "razuvious tank", + NextAction::array(0, new NextAction("razuvious use obedience crystal", ACTION_RAID + 1), NULL))); - // triggers.push_back(new TriggerNode( - // "razuvious nontank", - // NextAction::array(0, new NextAction("razuvious target", ACTION_RAID + 1), NULL))); + triggers.push_back(new TriggerNode( + "razuvious nontank", + NextAction::array(0, new NextAction("razuvious target", ACTION_RAID + 1), NULL))); // // four horseman // triggers.push_back(new TriggerNode( @@ -86,21 +102,7 @@ void RaidNaxxStrategy::InitTriggers(std::vector &triggers) // "sapphiron chill", // NextAction::array(0, new NextAction("sapphiron avoid chill", ACTION_RAID + 1), NULL))); - // Kel'Thuzad - triggers.push_back(new TriggerNode( - "kel'thuzad", - NextAction::array(0, - new NextAction("kel'thuzad choose target", ACTION_RAID + 1), - 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))); + // // Gluth // triggers.push_back(new TriggerNode( @@ -115,6 +117,7 @@ void RaidNaxxStrategy::InitTriggers(std::vector &triggers) // "gluth main tank mortal wound", // NextAction::array(0, // new NextAction("taunt spell", ACTION_RAID + 1), NULL))); + // // Loatheb // triggers.push_back(new TriggerNode( // "loatheb", @@ -130,7 +133,7 @@ void RaidNaxxStrategy::InitMultipliers(std::vector &multipliers) // multipliers.push_back(new LoathebGenericMultiplier(ai)); // multipliers.push_back(new ThaddiusGenericMultiplier(ai)); // multipliers.push_back(new SapphironGenericMultiplier(ai)); - // multipliers.push_back(new InstructorRazuviousGenericMultiplier(ai)); + multipliers.push_back(new InstructorRazuviousGenericMultiplier(botAI)); multipliers.push_back(new KelthuzadGenericMultiplier(botAI)); multipliers.push_back(new AnubrekhanGenericMultiplier(botAI)); // multipliers.push_back(new FourhorsemanGenericMultiplier(ai)); diff --git a/src/strategy/raids/naxxramas/RaidNaxxTriggerContext.h b/src/strategy/raids/naxxramas/RaidNaxxTriggerContext.h index 5682912e..524b8bc3 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxTriggerContext.h +++ b/src/strategy/raids/naxxramas/RaidNaxxTriggerContext.h @@ -25,8 +25,8 @@ class RaidNaxxTriggerContext : public NamedObjectContext // creators["thaddius phase transition"] = &RaidNaxxTriggerContext::thaddius_phase_transition; // creators["thaddius phase thaddius"] = &RaidNaxxTriggerContext::thaddius_phase_thaddius; - // creators["razuvious tank"] = &RaidNaxxTriggerContext::razuvious_tank; - // creators["razuvious nontank"] = &RaidNaxxTriggerContext::razuvious_nontank; + 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; @@ -56,8 +56,8 @@ class RaidNaxxTriggerContext : public NamedObjectContext // static Trigger* thaddius_phase_pet_lose_aggro(PlayerbotAI* ai) { return new ThaddiusPhasePetLoseAggroTrigger(ai); } // static Trigger* thaddius_phase_transition(PlayerbotAI* ai) { return new ThaddiusPhaseTransitionTrigger(ai); } // static Trigger* thaddius_phase_thaddius(PlayerbotAI* ai) { return new ThaddiusPhaseThaddiusTrigger(ai); } - // static Trigger* razuvious_tank(PlayerbotAI* ai) { return new RazuviousTankTrigger(ai); } - // static Trigger* razuvious_nontank(PlayerbotAI* ai) { return new RazuviousNontankTrigger(ai); } + 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); } diff --git a/src/strategy/raids/naxxramas/RaidNaxxTriggers.cpp b/src/strategy/raids/naxxramas/RaidNaxxTriggers.cpp index 1d2c7cd9..3a95bf4c 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxTriggers.cpp +++ b/src/strategy/raids/naxxramas/RaidNaxxTriggers.cpp @@ -91,23 +91,23 @@ bool HeiganRangedTrigger::IsActive() return botAI->IsRanged(bot); } -// bool RazuviousTankTrigger::IsActive() -// { -// Difficulty diff = bot->GetRaidDifficulty(); -// if (diff == RAID_DIFFICULTY_10MAN_NORMAL) { -// return BossPhaseTrigger::IsActive() && botAI->IsTank(bot); -// } -// return BossPhaseTrigger::IsActive() && bot->getClass() == CLASS_PRIEST; -// } +bool RazuviousTankTrigger::IsActive() +{ + Difficulty diff = bot->GetRaidDifficulty(); + if (diff == RAID_DIFFICULTY_10MAN_NORMAL) { + return helper.UpdateBossAI() && botAI->IsTank(bot); + } + return helper.UpdateBossAI() && bot->getClass() == CLASS_PRIEST; +} -// bool RazuviousNontankTrigger::IsActive() -// { -// Difficulty diff = bot->GetRaidDifficulty(); -// if (diff == RAID_DIFFICULTY_10MAN_NORMAL) { -// return BossPhaseTrigger::IsActive() && !(botAI->IsTank(bot)); -// } -// return BossPhaseTrigger::IsActive() && !(bot->getClass() == CLASS_PRIEST); -// } +bool RazuviousNontankTrigger::IsActive() +{ + Difficulty diff = bot->GetRaidDifficulty(); + if (diff == RAID_DIFFICULTY_10MAN_NORMAL) { + return helper.UpdateBossAI() && !(botAI->IsTank(bot)); + } + return helper.UpdateBossAI() && !(bot->getClass() == CLASS_PRIEST); +} // bool HorsemanAttractorsTrigger::IsActive() // { diff --git a/src/strategy/raids/naxxramas/RaidNaxxTriggers.h b/src/strategy/raids/naxxramas/RaidNaxxTriggers.h index b4c6653e..3f538191 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxTriggers.h +++ b/src/strategy/raids/naxxramas/RaidNaxxTriggers.h @@ -78,10 +78,43 @@ public: }; class HeiganRangedTrigger : public Trigger +{ + public: + HeiganRangedTrigger(PlayerbotAI* ai): Trigger(ai, "heigan ranged") {} + bool IsActive() override; +}; + +class RazuviousTankTrigger : public Trigger +{ + public: + RazuviousTankTrigger(PlayerbotAI* ai) : Trigger(ai, "instructor razuvious tank"), helper(ai) {} + bool IsActive() override; + private: + RazuviousBossHelper helper; +}; + +class RazuviousNontankTrigger : public Trigger +{ + public: + RazuviousNontankTrigger(PlayerbotAI* ai) : Trigger(ai, "instructor razuvious non-tank"), helper(ai) {} + bool IsActive() override; + private: + RazuviousBossHelper helper; +}; + +class KelthuzadTrigger : public Trigger +{ + public: + KelthuzadTrigger(PlayerbotAI* ai) : Trigger(ai, "kel'thuzad trigger"), helper(ai) {} + bool IsActive() override; + private: + KelthuzadBossHelper helper; +}; + +class AnubrekhanTrigger : public BossPhaseTrigger { public: - HeiganRangedTrigger(PlayerbotAI* ai): Trigger(ai, "heigan ranged") {} - virtual bool IsActive(); + AnubrekhanTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "anub'rekhan", 0, "anub'rekhan trigger") {} }; // class ThaddiusPhasePetTrigger : public BossPhaseTrigger @@ -112,20 +145,6 @@ public: // ThaddiusPhaseThaddiusTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "thaddius", 1 << (4 - 1), "thaddius phase thaddius") {} // }; -// class RazuviousTankTrigger : public BossPhaseTrigger -// { -// public: -// RazuviousTankTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "instructor razuvious", 0, "razuvious tank") {} -// virtual bool IsActive(); -// }; - -// class RazuviousNontankTrigger : public BossPhaseTrigger -// { -// public: -// RazuviousNontankTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "instructor razuvious", 0, "razuvious nontank") {} -// virtual bool IsActive(); -// }; - // class HorsemanAttractorsTrigger : public BossPhaseTrigger // { // public: @@ -168,20 +187,7 @@ public: // virtual bool IsActive(); // }; -class KelthuzadTrigger : public Trigger -{ - public: - KelthuzadTrigger(PlayerbotAI* ai) : Trigger(ai, "kel'thuzad trigger"), helper(ai) {} - bool IsActive() override; - private: - KelthuzadBossHelper helper; -}; -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/shaman/GenericShamanStrategy.cpp b/src/strategy/shaman/GenericShamanStrategy.cpp index 582c164e..e05c9754 100644 --- a/src/strategy/shaman/GenericShamanStrategy.cpp +++ b/src/strategy/shaman/GenericShamanStrategy.cpp @@ -124,9 +124,7 @@ void GenericShamanStrategy::InitTriggers(std::vector& triggers) // triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("riptide", 26.0f), nullptr))); triggers.push_back(new TriggerNode("heroism", NextAction::array(0, new NextAction("heroism", 31.0f), nullptr))); triggers.push_back(new TriggerNode("bloodlust", NextAction::array(0, new NextAction("bloodlust", 30.0f), nullptr))); - triggers.push_back(new TriggerNode( - "medium mana", - NextAction::array(0, new NextAction("mana tide totem", ACTION_EMERGENCY + 5), NULL))); + } void ShamanBuffDpsStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/shaman/HealShamanStrategy.cpp b/src/strategy/shaman/HealShamanStrategy.cpp index 3df7ff3b..d9103f42 100644 --- a/src/strategy/shaman/HealShamanStrategy.cpp +++ b/src/strategy/shaman/HealShamanStrategy.cpp @@ -97,5 +97,9 @@ void HealShamanStrategy::InitTriggers(std::vector& triggers) "enemy too close for spell", NextAction::array(0, new NextAction("flee", 49.0f), NULL))); + triggers.push_back(new TriggerNode( + "medium mana", + NextAction::array(0, new NextAction("mana tide totem", ACTION_HIGH + 5), NULL))); + triggers.push_back(new TriggerNode("party member to heal out of spell range", NextAction::array(0, new NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 1), nullptr))); } diff --git a/src/strategy/triggers/GenericTriggers.h b/src/strategy/triggers/GenericTriggers.h index e243ca03..83b2f294 100644 --- a/src/strategy/triggers/GenericTriggers.h +++ b/src/strategy/triggers/GenericTriggers.h @@ -225,19 +225,19 @@ class NoDrinkTrigger : public Trigger class LightAoeTrigger : public AoeTrigger { public: - LightAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 2, 8.0f) { } + LightAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 2, 10.0f) { } }; class MediumAoeTrigger : public AoeTrigger { public: - MediumAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 3, 8.0f) { } + MediumAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 3, 10.0f) { } }; class HighAoeTrigger : public AoeTrigger { public: - HighAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 4, 8.0f) { } + HighAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 4, 10.0f) { } }; class BuffTrigger : public SpellTrigger diff --git a/src/strategy/values/ThreatValues.h b/src/strategy/values/ThreatValues.h index 0c32903a..a7186318 100644 --- a/src/strategy/values/ThreatValues.h +++ b/src/strategy/values/ThreatValues.h @@ -22,4 +22,16 @@ class ThreatValue : public Uint8CalculatedValue, public Qualified uint8 Calculate(Unit* target); }; +class NeglectThreatResetValue : public ManualSetValue +{ + public: + NeglectThreatResetValue(PlayerbotAI* ai, bool defaultValue = false, std::string name = "neglect threat") : + ManualSetValue(ai, defaultValue, name) {} + virtual bool Get() { + bool ret = value; + Reset(); + return ret; + } +}; + #endif diff --git a/src/strategy/values/ValueContext.h b/src/strategy/values/ValueContext.h index 54ded1ac..c8db899a 100644 --- a/src/strategy/values/ValueContext.h +++ b/src/strategy/values/ValueContext.h @@ -291,6 +291,7 @@ class ValueContext : public NamedObjectContext creators["find target"] = &ValueContext::find_target; creators["boss target"] = &ValueContext::boss_target; creators["nearest triggers"] = &ValueContext::nearest_triggers; + creators["neglect threat"] = &ValueContext::neglect_threat; } private: @@ -486,6 +487,7 @@ class ValueContext : public NamedObjectContext static UntypedValue* find_target(PlayerbotAI* ai) { return new FindTargetValue(ai); } static UntypedValue* boss_target(PlayerbotAI* ai) { return new BossTargetValue(ai); } static UntypedValue* nearest_triggers(PlayerbotAI* ai) { return new NearestTriggersValue(ai); } + static UntypedValue* neglect_threat(PlayerbotAI* ai) { return new NeglectThreatResetValue(ai); } }; #endif