diff --git a/src/Ai/Base/Actions/CheckMountStateAction.cpp b/src/Ai/Base/Actions/CheckMountStateAction.cpp index 0e3abb724..5da250790 100644 --- a/src/Ai/Base/Actions/CheckMountStateAction.cpp +++ b/src/Ai/Base/Actions/CheckMountStateAction.cpp @@ -17,6 +17,7 @@ #include "SpellAuraEffects.h" static constexpr uint32 SPELL_COLD_WEATHER_FLYING = 54197; +static constexpr float PARACHUTE_LAND_THRESHOLD = 15.0f; // Define the static map / init bool for caching bot preferred mount data globally std::unordered_map CheckMountStateAction::mountCache; @@ -61,6 +62,21 @@ MountData CollectMountData(const Player* bot) bool CheckMountStateAction::Execute(Event /*event*/) { + // Forced flight dismount: + // Bots get stale flight movement flags after a forced dismount (e.g: Dalaran) because the post landing dismount cleanup + // needs MSG_MOVE_FALL_LAND (a client opcode) and client movement packets. The stale flags cause the bot to be stuck with + // the parachute, or even keep the bot hovering indefinitely and block MMAP routing. + // Note: Without MSG_MOVE_FALL_LAND, HandleFall doesn't trigger, meaning bots don't get fall damage in forced dismounts anyway, + // so the parachute usage here is more of an immersion feature. + if (bot->HasFeatherFallAura()) + { + float floorZ = bot->GetMapHeight(bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ()); + if (floorZ != INVALID_HEIGHT && floorZ != VMAP_INVALID_HEIGHT_VALUE && + bot->GetPositionZ() - floorZ <= PARACHUTE_LAND_THRESHOLD) + bot->RemoveAurasByType(SPELL_AURA_FEATHER_FALL); + } + ClearStaleFlightFlags(); + // Determine if there are no attackers bool noAttackers = !AI_VALUE2(bool, "combat", "self target") || !AI_VALUE(uint8, "attacker count"); bool enemy = AI_VALUE(Unit*, "enemy player target"); @@ -204,7 +220,7 @@ bool CheckMountStateAction::Mount() // Get bot mount data MountData mountData = CollectMountData(bot); int32 masterMountType = GetMountType(master); - int32 masterSpeed = CalculateMasterMountSpeed(master, mountData); + int32 masterSpeed = CalculateMasterMountSpeed(master); // Try shapeshift if (TryForms(master, masterMountType, masterSpeed)) @@ -234,14 +250,17 @@ void CheckMountStateAction::Dismount() WorldPacket emptyPacket; bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket); - bool const wantsFly = bot->HasIncreaseMountedFlightSpeedAura() || bot->HasFlyAura(); - bool const isWaterWalking = bot->HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); - bool const isFlying = bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING); - bool const hasGravityDisabled = bot->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); - if (!wantsFly && !isWaterWalking && (isFlying || hasGravityDisabled)) + ClearStaleFlightFlags(); +} + +void CheckMountStateAction::ClearStaleFlightFlags() +{ + if (bot->HasIncreaseMountedFlightSpeedAura() || bot->HasFlyAura()) + return; + + if (bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY)) { - bot->RemoveUnitMovementFlag( - MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY); + bot->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_CAN_FLY); if (!bot->IsRooted()) bot->SendMovementFlagUpdate(); } @@ -490,7 +509,7 @@ static bool BotCanUseFlyingMount(Player const* bot) return true; } -int32 CheckMountStateAction::CalculateMasterMountSpeed(Player* master, const MountData& mountData) const +int32 CheckMountStateAction::CalculateMasterMountSpeed(Player* master) const { // Check riding skill and level requirements int32 ridingSkill = bot->GetPureSkillValue(SKILL_RIDING); diff --git a/src/Ai/Base/Actions/CheckMountStateAction.h b/src/Ai/Base/Actions/CheckMountStateAction.h index d1faa3798..0bf83cc5e 100644 --- a/src/Ai/Base/Actions/CheckMountStateAction.h +++ b/src/Ai/Base/Actions/CheckMountStateAction.h @@ -53,9 +53,10 @@ private: float CalculateDismountDistance() const; float CalculateMountDistance() const; void Dismount(); + void ClearStaleFlightFlags(); bool ShouldFollowMasterMountState(Player* master, bool noAttackers, bool shouldMount) const; bool ShouldDismountForMaster(Player* master) const; - int32 CalculateMasterMountSpeed(Player* master, const MountData& mountData) const; + int32 CalculateMasterMountSpeed(Player* master) const; bool CheckForSwiftMount() const; std::map>> GetAllMountSpells() const; bool TryForms(Player* master, int32 masterMountType, int32 masterSpeed) const; diff --git a/src/Ai/Base/Actions/TameAction.cpp b/src/Ai/Base/Actions/TameAction.cpp index dfeb61a47..57ae24e8c 100644 --- a/src/Ai/Base/Actions/TameAction.cpp +++ b/src/Ai/Base/Actions/TameAction.cpp @@ -422,10 +422,9 @@ bool TameAction::RenamePet(const std::string& newName) // Remove the current pet and (re-)cast Call Pet spell if the bot is a hunter bot->RemovePet(nullptr, PET_SAVE_AS_CURRENT, true); - if (bot->getClass() == CLASS_HUNTER && bot->HasSpell(883)) - { - bot->CastSpell(bot, 883, true); - } + constexpr uint32 SPELL_CALL_PET = 883; + if (bot->getClass() == CLASS_HUNTER && bot->HasSpell(SPELL_CALL_PET)) + bot->CastSpell(bot, SPELL_CALL_PET, true); return true; } diff --git a/src/Ai/Base/Actions/TradeStatusExtendedAction.cpp b/src/Ai/Base/Actions/TradeStatusExtendedAction.cpp index ada779e36..f081c3365 100644 --- a/src/Ai/Base/Actions/TradeStatusExtendedAction.cpp +++ b/src/Ai/Base/Actions/TradeStatusExtendedAction.cpp @@ -67,9 +67,10 @@ bool TradeStatusExtendedAction::Execute(Event event) return false; } - if (bot->getClass() == CLASS_ROGUE && bot->HasSpell(1804) && lockbox->IsLocked()) // Pick Lock spell + constexpr uint32 SPELL_PICK_LOCK = 1804; + if (bot->getClass() == CLASS_ROGUE && bot->HasSpell(SPELL_PICK_LOCK) && lockbox->IsLocked()) { - // botAI->CastSpell(1804, bot, lockbox); // Attempt to cast Pick Lock on the lockbox + // botAI->CastSpell(SPELL_PICK_LOCK, bot, lockbox); // Attempt to cast Pick Lock on the lockbox botAI->DoSpecificAction("unlock traded item"); botAI->SetNextCheckDelay(4000); // Delay before accepting trade } diff --git a/src/Ai/Base/Trigger/BossAuraTriggers.cpp b/src/Ai/Base/Trigger/BossAuraTriggers.cpp index 8d2520cf6..4c8dd5b33 100644 --- a/src/Ai/Base/Trigger/BossAuraTriggers.cpp +++ b/src/Ai/Base/Trigger/BossAuraTriggers.cpp @@ -23,9 +23,7 @@ bool BossFireResistanceTrigger::IsActive() return false; // Check if bot have fire resistance aura - if (bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_5) || bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_4) || - bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_3) || bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_2) || - bot->HasAura(SPELL_FIRE_RESISTANCE_AURA_RANK_1)) + if (botAI->HasAura("fire resistance aura", bot)) return false; // Check if bot dont have already have fire resistance strategy @@ -76,9 +74,7 @@ bool BossFrostResistanceTrigger::IsActive() return false; // Check if bot have frost resistance aura - if (bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_5) || bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_4) || - bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_3) || bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_2) || - bot->HasAura(SPELL_FROST_RESISTANCE_AURA_RANK_1)) + if (botAI->HasAura("frost resistance aura", bot)) return false; // Check if bot dont have already have frost resistance strategy @@ -133,8 +129,7 @@ bool BossNatureResistanceTrigger::IsActive() return false; // Check if bot have nature resistance aura - if (bot->HasAura(SPELL_ASPECT_OF_THE_WILD_RANK_4) || bot->HasAura(SPELL_ASPECT_OF_THE_WILD_RANK_3) || - bot->HasAura(SPELL_ASPECT_OF_THE_WILD_RANK_2) || bot->HasAura(SPELL_ASPECT_OF_THE_WILD_RANK_1)) + if (botAI->HasAura("aspect of the wild", bot)) return false; // Check if bot dont have already setted nature resistance aura @@ -184,11 +179,7 @@ bool BossShadowResistanceTrigger::IsActive() return false; // Check if bot have shadow resistance aura - if (bot->HasAura(SPELL_SHADOW_RESISTANCE_AURA_RANK_5) || - bot->HasAura(SPELL_SHADOW_RESISTANCE_AURA_RANK_4) || - bot->HasAura(SPELL_SHADOW_RESISTANCE_AURA_RANK_3) || - bot->HasAura(SPELL_SHADOW_RESISTANCE_AURA_RANK_2) || - bot->HasAura(SPELL_SHADOW_RESISTANCE_AURA_RANK_1)) + if (botAI->HasAura("shadow resistance aura", bot)) return false; // Check if bot dont have already have shadow resistance strategy diff --git a/src/Ai/Class/Dk/Strategy/DeathKnightPullStrategy.cpp b/src/Ai/Class/Dk/Strategy/DeathKnightPullStrategy.cpp index be643b50c..db58d3135 100644 --- a/src/Ai/Class/Dk/Strategy/DeathKnightPullStrategy.cpp +++ b/src/Ai/Class/Dk/Strategy/DeathKnightPullStrategy.cpp @@ -5,38 +5,26 @@ #include "DeathKnightPullStrategy.h" -#include "AiObjectContext.h" #include "Player.h" #include "PlayerbotAI.h" #include "Playerbots.h" std::string DeathKnightPullStrategy::GetPullActionName() const { - Player* bot = botAI->GetBot(); Unit* target = GetTarget(); - if (!bot || !target || + if (!target || (!botAI->HasStrategy("blood", BOT_STATE_COMBAT) && !botAI->HasStrategy("blood", BOT_STATE_NON_COMBAT))) { return PullStrategy::GetPullActionName(); } - uint32 const deathGripSpellId = botAI->GetAiObjectContext()->GetValue("spell id", "death grip")->Get(); - if (deathGripSpellId && bot->HasSpell(deathGripSpellId) && - botAI->CanCastSpell(deathGripSpellId, target)) - { + if (botAI->CanCastSpell("death grip", target)) return "death grip"; - } - uint32 const icyTouchSpellId = botAI->GetAiObjectContext()->GetValue("spell id", "icy touch")->Get(); - if (!icyTouchSpellId || !bot->HasSpell(icyTouchSpellId) || - !botAI->CanCastSpell(icyTouchSpellId, target)) + if (!botAI->CanCastSpell("icy touch", target) && + botAI->CanCastSpell("dark command", target)) { - uint32 const darkCommandSpellId = botAI->GetAiObjectContext()->GetValue("spell id", "dark command")->Get(); - if (darkCommandSpellId && bot->HasSpell(darkCommandSpellId) && - botAI->CanCastSpell(darkCommandSpellId, target)) - { - return "dark command"; - } + return "dark command"; } return PullStrategy::GetPullActionName(); diff --git a/src/Ai/Class/Druid/Action/DruidShapeshiftActions.cpp b/src/Ai/Class/Druid/Action/DruidShapeshiftActions.cpp index f30d4ec03..97cdcf9d8 100644 --- a/src/Ai/Class/Druid/Action/DruidShapeshiftActions.cpp +++ b/src/Ai/Class/Druid/Action/DruidShapeshiftActions.cpp @@ -50,9 +50,10 @@ bool CastCancelDruidAction::Execute(Event /*event*/) return true; } -bool CastCancelDruidAction::isUseful() { return botAI->HasAura(auraId, bot); } +bool CastCancelDruidAction::isUseful() { return bot->HasAura(auraId); } bool CastTreeFormAction::isUseful() { - return GetTarget() && CastSpellAction::isUseful() && !botAI->HasAura(33891, bot); + constexpr uint32 SPELL_TREE_OF_LIFE = 33891; + return GetTarget() && CastSpellAction::isUseful() && !bot->HasAura(SPELL_TREE_OF_LIFE); } diff --git a/src/Ai/Class/Druid/DruidTriggers.cpp b/src/Ai/Class/Druid/DruidTriggers.cpp index 03b5accc9..22b850329 100644 --- a/src/Ai/Class/Druid/DruidTriggers.cpp +++ b/src/Ai/Class/Druid/DruidTriggers.cpp @@ -28,7 +28,11 @@ bool ThornsTrigger::IsActive() { return BuffTrigger::IsActive() && !botAI->HasAu bool BearFormTrigger::IsActive() { return !botAI->HasAnyAuraOf(bot, "bear form", "dire bear form", nullptr); } -bool TreeFormTrigger::IsActive() { return !botAI->HasAura(33891, bot); } +bool TreeFormTrigger::IsActive() +{ + constexpr uint32 SPELL_TREE_OF_LIFE = 33891; + return !bot->HasAura(SPELL_TREE_OF_LIFE); +} bool CatFormTrigger::IsActive() { return !botAI->HasAura("cat form", bot); } @@ -43,8 +47,11 @@ bool ProwlTrigger::IsActive() if (botAI->HasAura("prowl", bot) || bot->IsInCombat()) return false; - uint32 prowlId = botAI->GetAiObjectContext()->GetValue("spell id", "prowl")->Get(); - if (!prowlId || !bot->HasSpell(prowlId) || bot->HasSpellCooldown(prowlId)) + if (!botAI->HasSpell("prowl")) + return false; + + uint32 const prowlId = AI_VALUE2(uint32, "spell id", "prowl"); + if (bot->HasSpellCooldown(prowlId)) return false; float distance = 30.f; diff --git a/src/Ai/Class/Druid/DruidTriggers.h b/src/Ai/Class/Druid/DruidTriggers.h index 990024685..fa0f21132 100644 --- a/src/Ai/Class/Druid/DruidTriggers.h +++ b/src/Ai/Class/Druid/DruidTriggers.h @@ -393,14 +393,14 @@ public: class FerociousBiteExecuteTrigger : public Trigger { public: - FerociousBiteExecuteTrigger(PlayerbotAI* ai) : Trigger(ai, "ferocious bite execute") {} + FerociousBiteExecuteTrigger(PlayerbotAI* botAI) : Trigger(botAI, "ferocious bite execute") {} bool IsActive() override { Unit* target = AI_VALUE(Unit*, "current target"); if (!target || !target->IsAlive()) return false; - if (!AI_VALUE2(uint32, "spell id", "ferocious bite")) + if (!botAI->HasSpell("ferocious bite")) return false; if (AI_VALUE2(uint8, "combo", "current target") < 1) diff --git a/src/Ai/Class/Druid/Strategy/DruidPullStrategy.cpp b/src/Ai/Class/Druid/Strategy/DruidPullStrategy.cpp index dc72b9e82..7c3727057 100644 --- a/src/Ai/Class/Druid/Strategy/DruidPullStrategy.cpp +++ b/src/Ai/Class/Druid/Strategy/DruidPullStrategy.cpp @@ -5,34 +5,23 @@ #include "DruidPullStrategy.h" -#include "AiObjectContext.h" -#include "Player.h" #include "PlayerbotAI.h" #include "Playerbots.h" std::string DruidPullStrategy::GetPullActionName() const { - Player* bot = botAI->GetBot(); - std::string actionName = PullStrategy::GetPullActionName(); - if (!bot) - return actionName; - - uint32 const faerieFireFeralId = botAI->GetAiObjectContext()->GetValue("spell id", "faerie fire (feral)")->Get(); - if (faerieFireFeralId && bot->HasSpell(faerieFireFeralId) && - (botAI->HasStrategy("bear", BOT_STATE_COMBAT) || botAI->HasStrategy("cat", BOT_STATE_COMBAT))) - { - actionName = "faerie fire (feral)"; - } + std::string const pullActionName = PullStrategy::GetPullActionName(); + std::string const actionName = + botAI->HasSpell("faerie fire (feral)") && + (botAI->HasStrategy("bear", BOT_STATE_COMBAT) || botAI->HasStrategy("cat", BOT_STATE_COMBAT)) + ? "faerie fire (feral)" : pullActionName; Unit* target = GetTarget(); - uint32 const faerieFireSpellId = botAI->GetAiObjectContext()->GetValue("spell id", actionName)->Get(); - if (target && (!faerieFireSpellId || !bot->HasSpell(faerieFireSpellId) || - !botAI->CanCastSpell(faerieFireSpellId, target))) - { - uint32 const growlSpellId = botAI->GetAiObjectContext()->GetValue("spell id", "growl")->Get(); - if (growlSpellId && bot->HasSpell(growlSpellId) && botAI->CanCastSpell(growlSpellId, target)) - return "growl"; - } + if (!target) + return actionName; + + if (!botAI->CanCastSpell(actionName, target) && botAI->CanCastSpell("growl", target)) + return "growl"; return actionName; } diff --git a/src/Ai/Class/Hunter/HunterActions.cpp b/src/Ai/Class/Hunter/HunterActions.cpp index a49f9a10e..c3116d1f8 100644 --- a/src/Ai/Class/Hunter/HunterActions.cpp +++ b/src/Ai/Class/Hunter/HunterActions.cpp @@ -19,23 +19,13 @@ bool CastViperStingAction::isUseful() bool CastAspectOfTheHawkAction::isUseful() { Unit* target = GetTarget(); - if (!target) - return false; - - if (bot->HasSpell(61846) || bot->HasSpell(61847)) // Aspect of the Dragonhawk spell IDs - return false; - - return true; + return target && !botAI->HasSpell("aspect of the dragonhawk"); } bool CastArcaneShotAction::isUseful() { Unit* target = GetTarget(); - if (!target) - return false; - - if (bot->HasSpell(53301) || bot->HasSpell(60051) || - bot->HasSpell(60052) || bot->HasSpell(60053)) // Explosive Shot spell IDs + if (!target || !botAI->HasSpell("explosive shot")) return false; // Armor Penetration rating check - will not cast Arcane Shot above 435 ArP @@ -50,14 +40,7 @@ bool CastArcaneShotAction::isUseful() bool CastImmolationTrapAction::isUseful() { Unit* target = GetTarget(); - if (!target) - return false; - - if (bot->HasSpell(13813) || bot->HasSpell(14316) || bot->HasSpell(14317) || bot->HasSpell(27025) || - bot->HasSpell(49066) || bot->HasSpell(49067)) // Explosive Trap spell IDs - return false; - - return true; + return target && !botAI->HasSpell("explosive trap"); } Value* CastFreezingTrap::GetTargetValue() diff --git a/src/Ai/Class/Mage/MageActions.cpp b/src/Ai/Class/Mage/MageActions.cpp index 9c190d54c..13b40fa55 100644 --- a/src/Ai/Class/Mage/MageActions.cpp +++ b/src/Ai/Class/Mage/MageActions.cpp @@ -13,7 +13,7 @@ std::vector CastMoltenArmorAction::getAlternatives() { - if (!AI_VALUE2(uint32, "spell id", "molten armor")) + if (!botAI->HasSpell("molten armor")) return NextAction::merge({ NextAction("mage armor") }, CastBuffSpellAction::getAlternatives()); return CastBuffSpellAction::getAlternatives(); @@ -21,7 +21,7 @@ std::vector CastMoltenArmorAction::getAlternatives() std::vector CastMageArmorAction::getAlternatives() { - if (!AI_VALUE2(uint32, "spell id", "mage armor")) + if (!botAI->HasSpell("mage armor")) return NextAction::merge({ NextAction("ice armor") }, CastBuffSpellAction::getAlternatives()); return CastBuffSpellAction::getAlternatives(); diff --git a/src/Ai/Class/Mage/MageTriggers.cpp b/src/Ai/Class/Mage/MageTriggers.cpp index 34babc81e..0be6ff13b 100644 --- a/src/Ai/Class/Mage/MageTriggers.cpp +++ b/src/Ai/Class/Mage/MageTriggers.cpp @@ -39,26 +39,16 @@ bool ArcaneIntellectTrigger::IsActive() bool MageArmorTrigger::IsActive() { Unit* target = GetTarget(); - if (botAI->HasAura("mage armor", target)) - return false; - - if (AI_VALUE2(uint32, "spell id", "mage armor")) - return true; - - return !botAI->HasAura("ice armor", target) && !botAI->HasAura("frost armor", target) && + return botAI->HasSpell("mage armor") && !botAI->HasAura("mage armor", target) && + !botAI->HasAura("ice armor", target) && !botAI->HasAura("frost armor", target) && !botAI->HasAura("molten armor", target); } bool MoltenArmorTrigger::IsActive() { Unit* target = GetTarget(); - if (botAI->HasAura("molten armor", target)) - return false; - - if (AI_VALUE2(uint32, "spell id", "molten armor")) - return true; - - return !botAI->HasAura("ice armor", target) && !botAI->HasAura("frost armor", target) && + return botAI->HasSpell("molten armor") && !botAI->HasAura("molten armor", target) && + !botAI->HasAura("ice armor", target) && !botAI->HasAura("frost armor", target) && !botAI->HasAura("mage armor", target); } @@ -82,7 +72,8 @@ bool FrostbiteOnTargetTrigger::IsActive() bool NoFocusMagicTrigger::IsActive() { - if (!bot->HasSpell(54646)) // Focus Magic + constexpr uint32 SPELL_FOCUS_MAGIC = 54646; + if (!bot->HasSpell(SPELL_FOCUS_MAGIC)) return false; Group* group = bot->GetGroup(); @@ -95,7 +86,7 @@ bool NoFocusMagicTrigger::IsActive() if (!member || member == bot || !member->IsAlive()) continue; - if (member->HasAura(54646, bot->GetGUID())) + if (member->HasAura(SPELL_FOCUS_MAGIC, bot->GetGUID())) return false; } return true; @@ -103,11 +94,9 @@ bool NoFocusMagicTrigger::IsActive() bool DeepFreezeCooldownTrigger::IsActive() { - // If the bot does NOT have Deep Freeze, treat as "on cooldown" - if (!bot->HasSpell(44572)) // Deep Freeze - return true; - - return SpellCooldownTrigger::IsActive(); + constexpr uint32 SPELL_DEEP_FREEZE = 44572; + return !bot->HasSpell(SPELL_DEEP_FREEZE) || + SpellCooldownTrigger::IsActive(); } const std::unordered_set FlamestrikeNearbyTrigger::FLAMESTRIKE_SPELL_IDS = { diff --git a/src/Ai/Class/Mage/Strategy/GenericMageStrategy.cpp b/src/Ai/Class/Mage/Strategy/GenericMageStrategy.cpp index 69389a8c4..36b594ce9 100644 --- a/src/Ai/Class/Mage/Strategy/GenericMageStrategy.cpp +++ b/src/Ai/Class/Mage/Strategy/GenericMageStrategy.cpp @@ -8,6 +8,18 @@ #include "Playerbots.h" #include "RangedCombatStrategy.h" +namespace +{ +constexpr uint32 SPELL_CONJURE_MANA_SAPPHIRE = 42985; +constexpr uint32 SPELL_CONJURE_MANA_EMERALD = 27101; +constexpr uint32 SPELL_CONJURE_MANA_RUBY = 10054; +constexpr uint32 SPELL_CONJURE_MANA_CITRINE = 10053; +constexpr uint32 SPELL_CONJURE_MANA_JADE = 3552; +constexpr uint32 SPELL_CONJURE_MANA_AGATE = 759; +constexpr uint32 SPELL_FROSTFIRE_BOLT = 44614; +constexpr uint32 SPELL_ICE_SHARDS = 15047; +} + class GenericMageStrategyActionNodeFactory : public NamedObjectFactory { public: @@ -102,17 +114,17 @@ void GenericMageStrategy::InitTriggers(std::vector& triggers) // Mana Threshold Triggers Player* bot = botAI->GetBot(); - if (bot->HasSpell(42985)) // Mana Sapphire + if (bot->HasSpell(SPELL_CONJURE_MANA_SAPPHIRE)) triggers.push_back(new TriggerNode("high mana", { NextAction("use mana sapphire", 90.0f) })); - else if (bot->HasSpell(27101)) // Mana Emerald + else if (bot->HasSpell(SPELL_CONJURE_MANA_EMERALD)) triggers.push_back(new TriggerNode("high mana", { NextAction("use mana emerald", 90.0f) })); - else if (bot->HasSpell(10054)) // Mana Ruby + else if (bot->HasSpell(SPELL_CONJURE_MANA_RUBY)) triggers.push_back(new TriggerNode("high mana", { NextAction("use mana ruby", 90.0f) })); - else if (bot->HasSpell(10053)) // Mana Citrine + else if (bot->HasSpell(SPELL_CONJURE_MANA_CITRINE)) triggers.push_back(new TriggerNode("high mana", { NextAction("use mana citrine", 90.0f) })); - else if (bot->HasSpell(3552)) // Mana Jade + else if (bot->HasSpell(SPELL_CONJURE_MANA_JADE)) triggers.push_back(new TriggerNode("high mana", { NextAction("use mana jade", 90.0f) })); - else if (bot->HasSpell(759)) // Mana Agate + else if (bot->HasSpell(SPELL_CONJURE_MANA_AGATE)) triggers.push_back(new TriggerNode("high mana", { NextAction("use mana agate", 90.0f) })); triggers.push_back(new TriggerNode("medium mana", { NextAction("mana potion", 90.0f) })); @@ -142,7 +154,7 @@ void MageBoostStrategy::InitTriggers(std::vector& triggers) } else if (tab == MAGE_TAB_FIRE) { - if (bot->HasSpell(44614) /*Frostfire Bolt*/ && bot->HasAura(15047) /*Ice Shards*/) + if (bot->HasSpell(SPELL_FROSTFIRE_BOLT) && bot->HasAura(SPELL_ICE_SHARDS)) { // Frostfire triggers.push_back(new TriggerNode("combustion", { NextAction("combustion", 18.0f) })); triggers.push_back(new TriggerNode("icy veins", { NextAction("icy veins", 17.5f) })); diff --git a/src/Ai/Class/Paladin/Actions/PaladinGreaterBlessingAction.cpp b/src/Ai/Class/Paladin/Actions/PaladinGreaterBlessingAction.cpp index 6a174d300..85f7f894f 100644 --- a/src/Ai/Class/Paladin/Actions/PaladinGreaterBlessingAction.cpp +++ b/src/Ai/Class/Paladin/Actions/PaladinGreaterBlessingAction.cpp @@ -1145,8 +1145,7 @@ bool CastGreaterBlessingAssignmentAction::Execute(Event /*event*/) if (!FindPendingAssignment(assignment, spellName)) return false; - uint32 finalId = AI_VALUE2(uint32, "spell id", spellName); - if (!finalId) + if (!botAI->HasSpell(spellName)) return false; return botAI->CastSpell(spellName, assignment.player); diff --git a/src/Ai/Class/Paladin/Strategy/PaladinPullStrategy.cpp b/src/Ai/Class/Paladin/Strategy/PaladinPullStrategy.cpp index ba0381b5a..988d9a987 100644 --- a/src/Ai/Class/Paladin/Strategy/PaladinPullStrategy.cpp +++ b/src/Ai/Class/Paladin/Strategy/PaladinPullStrategy.cpp @@ -5,34 +5,23 @@ #include "PaladinPullStrategy.h" -#include "AiObjectContext.h" -#include "Player.h" #include "PlayerbotAI.h" #include "Playerbots.h" std::string PaladinPullStrategy::GetPullActionName() const { - Player* bot = botAI->GetBot(); Unit* target = GetTarget(); - if (!bot || !target || + if (!target || (!botAI->HasStrategy("tank", BOT_STATE_COMBAT) && !botAI->HasStrategy("tank", BOT_STATE_NON_COMBAT))) { return PullStrategy::GetPullActionName(); } - uint32 const avengersShieldSpellId = botAI->GetAiObjectContext()->GetValue("spell id", "avenger's shield")->Get(); - if (avengersShieldSpellId && bot->HasSpell(avengersShieldSpellId) && - botAI->CanCastSpell(avengersShieldSpellId, target)) - { + if (botAI->CanCastSpell("avenger's shield", target)) return "avenger's shield"; - } - uint32 const handOfReckoningSpellId = botAI->GetAiObjectContext()->GetValue("spell id", "hand of reckoning")->Get(); - if (handOfReckoningSpellId && bot->HasSpell(handOfReckoningSpellId) && - botAI->CanCastSpell(handOfReckoningSpellId, target)) - { + if (botAI->CanCastSpell("hand of reckoning", target)) return "hand of reckoning"; - } return PullStrategy::GetPullActionName(); } diff --git a/src/Ai/Class/Rogue/Action/RogueActions.cpp b/src/Ai/Class/Rogue/Action/RogueActions.cpp index 46beaf86c..aae0d3eb0 100644 --- a/src/Ai/Class/Rogue/Action/RogueActions.cpp +++ b/src/Ai/Class/Rogue/Action/RogueActions.cpp @@ -11,6 +11,14 @@ #include "PlayerbotAIConfig.h" #include "Playerbots.h" +namespace +{ +constexpr uint32 SPELL_WARSONG_FLAG = 23333; +constexpr uint32 SPELL_SILVERWING_FLAG = 23335; +constexpr uint32 SPELL_NETHERSTORM_FLAG = 34976; +constexpr uint32 SPELL_MASTER_POISONER_RANK_3 = 58410; +} + bool CastStealthAction::isUseful() { Unit* target = AI_VALUE(Unit*, "current target"); @@ -22,7 +30,8 @@ bool CastStealthAction::isUseful() bool CastStealthAction::isPossible() { // do not use with WSG flag or EYE flag - return !botAI->HasAura(23333, bot) && !botAI->HasAura(23335, bot) && !botAI->HasAura(34976, bot); + return !bot->HasAura(SPELL_WARSONG_FLAG) && !bot->HasAura(SPELL_SILVERWING_FLAG) && + !bot->HasAura(SPELL_NETHERSTORM_FLAG); } bool UnstealthAction::Execute(Event /*event*/) @@ -50,7 +59,8 @@ bool CheckStealthAction::Execute(Event /*event*/) bool CastVanishAction::isUseful() { // do not use with WSG flag or EYE flag - return !botAI->HasAura(23333, bot) && !botAI->HasAura(23335, bot) && !botAI->HasAura(34976, bot); + return !bot->HasAura(SPELL_WARSONG_FLAG) && !bot->HasAura(SPELL_SILVERWING_FLAG) && + !bot->HasAura(SPELL_NETHERSTORM_FLAG); } bool CastEnvenomAction::isUseful() @@ -61,7 +71,7 @@ bool CastEnvenomAction::isUseful() bool CastEnvenomAction::isPossible() { // alternate to eviscerate if talents unlearned - return botAI->HasAura(58410, bot) /* Master Poisoner Rank 3 */; + return bot->HasAura(SPELL_MASTER_POISONER_RANK_3); } bool CastTricksOfTheTradeOnMainTankAction::isUseful() diff --git a/src/Ai/Class/Rogue/RogueTriggers.cpp b/src/Ai/Class/Rogue/RogueTriggers.cpp index c33dbb7fe..d8fd166a1 100644 --- a/src/Ai/Class/Rogue/RogueTriggers.cpp +++ b/src/Ai/Class/Rogue/RogueTriggers.cpp @@ -9,6 +9,12 @@ #include "Playerbots.h" #include "ServerFacade.h" +namespace +{ +constexpr uint32 SPELL_STEALTH = 1784; +constexpr uint32 SPELL_SPRINT_RANK_1 = 2983; +} + // bool AdrenalineRushTrigger::isPossible() // { // return !botAI->HasAura("stealth", bot); @@ -29,7 +35,7 @@ bool UnstealthTrigger::IsActive() bool StealthTrigger::IsActive() { - if (botAI->HasAura("stealth", bot) || bot->IsInCombat() || bot->HasSpellCooldown(1784)) + if (bot->HasAura(SPELL_STEALTH) || bot->IsInCombat() || bot->HasSpellCooldown(SPELL_STEALTH)) return false; float distance = 30.f; @@ -63,13 +69,13 @@ bool StealthTrigger::IsActive() return target && ServerFacade::instance().GetDistance2d(bot, target) < distance; } -bool SapTrigger::IsPossible() { return bot->GetLevel() > 10 && bot->HasSpell(6770) && !bot->IsInCombat(); } +bool SapTrigger::IsPossible() { return bot->GetLevel() > 10 && botAI->HasSpell("sap") && !bot->IsInCombat(); } -bool SprintTrigger::IsPossible() { return bot->HasSpell(2983); } +bool SprintTrigger::IsPossible() { return bot->HasSpell(SPELL_SPRINT_RANK_1); } bool SprintTrigger::IsActive() { - if (bot->HasSpellCooldown(2983)) + if (bot->HasSpellCooldown(SPELL_SPRINT_RANK_1)) return false; float distance = botAI->GetMaster() ? 45.0f : 35.0f; @@ -105,7 +111,7 @@ bool SprintTrigger::IsActive() bool ExposeArmorTrigger::IsActive() { - Unit* target = AI_VALUE(Unit*, "current target"); // Get the bot's current target + Unit* target = AI_VALUE(Unit*, "current target"); return DebuffTrigger::IsActive() && !botAI->HasAura("sunder armor", target, false, false, -1, true) && AI_VALUE2(uint8, "combo", "current target") <= 3; } diff --git a/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.cpp b/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.cpp index c5ae222c1..083a67eef 100644 --- a/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.cpp +++ b/src/Ai/Class/Shaman/Strategy/TotemsShamanStrategy.cpp @@ -6,6 +6,17 @@ #include "TotemsShamanStrategy.h" #include "Playerbots.h" +namespace +{ +constexpr uint32 SPELL_TOTEM_OF_WRATH = 30706; +constexpr uint32 SPELL_FLAMETONGUE_TOTEM = 8227; +constexpr uint32 SPELL_CLEANSING_TOTEM = 8170; +constexpr uint32 SPELL_MANA_SPRING_TOTEM = 5675; +constexpr uint32 SPELL_WRATH_OF_AIR_TOTEM = 3738; +constexpr uint32 SPELL_GROUNDING_TOTEM = 8177; +constexpr uint32 SPELL_WINDFURY_TOTEM = 8512; +} + // These combat strategies are used to set the corresponding totems on the bar, and cast the totem when it's missing. // There are special cases for Totem of Wrath, Windfury Totem, Wrath of Air totem, and Cleansing totem - these totems // aren't learned at level 30, and have fallbacks in order to prevent the trigger from continuously firing. @@ -74,9 +85,9 @@ void TotemOfWrathStrategy::InitTriggers(std::vector& triggers) GenericShamanStrategy::InitTriggers(triggers); // If the bot hasn't learned Totem of Wrath yet, set Flametongue Totem instead. Player* bot = botAI->GetBot(); - if (bot->HasSpell(30706)) + if (bot->HasSpell(SPELL_TOTEM_OF_WRATH)) triggers.push_back(new TriggerNode("set totem of wrath", { NextAction("set totem of wrath", 60.0f) })); - else if (bot->HasSpell(8227)) + else if (bot->HasSpell(SPELL_FLAMETONGUE_TOTEM)) triggers.push_back(new TriggerNode("set flametongue totem", { NextAction("set flametongue totem", 60.0f) })); triggers.push_back(new TriggerNode("no fire totem", { NextAction("totem of wrath", 55.0f) })); } @@ -112,9 +123,9 @@ void CleansingTotemStrategy::InitTriggers(std::vector& triggers) GenericShamanStrategy::InitTriggers(triggers); // If the bot hasn't learned Cleansing Totem yet, set Mana Spring Totem instead. Player* bot = botAI->GetBot(); - if (bot->HasSpell(8170)) + if (bot->HasSpell(SPELL_CLEANSING_TOTEM)) triggers.push_back(new TriggerNode("set cleansing totem", { NextAction("set cleansing totem", 60.0f) })); - else if (bot->HasSpell(5675)) + else if (bot->HasSpell(SPELL_MANA_SPRING_TOTEM)) triggers.push_back(new TriggerNode("set mana spring totem", { NextAction("set mana spring totem", 60.0f) })); triggers.push_back(new TriggerNode("no water totem", { NextAction("cleansing totem", 55.0f) })); } @@ -134,9 +145,9 @@ void WrathOfAirTotemStrategy::InitTriggers(std::vector& triggers) GenericShamanStrategy::InitTriggers(triggers); // If the bot hasn't learned Wrath of Air Totem yet, set Grounding Totem instead. Player* bot = botAI->GetBot(); - if (bot->HasSpell(3738)) + if (bot->HasSpell(SPELL_WRATH_OF_AIR_TOTEM)) triggers.push_back(new TriggerNode("set wrath of air totem", { NextAction("set wrath of air totem", 60.0f) })); - else if (bot->HasSpell(8177)) + else if (bot->HasSpell(SPELL_GROUNDING_TOTEM)) triggers.push_back(new TriggerNode("set grounding totem", { NextAction("set grounding totem", 60.0f) })); triggers.push_back( new TriggerNode("no air totem", { NextAction("wrath of air totem", 55.0f) })); } @@ -147,9 +158,9 @@ void WindfuryTotemStrategy::InitTriggers(std::vector& triggers) GenericShamanStrategy::InitTriggers(triggers); // If the bot hasn't learned Windfury Totem yet, set Grounding Totem instead. Player* bot = botAI->GetBot(); - if (bot->HasSpell(8512)) + if (bot->HasSpell(SPELL_WINDFURY_TOTEM)) triggers.push_back(new TriggerNode("set windfury totem", { NextAction("set windfury totem", 60.0f) })); - else if (bot->HasSpell(8177)) + else if (bot->HasSpell(SPELL_GROUNDING_TOTEM)) triggers.push_back(new TriggerNode("set grounding totem", { NextAction("set grounding totem", 60.0f) })); triggers.push_back(new TriggerNode("no air totem", { NextAction("windfury totem", 55.0f) })); } diff --git a/src/Ai/Class/Warlock/WarlockActions.cpp b/src/Ai/Class/Warlock/WarlockActions.cpp index 5e23f1af5..2deafd022 100644 --- a/src/Ai/Class/Warlock/WarlockActions.cpp +++ b/src/Ai/Class/Warlock/WarlockActions.cpp @@ -77,11 +77,7 @@ bool CastShadowflameAction::isUseful() bool CastRainOfFireAction::isUseful() { Unit* target = GetTarget(); - if (!target) - return false; - if (bot->HasSpell(27243) || bot->HasSpell(47835) || bot->HasSpell(47836)) // Seed of Corruption spell IDs - return false; - return true; + return target && !botAI->HasSpell("seed of corruption"); } // Checks if the enemies are close enough to use Hellfire diff --git a/src/Ai/Class/Warlock/WarlockTriggers.cpp b/src/Ai/Class/Warlock/WarlockTriggers.cpp index 14e7a52e5..52af8b038 100644 --- a/src/Ai/Class/Warlock/WarlockTriggers.cpp +++ b/src/Ai/Class/Warlock/WarlockTriggers.cpp @@ -104,10 +104,8 @@ bool LifeTapTrigger::IsActive() // Checks if the Life Tap Glyph buff is active bool LifeTapGlyphBuffTrigger::IsActive() { - if (!botAI->HasAura(63320, bot)) - return false; - - return BuffTrigger::IsActive(); + constexpr uint32 SPELL_LIFE_TAP_GLYPH = 63320; + return bot->HasAura(SPELL_LIFE_TAP_GLYPH) && BuffTrigger::IsActive(); } // Checks if the target has a conflicting debuff that is equal to Curse of the Elements diff --git a/src/Ai/Class/Warrior/Strategy/WarriorPullStrategy.cpp b/src/Ai/Class/Warrior/Strategy/WarriorPullStrategy.cpp index cdae7e29c..40609f5c8 100644 --- a/src/Ai/Class/Warrior/Strategy/WarriorPullStrategy.cpp +++ b/src/Ai/Class/Warrior/Strategy/WarriorPullStrategy.cpp @@ -5,23 +5,16 @@ #include "WarriorPullStrategy.h" -#include "AiObjectContext.h" -#include "Player.h" #include "PlayerbotAI.h" std::string WarriorPullStrategy::GetPullActionName() const { - Player* bot = botAI->GetBot(); Unit* target = GetTarget(); - if (!bot || !target) + if (!target) return PullStrategy::GetPullActionName(); - uint32 const heroicThrowSpellId = botAI->GetAiObjectContext()->GetValue("spell id", "heroic throw")->Get(); - if (heroicThrowSpellId && bot->HasSpell(heroicThrowSpellId) && - botAI->CanCastSpell(heroicThrowSpellId, target)) - { + if (botAI->CanCastSpell("heroic throw", target)) return "heroic throw"; - } return PullStrategy::GetPullActionName(); } diff --git a/src/Ai/Class/Warrior/WarriorActions.cpp b/src/Ai/Class/Warrior/WarriorActions.cpp index b30c1a38b..4636f7845 100644 --- a/src/Ai/Class/Warrior/WarriorActions.cpp +++ b/src/Ai/Class/Warrior/WarriorActions.cpp @@ -8,6 +8,15 @@ #include "AiFactory.h" #include "Playerbots.h" +namespace +{ +constexpr uint32 SPELL_RETALIATION = 20230; +constexpr uint32 SPELL_DIVINE_SHIELD = 642; +constexpr uint32 SPELL_ICE_BLOCK = 45438; +constexpr uint32 SPELL_BLESSING_OF_PROTECTION = 41450; +constexpr uint32 SPELL_SHATTERING_THROW = 64382; +} + bool CastBerserkerRageAction::isPossible() { if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true)) @@ -153,14 +162,8 @@ bool CastVigilanceAction::Execute(Event /*event*/) bool CastRetaliationAction::isUseful() { - // Spell cooldown check - if (!bot->HasSpell(20230)) - { - return false; - } - - // Spell cooldown check - if (bot->HasSpellCooldown(20230)) + if (!bot->HasSpell(SPELL_RETALIATION) || bot->HasSpellCooldown(SPELL_RETALIATION) || + bot->HasAura(SPELL_RETALIATION)) { return false; } @@ -199,8 +202,8 @@ bool CastRetaliationAction::isUseful() break; } - // Only cast Retaliation if there are at least 2 melee attackers and the buff is not active - return meleeAttackers >= 2 && !botAI->HasAura("retaliation", bot); + // Only cast Retaliation if there are at least 2 melee attackers + return meleeAttackers >= 2; } Unit* CastShatteringThrowAction::GetTarget() @@ -214,15 +217,15 @@ Unit* CastShatteringThrowAction::GetTarget() continue; if (bot->IsWithinDistInMap(enemy, 25.0f) && - (enemy->HasAura(642) || // Divine Shield - enemy->HasAura(45438) || // Ice Block - enemy->HasAura(41450))) // Blessing of Protection + (enemy->HasAura(SPELL_DIVINE_SHIELD) || + enemy->HasAura(SPELL_ICE_BLOCK) || + enemy->HasAura(SPELL_BLESSING_OF_PROTECTION))) { return enemy; } } - return nullptr; // No valid target + return nullptr; } bool CastShatteringThrowAction::Execute(Event /*event*/) @@ -236,7 +239,7 @@ bool CastShatteringThrowAction::Execute(Event /*event*/) bool CastShatteringThrowAction::isUseful() { - if (!bot->HasSpell(64382) || bot->HasSpellCooldown(64382)) + if (!bot->HasSpell(SPELL_SHATTERING_THROW) || bot->HasSpellCooldown(SPELL_SHATTERING_THROW)) return false; GuidVector enemies = AI_VALUE(GuidVector, "possible targets"); @@ -247,17 +250,16 @@ bool CastShatteringThrowAction::isUseful() if (!enemy || !enemy->IsAlive() || enemy->IsFriendlyTo(bot)) continue; - // Check if the enemy is within 25 yards and has the specific auras if (bot->IsWithinDistInMap(enemy, 25.0f) && - (enemy->HasAura(642) || // Divine Shield - enemy->HasAura(45438) || // Ice Block - enemy->HasAura(41450))) // Blessing of Protection + (enemy->HasAura(SPELL_DIVINE_SHIELD) || + enemy->HasAura(SPELL_ICE_BLOCK) || + enemy->HasAura(SPELL_BLESSING_OF_PROTECTION))) { return true; } } - return false; // No valid targets within range + return false; } bool CastShatteringThrowAction::isPossible() diff --git a/src/Ai/Class/Warrior/WarriorTriggers.cpp b/src/Ai/Class/Warrior/WarriorTriggers.cpp index f6e5bd234..e875c403c 100644 --- a/src/Ai/Class/Warrior/WarriorTriggers.cpp +++ b/src/Ai/Class/Warrior/WarriorTriggers.cpp @@ -6,6 +6,16 @@ #include "WarriorTriggers.h" #include "Playerbots.h" +namespace +{ +constexpr uint32 SPELL_VIGILANCE = 50720; +constexpr uint32 SPELL_SHATTERING_THROW = 64382; +constexpr uint32 SPELL_DIVINE_SHIELD = 642; +constexpr uint32 SPELL_ICE_BLOCK = 45438; +constexpr uint32 SPELL_BLESSING_OF_PROTECTION = 41450; +constexpr uint32 SPELL_COMMANDING_PRESENCE_RANKS[] = { 12318, 12857, 12858, 12860, 12861 }; +} + bool BloodrageBuffTrigger::IsActive() { return AI_VALUE2(uint8, "health", "self target") >= sPlayerbotAIConfig.mediumHealth && @@ -14,7 +24,7 @@ bool BloodrageBuffTrigger::IsActive() bool VigilanceTrigger::IsActive() { - if (!bot->HasSpell(50720)) + if (!bot->HasSpell(SPELL_VIGILANCE)) return false; Group* group = bot->GetGroup(); @@ -64,7 +74,7 @@ bool VigilanceTrigger::IsActive() bool ShatteringThrowTrigger::IsActive() { - if (!bot->HasSpell(64382) || bot->HasSpellCooldown(64382)) + if (!bot->HasSpell(SPELL_SHATTERING_THROW) || bot->HasSpellCooldown(SPELL_SHATTERING_THROW)) return false; GuidVector enemies = AI_VALUE(GuidVector, "possible targets"); @@ -76,9 +86,9 @@ bool ShatteringThrowTrigger::IsActive() continue; if (bot->IsWithinDistInMap(enemy, 25.0f) && - (enemy->HasAura(642) || // Divine Shield - enemy->HasAura(45438) || // Ice Block - enemy->HasAura(41450))) // Blessing of Protection + (enemy->HasAura(SPELL_DIVINE_SHIELD) || + enemy->HasAura(SPELL_ICE_BLOCK) || + enemy->HasAura(SPELL_BLESSING_OF_PROTECTION))) { return true; } @@ -112,15 +122,13 @@ bool BattleShoutTrigger::IsActive() if (!bsApValue) return false; - static const uint32 commandingPresenceSpells[] = { - 12318, 12857, 12858, 12860, 12861 }; static const float commandingPresenceBonus[] = { 0.05f, 0.10f, 0.15f, 0.20f, 0.25f }; float cpBonus = 0.0f; for (int rank = 4; rank >= 0; --rank) { - if (bot->HasAura(commandingPresenceSpells[rank])) + if (bot->HasAura(SPELL_COMMANDING_PRESENCE_RANKS[rank])) { cpBonus = commandingPresenceBonus[rank]; break; diff --git a/src/Ai/Raid/Naxx/Action/NaxxActions_Razuvious.cpp b/src/Ai/Raid/Naxx/Action/NaxxActions_Razuvious.cpp index 5d91db0c6..5d865b14f 100644 --- a/src/Ai/Raid/Naxx/Action/NaxxActions_Razuvious.cpp +++ b/src/Ai/Raid/Naxx/Action/NaxxActions_Razuvious.cpp @@ -5,6 +5,13 @@ #include "Playerbots.h" #include "SharedDefines.h" +namespace +{ +constexpr uint32 SPELL_UNDERSTUDY_TAUNT = 29060; +constexpr uint32 SPELL_BONE_BARRIER = 29061; +constexpr uint32 SPELL_BLOOD_STRIKE = 61696; +} + bool RazuviousUseObedienceCrystalAction::Execute(Event /*event*/) { if (!helper.UpdateBossAI()) @@ -42,7 +49,8 @@ bool RazuviousUseObedienceCrystalAction::Execute(Event /*event*/) bool tauntUseful = true; if (forceObedience->GetDuration() <= (duration_time - 5000)) { - if (target->GetVictim() && botAI->HasAura(29061, target->GetVictim())) + Unit* victim = target->GetVictim(); + if (victim && victim->HasAura(SPELL_BONE_BARRIER)) tauntUseful = false; if (forceObedience->GetDuration() <= 3000) @@ -55,19 +63,19 @@ bool RazuviousUseObedienceCrystalAction::Execute(Event /*event*/) if (tauntUseful && !charm->HasSpellCooldown(29060)) { // shield - if (!charm->HasSpellCooldown(29061)) + if (!charm->HasSpellCooldown(SPELL_BONE_BARRIER)) { - charm->CastSpell(charm, 29061, true); - charm->AddSpellCooldown(29061, 0, 30 * 1000); + charm->CastSpell(charm, SPELL_BONE_BARRIER, true); + charm->AddSpellCooldown(SPELL_BONE_BARRIER, 0, 30 * 1000); } - charm->CastSpell(target, 29060, true); - charm->AddSpellCooldown(29060, 0, 20 * 1000); + charm->CastSpell(target, SPELL_UNDERSTUDY_TAUNT, true); + charm->AddSpellCooldown(SPELL_UNDERSTUDY_TAUNT, 0, 20 * 1000); } // strike - if (!charm->HasSpellCooldown(61696)) + if (!charm->HasSpellCooldown(SPELL_BLOOD_STRIKE)) { - charm->CastSpell(target, 61696, true); - charm->AddSpellCooldown(61696, 0, 4 * 1000); + charm->CastSpell(target, SPELL_BLOOD_STRIKE, true); + charm->AddSpellCooldown(SPELL_BLOOD_STRIKE, 0, 4 * 1000); } } } diff --git a/src/Ai/Raid/Naxx/Action/NaxxActions_Sapphiron.cpp b/src/Ai/Raid/Naxx/Action/NaxxActions_Sapphiron.cpp index 55bcdabc4..a0861be39 100644 --- a/src/Ai/Raid/Naxx/Action/NaxxActions_Sapphiron.cpp +++ b/src/Ai/Raid/Naxx/Action/NaxxActions_Sapphiron.cpp @@ -75,7 +75,7 @@ bool SapphironFlightPositionAction::MoveToNearestIcebolt() for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) { Player* member = ref->GetSource(); - if (NaxxSpellIds::HasAnyAura(botAI, member, {NaxxSpellIds::Icebolt10, NaxxSpellIds::Icebolt25}) || + if (NaxxSpellIds::HasAnyAura(member, {NaxxSpellIds::Icebolt10, NaxxSpellIds::Icebolt25}) || botAI->HasAura("icebolt", member, false, false, -1, true)) { if (!playerWithIcebolt || minDistance > bot->GetDistance(member)) diff --git a/src/Ai/Raid/Naxx/Action/NaxxActions_Thaddius.cpp b/src/Ai/Raid/Naxx/Action/NaxxActions_Thaddius.cpp index 016a9faa5..106d43c36 100644 --- a/src/Ai/Raid/Naxx/Action/NaxxActions_Thaddius.cpp +++ b/src/Ai/Raid/Naxx/Action/NaxxActions_Thaddius.cpp @@ -111,15 +111,13 @@ bool ThaddiusMovePolarityAction::Execute(Event /*event*/) {3504.68f, -2936.68f}, }; uint32 idx; - if (NaxxSpellIds::HasAnyAura( - botAI, bot, + if (NaxxSpellIds::HasAnyAura(bot, {NaxxSpellIds::NegativeCharge10, NaxxSpellIds::NegativeCharge25, NaxxSpellIds::NegativeChargeStack}) || botAI->HasAura("negative charge", bot, false, false, -1, true)) { idx = 0; } - else if (NaxxSpellIds::HasAnyAura( - botAI, bot, + else if (NaxxSpellIds::HasAnyAura(bot, {NaxxSpellIds::PositiveCharge10, NaxxSpellIds::PositiveCharge25, NaxxSpellIds::PositiveChargeStack}) || botAI->HasAura("positive charge", bot, false, false, -1, true)) { diff --git a/src/Ai/Raid/Naxx/NaxxBossHelper.h b/src/Ai/Raid/Naxx/NaxxBossHelper.h index 7bec3a7df..2df40a701 100644 --- a/src/Ai/Raid/Naxx/NaxxBossHelper.h +++ b/src/Ai/Raid/Naxx/NaxxBossHelper.h @@ -192,7 +192,7 @@ public: { Player* member = ref->GetSource(); if (member && - (NaxxSpellIds::HasAnyAura(botAI, member, {NaxxSpellIds::Icebolt10, NaxxSpellIds::Icebolt25}) || + (NaxxSpellIds::HasAnyAura(member, {NaxxSpellIds::Icebolt10, NaxxSpellIds::Icebolt25}) || botAI->HasAura("icebolt", member, false, false, -1, true))) { return true; diff --git a/src/Ai/Raid/Naxx/NaxxMultipliers.cpp b/src/Ai/Raid/Naxx/NaxxMultipliers.cpp index b7700eb1b..1c2cf05bf 100644 --- a/src/Ai/Raid/Naxx/NaxxMultipliers.cpp +++ b/src/Ai/Raid/Naxx/NaxxMultipliers.cpp @@ -236,7 +236,7 @@ float AnubrekhanGenericMultiplier::GetValue(Action* action) return 1.0f; if (NaxxSpellIds::HasAnyAura( - botAI, boss, {NaxxSpellIds::LocustSwarm10, NaxxSpellIds::LocustSwarm10Alt, NaxxSpellIds::LocustSwarm25}) || + boss, {NaxxSpellIds::LocustSwarm10, NaxxSpellIds::LocustSwarm10Alt, NaxxSpellIds::LocustSwarm25}) || botAI->HasAura("locust swarm", boss)) { if (dynamic_cast(action)) diff --git a/src/Ai/Raid/Naxx/NaxxSpellIds.h b/src/Ai/Raid/Naxx/NaxxSpellIds.h index 94c013eb7..2a7308d81 100644 --- a/src/Ai/Raid/Naxx/NaxxSpellIds.h +++ b/src/Ai/Raid/Naxx/NaxxSpellIds.h @@ -123,14 +123,14 @@ namespace NaxxSpellIds SPELL_INEVITABLE_DOOM = 29204, SPELL_BERSERK = 26662 */ - inline bool HasAnyAura(PlayerbotAI* botAI, Unit* unit, std::initializer_list spellIds) + inline bool HasAnyAura(Unit* unit, std::initializer_list spellIds) { - if (!botAI || !unit) + if (!unit) return false; for (uint32 spellId : spellIds) { - if (botAI->HasAura(spellId, unit)) + if (unit->HasAura(spellId)) return true; } return false; diff --git a/src/Ai/Raid/Uld/UldTriggers.cpp b/src/Ai/Raid/Uld/UldTriggers.cpp index 7c84043ef..102bf0f59 100644 --- a/src/Ai/Raid/Uld/UldTriggers.cpp +++ b/src/Ai/Raid/Uld/UldTriggers.cpp @@ -1531,7 +1531,7 @@ bool VezaxShadowCrashTrigger::IsActive() if (!boss || !boss->IsAlive()) return false; - return botAI->HasAura(SPELL_VEZAX_SHADOW_CRASH, bot); + return bot->HasAura(SPELL_VEZAX_SHADOW_CRASH); } bool VezaxMarkOfTheFacelessTrigger::IsActive() @@ -1542,7 +1542,7 @@ bool VezaxMarkOfTheFacelessTrigger::IsActive() if (!boss || !boss->IsAlive()) return false; - if (!botAI->HasAura(SPELL_MARK_OF_THE_FACELESS, bot)) + if (!bot->HasAura(SPELL_MARK_OF_THE_FACELESS)) return false; float distance = bot->GetDistance2d(ULDUAR_VEZAX_MARK_OF_THE_FACELESS_SPOT.GetPositionX(), diff --git a/src/Bot/Factory/AiFactory.cpp b/src/Bot/Factory/AiFactory.cpp index b3abbd8ad..d54244994 100644 --- a/src/Bot/Factory/AiFactory.cpp +++ b/src/Bot/Factory/AiFactory.cpp @@ -26,6 +26,15 @@ #include "WarlockAiObjectContext.h" #include "WarriorAiObjectContext.h" +namespace +{ +constexpr uint32 SPELL_FROSTFIRE_BOLT = 44614; +constexpr uint32 SPELL_ICE_SHARDS = 15047; +constexpr uint32 SPELL_WHIRLWIND = 1680; +constexpr uint32 SPELL_CAT_FORM = 768; +constexpr uint32 SPELL_DRUID_THICK_HIDE = 16931; +} + AiObjectContext* AiFactory::createAiObjectContext(Player* player, PlayerbotAI* botAI) { switch (player->getClass()) @@ -300,7 +309,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa engine->addStrategiesNoInit("arcane", "bdps", nullptr); else if (tab == MAGE_TAB_FIRE) { - if (player->HasSpell(44614) /*Frostfire Bolt*/ && player->HasAura(15047) /*Ice Shards*/) + if (player->HasSpell(SPELL_FROSTFIRE_BOLT) && player->HasAura(SPELL_ICE_SHARDS)) engine->addStrategiesNoInit("frostfire", "bdps", nullptr); else engine->addStrategiesNoInit("fire", "bdps", nullptr); @@ -313,7 +322,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa case CLASS_WARRIOR: if (tab == WARRIOR_TAB_PROTECTION) engine->addStrategiesNoInit("tank", "tank assist", "pull", "pull back", "aoe", nullptr); - else if (tab == WARRIOR_TAB_ARMS || !player->HasSpell(1680)) // Whirlwind + else if (tab == WARRIOR_TAB_ARMS || !player->HasSpell(SPELL_WHIRLWIND)) engine->addStrategiesNoInit("arms", "aoe", "dps assist", nullptr); else // if (tab == WARRIOR_TAB_FURY) engine->addStrategiesNoInit("fury", "aoe", "dps assist", nullptr); @@ -345,7 +354,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa engine->addStrategiesNoInit("resto", "cure", "dps assist", "blanketing", "tranquility", nullptr); else { - if (player->HasSpell(768) /*cat form*/ && !player->HasAura(16931) /*thick hide*/) + if (player->HasSpell(SPELL_CAT_FORM) && !player->HasAura(SPELL_DRUID_THICK_HIDE)) engine->addStrategiesNoInit("cat", "aoe", "cc", "dps assist", "feral charge", nullptr); else engine->addStrategiesNoInit("bear", "tank assist", "pull", "pull back", "feral charge", nullptr); @@ -535,7 +544,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const case CLASS_DRUID: if (tab == DRUID_TAB_FERAL) { - if (player->GetLevel() >= 20 && !player->HasAura(16931) /*thick hide*/) + if (player->GetLevel() >= 20 && !player->HasAura(SPELL_DRUID_THICK_HIDE)) nonCombatEngine->addStrategy("dps assist", false); else nonCombatEngine->addStrategiesNoInit("tank assist", "pull", nullptr); diff --git a/src/Bot/Factory/PlayerbotFactory.cpp b/src/Bot/Factory/PlayerbotFactory.cpp index 06e3e8405..0abfecfa9 100644 --- a/src/Bot/Factory/PlayerbotFactory.cpp +++ b/src/Bot/Factory/PlayerbotFactory.cpp @@ -61,6 +61,56 @@ std::vector PlayerbotFactory::enchantGemIdCache; std::unordered_map> PlayerbotFactory::trainerIdCache; std::vector PlayerbotFactory::ccBreakTrinketCache; +namespace +{ +constexpr uint32 SPELL_DRUID_THICK_HIDE = 16931; +constexpr uint32 SPELL_OWLKIN_FRENZY = 48393; +constexpr uint32 SPELL_PRIMAL_TENACITY = 33957; +constexpr uint32 SPELL_IMPROVED_BARKSKIN = 63411; + +constexpr uint32 SPELL_SECOND_WIND = 29838; +constexpr uint32 SPELL_BLOOD_CRAZE = 16492; +constexpr uint32 SPELL_GAG_ORDER = 12958; + +constexpr uint32 SPELL_SACRED_CLEANSING = 53553; +constexpr uint32 SPELL_RECKONING = 20179; +constexpr uint32 SPELL_DIVINE_PURPOSE = 31872; + +constexpr uint32 SPELL_HUNTER_THICK_HIDE = 19612; +constexpr uint32 SPELL_CONCUSSIVE_BARRAGE = 35102; +constexpr uint32 SPELL_ENTRAPMENT = 19388; + +constexpr uint32 SPELL_DEADLY_BREW = 51626; +constexpr uint32 SPELL_THROWING_SPECIALIZATION = 51679; +constexpr uint32 SPELL_WAYLAY = 51696; + +constexpr uint32 SPELL_IMPROVED_MANA_BURN = 14772; +constexpr uint32 SPELL_BODY_AND_SOUL = 64129; +constexpr uint32 SPELL_IMPROVED_VAMPIRIC_EMBRACE = 27840; + +constexpr uint32 SPELL_ABOMINATIONS_MIGHT = 53138; +constexpr uint32 SPELL_IMPROVED_ICY_TALONS = 55610; +constexpr uint32 SPELL_SUDDEN_DOOM = 49529; +constexpr uint32 SPELL_ACCLIMATION = 50152; +constexpr uint32 SPELL_MAGIC_SUPPRESSION = 49611; + +constexpr uint32 SPELL_SHAMAN_DUAL_WIELD = 30798; +constexpr uint32 SPELL_ASTRAL_SHIFT = 51479; +constexpr uint32 SPELL_EARTHEN_POWER = 51524; +constexpr uint32 SPELL_FOCUSED_MIND = 30866; + +constexpr uint32 SPELL_BURNOUT = 44472; +constexpr uint32 SPELL_ICE_SHARDS = 15047; +constexpr uint32 SPELL_IMPROVED_BLINK = 31570; +constexpr uint32 SPELL_FIERY_PAYBACK = 64357; +constexpr uint32 SPELL_SHATTERED_BARRIER = 54787; + +constexpr uint32 SPELL_IMPROVED_HOWL_OF_TERROR = 30057; +constexpr uint32 SPELL_NEMESIS = 63123; +constexpr uint32 SPELL_INTENSITY = 18136; +constexpr uint32 SPELL_NETHER_PROTECTION = 30302; +} + bool PlayerbotFactory::IsPrimaryTradeSkill(uint16 skillId) { SkillLineEntry const* skillLine = sSkillLineStore.LookupEntry(skillId); @@ -1440,7 +1490,7 @@ uint32 PlayerbotFactory::InitTalentsTree(bool increment /*false*/, bool use_temp /// @todo: fix cat druid hardcode if (bot->getClass() == CLASS_DRUID && specTab == DRUID_TAB_FERAL && bot->GetLevel() >= 20) { - bool isCat = !bot->HasAura(16931); + bool isCat = !bot->HasAura(SPELL_DRUID_THICK_HIDE); if (!isCat && bot->GetLevel() == 20) { uint32 bearP = sPlayerbotAIConfig.randomClassSpecProb[cls][1]; @@ -1495,7 +1545,7 @@ uint32 PlayerbotFactory::InitTalentsTree(bool increment /*false*/, bool use_temp if (bot->GetFreeTalentPoints()) InitTalents((specTab + 2) % 3); - if (bot->getClass() == CLASS_SHAMAN && bot->HasSpell(30798)) + if (bot->getClass() == CLASS_SHAMAN && bot->HasSpell(SPELL_SHAMAN_DUAL_WIELD)) { bot->SetSkill(SKILL_DUAL_WIELD, 0, 1, 1); bot->SetCanDualWield(true); @@ -1581,7 +1631,7 @@ void PlayerbotFactory::InitTalentsBySpecNo(Player* bot, int specNo, bool reset) } } - if (bot->getClass() == CLASS_SHAMAN && bot->HasSpell(30798)) + if (bot->getClass() == CLASS_SHAMAN && bot->HasSpell(SPELL_SHAMAN_DUAL_WIELD)) { bot->SetSkill(SKILL_DUAL_WIELD, 0, 1, 1); bot->SetCanDualWield(true); @@ -4170,13 +4220,13 @@ void PlayerbotFactory::InitGlyphs(bool increment) if (bot->getClass() == CLASS_WARRIOR) { // Arms PvP (spec index 3): If the bot has the Second Wind talent - if (bot->HasAura(29838)) + if (bot->HasAura(SPELL_SECOND_WIND)) tab = 3; // Fury PvP (spec index 4): If the bot has the Blood Craze talent - else if (bot->HasAura(16492)) + else if (bot->HasAura(SPELL_BLOOD_CRAZE)) tab = 4; // Protection PvP (spec index 5): If the bot has the Gag Order talent - else if (bot->HasAura(12958)) + else if (bot->HasAura(SPELL_GAG_ORDER)) tab = 5; } @@ -4184,13 +4234,13 @@ void PlayerbotFactory::InitGlyphs(bool increment) if (bot->getClass() == CLASS_PALADIN) { // Holy PvP (spec index 3): If the bot has the Sacred Cleansing talent - if (bot->HasAura(53553)) + if (bot->HasAura(SPELL_SACRED_CLEANSING)) tab = 3; // Protection PvP (spec index 4): If the bot has the Reckoning talent - else if (bot->HasAura(20179)) + else if (bot->HasAura(SPELL_RECKONING)) tab = 4; // Retribution PvP (spec index 5): If the bot has the Divine Purpose talent - else if (bot->HasAura(31872)) + else if (bot->HasAura(SPELL_DIVINE_PURPOSE)) tab = 5; } @@ -4198,13 +4248,13 @@ void PlayerbotFactory::InitGlyphs(bool increment) if (bot->getClass() == CLASS_HUNTER) { // Beast Mastery PvP (spec index 3): If the bot has the Thick Hide talent - if (bot->HasAura(19612)) + if (bot->HasAura(SPELL_HUNTER_THICK_HIDE)) tab = 3; // Marksmanship PvP (spec index 4): If the bot has the Concussive Barrage talent - else if (bot->HasAura(35102)) + else if (bot->HasAura(SPELL_CONCUSSIVE_BARRAGE)) tab = 4; // Survival PvP (spec index 5): If the bot has the Entrapment talent and does NOT have the Concussive Barrage talent - else if (bot->HasAura(19388) && !bot->HasAura(35102)) + else if (bot->HasAura(SPELL_ENTRAPMENT) && !bot->HasAura(SPELL_CONCUSSIVE_BARRAGE)) tab = 5; } @@ -4212,13 +4262,13 @@ void PlayerbotFactory::InitGlyphs(bool increment) if (bot->getClass() == CLASS_ROGUE) { // Assassination PvP (spec index 3): If the bot has the Deadly Brew talent - if (bot->HasAura(51626)) + if (bot->HasAura(SPELL_DEADLY_BREW)) tab = 3; // Combat PvP (spec index 4): If the bot has the Throwing Specialization talent - else if (bot->HasAura(51679)) + else if (bot->HasAura(SPELL_THROWING_SPECIALIZATION)) tab = 4; // Subtlety PvP (spec index 5): If the bot has the Waylay talent - else if (bot->HasAura(51696)) + else if (bot->HasAura(SPELL_WAYLAY)) tab = 5; } @@ -4226,13 +4276,13 @@ void PlayerbotFactory::InitGlyphs(bool increment) if (bot->getClass() == CLASS_PRIEST) { // Discipline PvP (spec index 3): If the bot has the Improved Mana Burn talent - if (bot->HasAura(14772)) + if (bot->HasAura(SPELL_IMPROVED_MANA_BURN)) tab = 3; // Holy PvP (spec index 4): If the bot has the Body and Soul talent - else if (bot->HasAura(64129)) + else if (bot->HasAura(SPELL_BODY_AND_SOUL)) tab = 4; // Shadow PvP (spec index 5): If the bot has the Improved Vampiric Embrace talent - else if (bot->HasAura(27840)) + else if (bot->HasAura(SPELL_IMPROVED_VAMPIRIC_EMBRACE)) tab = 5; } @@ -4241,16 +4291,16 @@ void PlayerbotFactory::InitGlyphs(bool increment) { // Double Aura Blood PvE (spec index 3): If the bot has both the Abomination's Might and Improved Icy Talons // talents - if (bot->HasAura(53138) && bot->HasAura(55610)) + if (bot->HasAura(SPELL_ABOMINATIONS_MIGHT) && bot->HasAura(SPELL_IMPROVED_ICY_TALONS)) tab = 3; // Blood PvP (spec index 4): If the bot has the Sudden Doom talent - else if (bot->HasAura(49529)) + else if (bot->HasAura(SPELL_SUDDEN_DOOM)) tab = 4; // Frost PvP (spec index 5): If the bot has the Acclimation talent - else if (bot->HasAura(50152)) + else if (bot->HasAura(SPELL_ACCLIMATION)) tab = 5; // Unholy PvP (spec index 6): If the bot has the Magic Suppression talent - else if (bot->HasAura(49611)) + else if (bot->HasAura(SPELL_MAGIC_SUPPRESSION)) tab = 6; } @@ -4258,13 +4308,13 @@ void PlayerbotFactory::InitGlyphs(bool increment) if (bot->getClass() == CLASS_SHAMAN) { // Elemental PvP (spec index 3): If the bot has the Astral Shift talent - if (bot->HasAura(51479)) + if (bot->HasAura(SPELL_ASTRAL_SHIFT)) tab = 3; // Enhancement PvP (spec index 4): If the bot has the Earthen Power talent - else if (bot->HasAura(51524)) + else if (bot->HasAura(SPELL_EARTHEN_POWER)) tab = 4; // Restoration PvP (spec index 5): If the bot has the Focused Mind talent - else if (bot->HasAura(30866)) + else if (bot->HasAura(SPELL_FOCUSED_MIND)) tab = 5; } @@ -4272,16 +4322,16 @@ void PlayerbotFactory::InitGlyphs(bool increment) if (bot->getClass() == CLASS_MAGE) { // Frostfire PvE (spec index 3): If the bot has both the Burnout talent and the Ice Shards talent - if (bot->HasAura(44472) && bot->HasAura(15047)) + if (bot->HasAura(SPELL_BURNOUT) && bot->HasAura(SPELL_ICE_SHARDS)) tab = 3; // Arcane PvP (spec index 4): If the bot has the Improved Blink talent - else if (bot->HasAura(31570)) + else if (bot->HasAura(SPELL_IMPROVED_BLINK)) tab = 4; // Fire PvP (spec index 5): If the bot has the Fiery Payback talent - else if (bot->HasAura(64357)) + else if (bot->HasAura(SPELL_FIERY_PAYBACK)) tab = 5; // Frost PvP (spec index 6): If the bot has the Shattered Barrier talent - else if (bot->HasAura(54787)) + else if (bot->HasAura(SPELL_SHATTERED_BARRIER)) tab = 6; } @@ -4289,13 +4339,13 @@ void PlayerbotFactory::InitGlyphs(bool increment) if (bot->getClass() == CLASS_WARLOCK) { // Affliction PvP (spec index 3): If the bot has the Improved Howl of Terror talent - if (bot->HasAura(30057)) + if (bot->HasAura(SPELL_IMPROVED_HOWL_OF_TERROR)) tab = 3; // Demonology PvP (spec index 4): If the bot has both the Nemesis talent and the Intensity talent - else if (bot->HasAura(63123) && bot->HasAura(18136)) + else if (bot->HasAura(SPELL_NEMESIS) && bot->HasAura(SPELL_INTENSITY)) tab = 4; // Destruction PvP (spec index 5): If the bot has the Nether Protection talent - else if (bot->HasAura(30302)) + else if (bot->HasAura(SPELL_NETHER_PROTECTION)) tab = 5; } @@ -4303,16 +4353,16 @@ void PlayerbotFactory::InitGlyphs(bool increment) if (bot->getClass() == CLASS_DRUID) { // Cat PvE (spec index 3): If the bot is Feral spec, level 20 or higher, and does NOT have the Thick Hide talent - if (tab == DRUID_TAB_FERAL && bot->GetLevel() >= 20 && !bot->HasAura(16931)) + if (tab == DRUID_TAB_FERAL && bot->GetLevel() >= 20 && !bot->HasAura(SPELL_DRUID_THICK_HIDE)) tab = 3; // Balance PvP (spec index 4): If the bot has the Owlkin Frenzy talent - else if (bot->HasAura(48393)) + else if (bot->HasAura(SPELL_OWLKIN_FRENZY)) tab = 4; // Feral PvP (spec index 5): If the bot has the Primal Tenacity talent - else if (bot->HasAura(33957)) + else if (bot->HasAura(SPELL_PRIMAL_TENACITY)) tab = 5; // Resto PvP (spec index 6): If the bot has the Improved Barkskin talent - else if (bot->HasAura(63411)) + else if (bot->HasAura(SPELL_IMPROVED_BARKSKIN)) tab = 6; } diff --git a/src/Bot/PlayerbotAI.cpp b/src/Bot/PlayerbotAI.cpp index 8bd1f2c2f..00f878686 100644 --- a/src/Bot/PlayerbotAI.cpp +++ b/src/Bot/PlayerbotAI.cpp @@ -3027,6 +3027,8 @@ bool PlayerbotAI::TellMaster(std::string const text, PlayerbotSecurityLevel secu { if (sPlayerbotAIConfig.randomBotSayWithoutMaster) return TellMasterNoFacing(text, securityLevel); + + return false; } if (!TellMasterNoFacing(text, securityLevel)) return false; @@ -3150,20 +3152,10 @@ bool PlayerbotAI::HasAura(std::string const name, Unit* unit, bool maxStack, boo return false; } -bool PlayerbotAI::HasAura(uint32 spellId, Unit const* unit) +bool PlayerbotAI::HasSpell(std::string const spellName) const { - if (!spellId || !unit) - return false; - - return unit->HasAura(spellId); - // for (uint8 effect = EFFECT_0; effect <= EFFECT_2; effect++) - // { - // AuraEffect const* aurEff = unit->GetAuraEffect(spellId, effect); - // if (IsRealAura(bot, aurEff, unit)) - // return true; - // } - - // return false; + uint32 const spellId = aiObjectContext->GetValue("spell id", spellName)->Get(); + return spellId && bot->HasSpell(spellId); } Aura* PlayerbotAI::GetAura(std::string const name, Unit* unit, bool checkIsOwner, bool checkDuration, int checkStack) @@ -4267,7 +4259,7 @@ void PlayerbotAI::InterruptSpell() void PlayerbotAI::RemoveAura(std::string const name) { uint32 spellid = aiObjectContext->GetValue("spell id", name)->Get(); - if (spellid && HasAura(spellid, bot)) + if (spellid && bot->HasAura(spellid)) bot->RemoveAurasDueToSpell(spellid); } diff --git a/src/Bot/PlayerbotAI.h b/src/Bot/PlayerbotAI.h index 2e31c9a9e..033b6aaeb 100644 --- a/src/Bot/PlayerbotAI.h +++ b/src/Bot/PlayerbotAI.h @@ -497,6 +497,7 @@ public: virtual bool CanCastSpell(std::string const name, Unit* target, Item* itemTarget = nullptr); virtual bool CastSpell(std::string const name, Unit* target, Item* itemTarget = nullptr); + virtual bool HasSpell(std::string const spellName) const; virtual bool HasAura(std::string const spellName, Unit* player, bool maxStack = false, bool checkIsOwner = false, int maxAmount = -1, bool checkDuration = false); virtual bool HasAnyAuraOf(Unit* player, ...); @@ -509,7 +510,6 @@ public: bool CanCastSpell(uint32 spellid, float x, float y, float z, bool checkHasSpell = true, Item* itemTarget = nullptr); - bool HasAura(uint32 spellId, Unit const* player); Aura* GetAura(std::string const spellName, Unit* unit, bool checkIsOwner = false, bool checkDuration = false, int checkStack = -1); bool CastSpell(uint32 spellId, Unit* target, Item* itemTarget = nullptr); diff --git a/src/Mgr/Item/StatsWeightCalculator.cpp b/src/Mgr/Item/StatsWeightCalculator.cpp index 2e11f0a38..4e61dd09e 100644 --- a/src/Mgr/Item/StatsWeightCalculator.cpp +++ b/src/Mgr/Item/StatsWeightCalculator.cpp @@ -23,13 +23,29 @@ namespace { -constexpr uint32 SPELL_MOLTEN_ARMOR_RANK_1 = 30482; -constexpr uint32 SPELL_MOLTEN_ARMOR_RANK_2 = 43045; -constexpr uint32 SPELL_MOLTEN_ARMOR_RANK_3 = 43046; -constexpr uint32 SPELL_FEL_ARMOR_RANK_1 = 28176; -constexpr uint32 SPELL_FEL_ARMOR_RANK_2 = 28189; -constexpr uint32 SPELL_FEL_ARMOR_RANK_3 = 47892; -constexpr uint32 SPELL_FEL_ARMOR_RANK_4 = 47893; +constexpr uint32 SPELL_MOLTEN_ARMOR_RANKS[] = { 30482, 43045, 43046 }; +constexpr uint32 SPELL_FEL_ARMOR_RANKS[] = { 28176, 28189, 47892, 47893 }; +constexpr uint32 SPELL_CAREFUL_AIM = 34484; +constexpr uint32 SPELL_HUNTER_VS_WILD = 56341; +constexpr uint32 SPELL_ARMORED_TO_THE_TEETH = 61222; +constexpr uint32 SPELL_MENTAL_DEXTERITY = 51885; +constexpr uint32 SPELL_ROGUE_SWORD_SPECIALIZATION = 13964; +constexpr uint32 SPELL_POLEAXE_SPECIALIZATION = 12785; +constexpr uint32 SPELL_NERVES_OF_COLD_STEEL = 50138; +constexpr uint32 SPELL_SHADOW_FOCUS = 15835; +constexpr uint32 SPELL_ARCANE_FOCUS = 12840; +} + +template +bool HasAnySpell(Player* player, uint32 const (&spellIds)[Size]) +{ + for (uint32 const spellId : spellIds) + { + if (player->HasSpell(spellId)) + return true; + } + + return false; } StatsWeightCalculator::StatsWeightCalculator(Player* player) : player_(player) @@ -512,26 +528,24 @@ void StatsWeightCalculator::GenerateAdditionalWeights(Player* player) // int tab = AiFactory::GetPlayerSpecTab(player); if (cls == CLASS_HUNTER) { - if (player->HasAura(34484)) + if (player->HasAura(SPELL_CAREFUL_AIM)) stats_weights_[STATS_TYPE_INTELLECT] += 1.1f; - if (player->HasAura(56341)) + if (player->HasAura(SPELL_HUNTER_VS_WILD)) stats_weights_[STATS_TYPE_STAMINA] += 0.3f; } else if (cls == CLASS_WARRIOR) { - if (player->HasAura(61222)) + if (player->HasAura(SPELL_ARMORED_TO_THE_TEETH)) stats_weights_[STATS_TYPE_ARMOR] += 0.03f; } else if (cls == CLASS_SHAMAN) { - if (player->HasAura(51885)) + if (player->HasAura(SPELL_MENTAL_DEXTERITY)) stats_weights_[STATS_TYPE_INTELLECT] += 1.1f; } else if (cls == CLASS_MAGE) { - if (!player->HasSpell(SPELL_MOLTEN_ARMOR_RANK_1) - && !player->HasSpell(SPELL_MOLTEN_ARMOR_RANK_2) - && !player->HasSpell(SPELL_MOLTEN_ARMOR_RANK_3)) + if (!HasAnySpell(player, SPELL_MOLTEN_ARMOR_RANKS)) { if (tab != MAGE_TAB_FIRE) stats_weights_[STATS_TYPE_SPIRIT] -= 0.6f; @@ -541,8 +555,7 @@ void StatsWeightCalculator::GenerateAdditionalWeights(Player* player) } else if (cls == CLASS_WARLOCK) { - if (!player->HasSpell(SPELL_FEL_ARMOR_RANK_1) && !player->HasSpell(SPELL_FEL_ARMOR_RANK_2) && - !player->HasSpell(SPELL_FEL_ARMOR_RANK_3) && !player->HasSpell(SPELL_FEL_ARMOR_RANK_4)) + if (!HasAnySpell(player, SPELL_FEL_ARMOR_RANKS)) stats_weights_[STATS_TYPE_SPIRIT] -= 0.4f; } @@ -690,17 +703,17 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto) weight_ *= 1.5; } - if (cls == CLASS_ROGUE && player_->HasAura(13964) && + if (cls == CLASS_ROGUE && player_->HasAura(SPELL_ROGUE_SWORD_SPECIALIZATION) && (proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE)) { weight_ *= 1.1; } - if (cls == CLASS_WARRIOR && player_->HasAura(12785) && + if (cls == CLASS_WARRIOR && player_->HasAura(SPELL_POLEAXE_SPECIALIZATION) && (proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2)) { weight_ *= 1.1; } - if (cls == CLASS_DEATH_KNIGHT && player_->HasAura(50138) && !isDoubleHand) + if (cls == CLASS_DEATH_KNIGHT && player_->HasAura(SPELL_NERVES_OF_COLD_STEEL) && !isDoubleHand) { weight_ *= 1.3; } @@ -739,9 +752,9 @@ void StatsWeightCalculator::ApplyOverflowPenalty(Player* player) player->GetTotalAuraModifier(SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT); // suppression (18176) hit_current += player->GetRatingBonusValue(CR_HIT_SPELL); - if (cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW && player->HasAura(15835)) // Shadow Focus + if (cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW && player->HasAura(SPELL_SHADOW_FOCUS)) hit_current += 3; - if (cls == CLASS_MAGE && tab == MAGE_TAB_ARCANE && player->HasAura(12840)) // Arcane Focus + if (cls == CLASS_MAGE && tab == MAGE_TAB_ARCANE && player->HasAura(SPELL_ARCANE_FOCUS)) hit_current += 3; hit_overflow = SPELL_HIT_OVERFLOW;