mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
Compare commits
No commits in common. "085e127e38bcc9952338e40e45a8a22472585502" and "f989976c9392fe750a4e823341dd6bf7d0db1ae5" have entirely different histories.
085e127e38
...
f989976c93
@ -17,7 +17,6 @@
|
||||
#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<uint32, PreferredMountCache> CheckMountStateAction::mountCache;
|
||||
@ -62,21 +61,6 @@ 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");
|
||||
@ -220,7 +204,7 @@ bool CheckMountStateAction::Mount()
|
||||
// Get bot mount data
|
||||
MountData mountData = CollectMountData(bot);
|
||||
int32 masterMountType = GetMountType(master);
|
||||
int32 masterSpeed = CalculateMasterMountSpeed(master);
|
||||
int32 masterSpeed = CalculateMasterMountSpeed(master, mountData);
|
||||
|
||||
// Try shapeshift
|
||||
if (TryForms(master, masterMountType, masterSpeed))
|
||||
@ -250,17 +234,14 @@ void CheckMountStateAction::Dismount()
|
||||
WorldPacket emptyPacket;
|
||||
bot->GetSession()->HandleCancelMountAuraOpcode(emptyPacket);
|
||||
|
||||
ClearStaleFlightFlags();
|
||||
}
|
||||
|
||||
void CheckMountStateAction::ClearStaleFlightFlags()
|
||||
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))
|
||||
{
|
||||
if (bot->HasIncreaseMountedFlightSpeedAura() || bot->HasFlyAura())
|
||||
return;
|
||||
|
||||
if (bot->HasUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY))
|
||||
{
|
||||
bot->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_CAN_FLY);
|
||||
bot->RemoveUnitMovementFlag(
|
||||
MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY);
|
||||
if (!bot->IsRooted())
|
||||
bot->SendMovementFlagUpdate();
|
||||
}
|
||||
@ -509,7 +490,7 @@ static bool BotCanUseFlyingMount(Player const* bot)
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 CheckMountStateAction::CalculateMasterMountSpeed(Player* master) const
|
||||
int32 CheckMountStateAction::CalculateMasterMountSpeed(Player* master, const MountData& mountData) const
|
||||
{
|
||||
// Check riding skill and level requirements
|
||||
int32 ridingSkill = bot->GetPureSkillValue(SKILL_RIDING);
|
||||
|
||||
@ -53,10 +53,9 @@ 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;
|
||||
int32 CalculateMasterMountSpeed(Player* master, const MountData& mountData) const;
|
||||
bool CheckForSwiftMount() const;
|
||||
std::map<uint32, std::map<int32, std::vector<uint32>>> GetAllMountSpells() const;
|
||||
bool TryForms(Player* master, int32 masterMountType, int32 masterSpeed) const;
|
||||
|
||||
@ -422,9 +422,10 @@ 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);
|
||||
constexpr uint32 SPELL_CALL_PET = 883;
|
||||
if (bot->getClass() == CLASS_HUNTER && bot->HasSpell(SPELL_CALL_PET))
|
||||
bot->CastSpell(bot, SPELL_CALL_PET, true);
|
||||
if (bot->getClass() == CLASS_HUNTER && bot->HasSpell(883))
|
||||
{
|
||||
bot->CastSpell(bot, 883, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -67,10 +67,9 @@ bool TradeStatusExtendedAction::Execute(Event event)
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr uint32 SPELL_PICK_LOCK = 1804;
|
||||
if (bot->getClass() == CLASS_ROGUE && bot->HasSpell(SPELL_PICK_LOCK) && lockbox->IsLocked())
|
||||
if (bot->getClass() == CLASS_ROGUE && bot->HasSpell(1804) && lockbox->IsLocked()) // Pick Lock spell
|
||||
{
|
||||
// botAI->CastSpell(SPELL_PICK_LOCK, bot, lockbox); // Attempt to cast Pick Lock on the lockbox
|
||||
// botAI->CastSpell(1804, bot, lockbox); // Attempt to cast Pick Lock on the lockbox
|
||||
botAI->DoSpecificAction("unlock traded item");
|
||||
botAI->SetNextCheckDelay(4000); // Delay before accepting trade
|
||||
}
|
||||
|
||||
@ -23,7 +23,9 @@ bool BossFireResistanceTrigger::IsActive()
|
||||
return false;
|
||||
|
||||
// Check if bot have fire resistance aura
|
||||
if (botAI->HasAura("fire resistance aura", bot))
|
||||
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))
|
||||
return false;
|
||||
|
||||
// Check if bot dont have already have fire resistance strategy
|
||||
@ -74,7 +76,9 @@ bool BossFrostResistanceTrigger::IsActive()
|
||||
return false;
|
||||
|
||||
// Check if bot have frost resistance aura
|
||||
if (botAI->HasAura("frost resistance aura", bot))
|
||||
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))
|
||||
return false;
|
||||
|
||||
// Check if bot dont have already have frost resistance strategy
|
||||
@ -129,7 +133,8 @@ bool BossNatureResistanceTrigger::IsActive()
|
||||
return false;
|
||||
|
||||
// Check if bot have nature resistance aura
|
||||
if (botAI->HasAura("aspect of the wild", bot))
|
||||
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))
|
||||
return false;
|
||||
|
||||
// Check if bot dont have already setted nature resistance aura
|
||||
@ -179,7 +184,11 @@ bool BossShadowResistanceTrigger::IsActive()
|
||||
return false;
|
||||
|
||||
// Check if bot have shadow resistance aura
|
||||
if (botAI->HasAura("shadow resistance aura", bot))
|
||||
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))
|
||||
return false;
|
||||
|
||||
// Check if bot dont have already have shadow resistance strategy
|
||||
|
||||
@ -5,27 +5,39 @@
|
||||
|
||||
#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 (!target ||
|
||||
if (!bot || !target ||
|
||||
(!botAI->HasStrategy("blood", BOT_STATE_COMBAT) && !botAI->HasStrategy("blood", BOT_STATE_NON_COMBAT)))
|
||||
{
|
||||
return PullStrategy::GetPullActionName();
|
||||
}
|
||||
|
||||
if (botAI->CanCastSpell("death grip", target))
|
||||
uint32 const deathGripSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "death grip")->Get();
|
||||
if (deathGripSpellId && bot->HasSpell(deathGripSpellId) &&
|
||||
botAI->CanCastSpell(deathGripSpellId, target))
|
||||
{
|
||||
return "death grip";
|
||||
}
|
||||
|
||||
if (!botAI->CanCastSpell("icy touch", target) &&
|
||||
botAI->CanCastSpell("dark command", target))
|
||||
uint32 const icyTouchSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "icy touch")->Get();
|
||||
if (!icyTouchSpellId || !bot->HasSpell(icyTouchSpellId) ||
|
||||
!botAI->CanCastSpell(icyTouchSpellId, target))
|
||||
{
|
||||
uint32 const darkCommandSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "dark command")->Get();
|
||||
if (darkCommandSpellId && bot->HasSpell(darkCommandSpellId) &&
|
||||
botAI->CanCastSpell(darkCommandSpellId, target))
|
||||
{
|
||||
return "dark command";
|
||||
}
|
||||
}
|
||||
|
||||
return PullStrategy::GetPullActionName();
|
||||
}
|
||||
|
||||
@ -50,10 +50,9 @@ bool CastCancelDruidAction::Execute(Event /*event*/)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CastCancelDruidAction::isUseful() { return bot->HasAura(auraId); }
|
||||
bool CastCancelDruidAction::isUseful() { return botAI->HasAura(auraId, bot); }
|
||||
|
||||
bool CastTreeFormAction::isUseful()
|
||||
{
|
||||
constexpr uint32 SPELL_TREE_OF_LIFE = 33891;
|
||||
return GetTarget() && CastSpellAction::isUseful() && !bot->HasAura(SPELL_TREE_OF_LIFE);
|
||||
return GetTarget() && CastSpellAction::isUseful() && !botAI->HasAura(33891, bot);
|
||||
}
|
||||
|
||||
@ -28,11 +28,7 @@ bool ThornsTrigger::IsActive() { return BuffTrigger::IsActive() && !botAI->HasAu
|
||||
|
||||
bool BearFormTrigger::IsActive() { return !botAI->HasAnyAuraOf(bot, "bear form", "dire bear form", nullptr); }
|
||||
|
||||
bool TreeFormTrigger::IsActive()
|
||||
{
|
||||
constexpr uint32 SPELL_TREE_OF_LIFE = 33891;
|
||||
return !bot->HasAura(SPELL_TREE_OF_LIFE);
|
||||
}
|
||||
bool TreeFormTrigger::IsActive() { return !botAI->HasAura(33891, bot); }
|
||||
|
||||
bool CatFormTrigger::IsActive() { return !botAI->HasAura("cat form", bot); }
|
||||
|
||||
@ -47,11 +43,8 @@ bool ProwlTrigger::IsActive()
|
||||
if (botAI->HasAura("prowl", bot) || bot->IsInCombat())
|
||||
return false;
|
||||
|
||||
if (!botAI->HasSpell("prowl"))
|
||||
return false;
|
||||
|
||||
uint32 const prowlId = AI_VALUE2(uint32, "spell id", "prowl");
|
||||
if (bot->HasSpellCooldown(prowlId))
|
||||
uint32 prowlId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "prowl")->Get();
|
||||
if (!prowlId || !bot->HasSpell(prowlId) || bot->HasSpellCooldown(prowlId))
|
||||
return false;
|
||||
|
||||
float distance = 30.f;
|
||||
|
||||
@ -393,14 +393,14 @@ public:
|
||||
class FerociousBiteExecuteTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
FerociousBiteExecuteTrigger(PlayerbotAI* botAI) : Trigger(botAI, "ferocious bite execute") {}
|
||||
FerociousBiteExecuteTrigger(PlayerbotAI* ai) : Trigger(ai, "ferocious bite execute") {}
|
||||
bool IsActive() override
|
||||
{
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
if (!target || !target->IsAlive())
|
||||
return false;
|
||||
|
||||
if (!botAI->HasSpell("ferocious bite"))
|
||||
if (!AI_VALUE2(uint32, "spell id", "ferocious bite"))
|
||||
return false;
|
||||
|
||||
if (AI_VALUE2(uint8, "combo", "current target") < 1)
|
||||
|
||||
@ -5,23 +5,34 @@
|
||||
|
||||
#include "DruidPullStrategy.h"
|
||||
|
||||
#include "AiObjectContext.h"
|
||||
#include "Player.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
std::string DruidPullStrategy::GetPullActionName() const
|
||||
{
|
||||
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();
|
||||
if (!target)
|
||||
Player* bot = botAI->GetBot();
|
||||
std::string actionName = PullStrategy::GetPullActionName();
|
||||
if (!bot)
|
||||
return actionName;
|
||||
|
||||
if (!botAI->CanCastSpell(actionName, target) && botAI->CanCastSpell("growl", target))
|
||||
uint32 const faerieFireFeralId = botAI->GetAiObjectContext()->GetValue<uint32>("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)";
|
||||
}
|
||||
|
||||
Unit* target = GetTarget();
|
||||
uint32 const faerieFireSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", actionName)->Get();
|
||||
if (target && (!faerieFireSpellId || !bot->HasSpell(faerieFireSpellId) ||
|
||||
!botAI->CanCastSpell(faerieFireSpellId, target)))
|
||||
{
|
||||
uint32 const growlSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "growl")->Get();
|
||||
if (growlSpellId && bot->HasSpell(growlSpellId) && botAI->CanCastSpell(growlSpellId, target))
|
||||
return "growl";
|
||||
}
|
||||
|
||||
return actionName;
|
||||
}
|
||||
|
||||
@ -19,13 +19,23 @@ bool CastViperStingAction::isUseful()
|
||||
bool CastAspectOfTheHawkAction::isUseful()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
return target && !botAI->HasSpell("aspect of the dragonhawk");
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
if (bot->HasSpell(61846) || bot->HasSpell(61847)) // Aspect of the Dragonhawk spell IDs
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CastArcaneShotAction::isUseful()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (!target || !botAI->HasSpell("explosive shot"))
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
if (bot->HasSpell(53301) || bot->HasSpell(60051) ||
|
||||
bot->HasSpell(60052) || bot->HasSpell(60053)) // Explosive Shot spell IDs
|
||||
return false;
|
||||
|
||||
// Armor Penetration rating check - will not cast Arcane Shot above 435 ArP
|
||||
@ -40,7 +50,14 @@ bool CastArcaneShotAction::isUseful()
|
||||
bool CastImmolationTrapAction::isUseful()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
return target && !botAI->HasSpell("explosive trap");
|
||||
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;
|
||||
}
|
||||
|
||||
Value<Unit*>* CastFreezingTrap::GetTargetValue()
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
std::vector<NextAction> CastMoltenArmorAction::getAlternatives()
|
||||
{
|
||||
if (!botAI->HasSpell("molten armor"))
|
||||
if (!AI_VALUE2(uint32, "spell id", "molten armor"))
|
||||
return NextAction::merge({ NextAction("mage armor") }, CastBuffSpellAction::getAlternatives());
|
||||
|
||||
return CastBuffSpellAction::getAlternatives();
|
||||
@ -21,7 +21,7 @@ std::vector<NextAction> CastMoltenArmorAction::getAlternatives()
|
||||
|
||||
std::vector<NextAction> CastMageArmorAction::getAlternatives()
|
||||
{
|
||||
if (!botAI->HasSpell("mage armor"))
|
||||
if (!AI_VALUE2(uint32, "spell id", "mage armor"))
|
||||
return NextAction::merge({ NextAction("ice armor") }, CastBuffSpellAction::getAlternatives());
|
||||
|
||||
return CastBuffSpellAction::getAlternatives();
|
||||
|
||||
@ -39,16 +39,26 @@ bool ArcaneIntellectTrigger::IsActive()
|
||||
bool MageArmorTrigger::IsActive()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
return botAI->HasSpell("mage armor") && !botAI->HasAura("mage armor", target) &&
|
||||
!botAI->HasAura("ice armor", target) && !botAI->HasAura("frost armor", target) &&
|
||||
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) &&
|
||||
!botAI->HasAura("molten armor", target);
|
||||
}
|
||||
|
||||
bool MoltenArmorTrigger::IsActive()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
return botAI->HasSpell("molten armor") && !botAI->HasAura("molten armor", target) &&
|
||||
!botAI->HasAura("ice armor", target) && !botAI->HasAura("frost armor", target) &&
|
||||
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) &&
|
||||
!botAI->HasAura("mage armor", target);
|
||||
}
|
||||
|
||||
@ -72,8 +82,7 @@ bool FrostbiteOnTargetTrigger::IsActive()
|
||||
|
||||
bool NoFocusMagicTrigger::IsActive()
|
||||
{
|
||||
constexpr uint32 SPELL_FOCUS_MAGIC = 54646;
|
||||
if (!bot->HasSpell(SPELL_FOCUS_MAGIC))
|
||||
if (!bot->HasSpell(54646)) // Focus Magic
|
||||
return false;
|
||||
|
||||
Group* group = bot->GetGroup();
|
||||
@ -86,7 +95,7 @@ bool NoFocusMagicTrigger::IsActive()
|
||||
if (!member || member == bot || !member->IsAlive())
|
||||
continue;
|
||||
|
||||
if (member->HasAura(SPELL_FOCUS_MAGIC, bot->GetGUID()))
|
||||
if (member->HasAura(54646, bot->GetGUID()))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -94,9 +103,11 @@ bool NoFocusMagicTrigger::IsActive()
|
||||
|
||||
bool DeepFreezeCooldownTrigger::IsActive()
|
||||
{
|
||||
constexpr uint32 SPELL_DEEP_FREEZE = 44572;
|
||||
return !bot->HasSpell(SPELL_DEEP_FREEZE) ||
|
||||
SpellCooldownTrigger::IsActive();
|
||||
// If the bot does NOT have Deep Freeze, treat as "on cooldown"
|
||||
if (!bot->HasSpell(44572)) // Deep Freeze
|
||||
return true;
|
||||
|
||||
return SpellCooldownTrigger::IsActive();
|
||||
}
|
||||
|
||||
const std::unordered_set<uint32> FlamestrikeNearbyTrigger::FLAMESTRIKE_SPELL_IDS = {
|
||||
|
||||
@ -8,18 +8,6 @@
|
||||
#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<ActionNode>
|
||||
{
|
||||
public:
|
||||
@ -114,17 +102,17 @@ void GenericMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
// Mana Threshold Triggers
|
||||
Player* bot = botAI->GetBot();
|
||||
if (bot->HasSpell(SPELL_CONJURE_MANA_SAPPHIRE))
|
||||
if (bot->HasSpell(42985)) // Mana Sapphire
|
||||
triggers.push_back(new TriggerNode("high mana", { NextAction("use mana sapphire", 90.0f) }));
|
||||
else if (bot->HasSpell(SPELL_CONJURE_MANA_EMERALD))
|
||||
else if (bot->HasSpell(27101)) // Mana Emerald
|
||||
triggers.push_back(new TriggerNode("high mana", { NextAction("use mana emerald", 90.0f) }));
|
||||
else if (bot->HasSpell(SPELL_CONJURE_MANA_RUBY))
|
||||
else if (bot->HasSpell(10054)) // Mana Ruby
|
||||
triggers.push_back(new TriggerNode("high mana", { NextAction("use mana ruby", 90.0f) }));
|
||||
else if (bot->HasSpell(SPELL_CONJURE_MANA_CITRINE))
|
||||
else if (bot->HasSpell(10053)) // Mana Citrine
|
||||
triggers.push_back(new TriggerNode("high mana", { NextAction("use mana citrine", 90.0f) }));
|
||||
else if (bot->HasSpell(SPELL_CONJURE_MANA_JADE))
|
||||
else if (bot->HasSpell(3552)) // Mana Jade
|
||||
triggers.push_back(new TriggerNode("high mana", { NextAction("use mana jade", 90.0f) }));
|
||||
else if (bot->HasSpell(SPELL_CONJURE_MANA_AGATE))
|
||||
else if (bot->HasSpell(759)) // 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) }));
|
||||
@ -154,7 +142,7 @@ void MageBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
}
|
||||
else if (tab == MAGE_TAB_FIRE)
|
||||
{
|
||||
if (bot->HasSpell(SPELL_FROSTFIRE_BOLT) && bot->HasAura(SPELL_ICE_SHARDS))
|
||||
if (bot->HasSpell(44614) /*Frostfire Bolt*/ && bot->HasAura(15047) /*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) }));
|
||||
|
||||
@ -1145,7 +1145,8 @@ bool CastGreaterBlessingAssignmentAction::Execute(Event /*event*/)
|
||||
if (!FindPendingAssignment(assignment, spellName))
|
||||
return false;
|
||||
|
||||
if (!botAI->HasSpell(spellName))
|
||||
uint32 finalId = AI_VALUE2(uint32, "spell id", spellName);
|
||||
if (!finalId)
|
||||
return false;
|
||||
|
||||
return botAI->CastSpell(spellName, assignment.player);
|
||||
|
||||
@ -5,23 +5,34 @@
|
||||
|
||||
#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 (!target ||
|
||||
if (!bot || !target ||
|
||||
(!botAI->HasStrategy("tank", BOT_STATE_COMBAT) && !botAI->HasStrategy("tank", BOT_STATE_NON_COMBAT)))
|
||||
{
|
||||
return PullStrategy::GetPullActionName();
|
||||
}
|
||||
|
||||
if (botAI->CanCastSpell("avenger's shield", target))
|
||||
uint32 const avengersShieldSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "avenger's shield")->Get();
|
||||
if (avengersShieldSpellId && bot->HasSpell(avengersShieldSpellId) &&
|
||||
botAI->CanCastSpell(avengersShieldSpellId, target))
|
||||
{
|
||||
return "avenger's shield";
|
||||
}
|
||||
|
||||
if (botAI->CanCastSpell("hand of reckoning", target))
|
||||
uint32 const handOfReckoningSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "hand of reckoning")->Get();
|
||||
if (handOfReckoningSpellId && bot->HasSpell(handOfReckoningSpellId) &&
|
||||
botAI->CanCastSpell(handOfReckoningSpellId, target))
|
||||
{
|
||||
return "hand of reckoning";
|
||||
}
|
||||
|
||||
return PullStrategy::GetPullActionName();
|
||||
}
|
||||
|
||||
@ -11,14 +11,6 @@
|
||||
#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");
|
||||
@ -30,8 +22,7 @@ bool CastStealthAction::isUseful()
|
||||
bool CastStealthAction::isPossible()
|
||||
{
|
||||
// do not use with WSG flag or EYE flag
|
||||
return !bot->HasAura(SPELL_WARSONG_FLAG) && !bot->HasAura(SPELL_SILVERWING_FLAG) &&
|
||||
!bot->HasAura(SPELL_NETHERSTORM_FLAG);
|
||||
return !botAI->HasAura(23333, bot) && !botAI->HasAura(23335, bot) && !botAI->HasAura(34976, bot);
|
||||
}
|
||||
|
||||
bool UnstealthAction::Execute(Event /*event*/)
|
||||
@ -59,8 +50,7 @@ bool CheckStealthAction::Execute(Event /*event*/)
|
||||
bool CastVanishAction::isUseful()
|
||||
{
|
||||
// do not use with WSG flag or EYE flag
|
||||
return !bot->HasAura(SPELL_WARSONG_FLAG) && !bot->HasAura(SPELL_SILVERWING_FLAG) &&
|
||||
!bot->HasAura(SPELL_NETHERSTORM_FLAG);
|
||||
return !botAI->HasAura(23333, bot) && !botAI->HasAura(23335, bot) && !botAI->HasAura(34976, bot);
|
||||
}
|
||||
|
||||
bool CastEnvenomAction::isUseful()
|
||||
@ -71,7 +61,7 @@ bool CastEnvenomAction::isUseful()
|
||||
bool CastEnvenomAction::isPossible()
|
||||
{
|
||||
// alternate to eviscerate if talents unlearned
|
||||
return bot->HasAura(SPELL_MASTER_POISONER_RANK_3);
|
||||
return botAI->HasAura(58410, bot) /* Master Poisoner Rank 3 */;
|
||||
}
|
||||
|
||||
bool CastTricksOfTheTradeOnMainTankAction::isUseful()
|
||||
|
||||
@ -9,12 +9,6 @@
|
||||
#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);
|
||||
@ -35,7 +29,7 @@ bool UnstealthTrigger::IsActive()
|
||||
|
||||
bool StealthTrigger::IsActive()
|
||||
{
|
||||
if (bot->HasAura(SPELL_STEALTH) || bot->IsInCombat() || bot->HasSpellCooldown(SPELL_STEALTH))
|
||||
if (botAI->HasAura("stealth", bot) || bot->IsInCombat() || bot->HasSpellCooldown(1784))
|
||||
return false;
|
||||
|
||||
float distance = 30.f;
|
||||
@ -69,13 +63,13 @@ bool StealthTrigger::IsActive()
|
||||
return target && ServerFacade::instance().GetDistance2d(bot, target) < distance;
|
||||
}
|
||||
|
||||
bool SapTrigger::IsPossible() { return bot->GetLevel() > 10 && botAI->HasSpell("sap") && !bot->IsInCombat(); }
|
||||
bool SapTrigger::IsPossible() { return bot->GetLevel() > 10 && bot->HasSpell(6770) && !bot->IsInCombat(); }
|
||||
|
||||
bool SprintTrigger::IsPossible() { return bot->HasSpell(SPELL_SPRINT_RANK_1); }
|
||||
bool SprintTrigger::IsPossible() { return bot->HasSpell(2983); }
|
||||
|
||||
bool SprintTrigger::IsActive()
|
||||
{
|
||||
if (bot->HasSpellCooldown(SPELL_SPRINT_RANK_1))
|
||||
if (bot->HasSpellCooldown(2983))
|
||||
return false;
|
||||
|
||||
float distance = botAI->GetMaster() ? 45.0f : 35.0f;
|
||||
@ -111,7 +105,7 @@ bool SprintTrigger::IsActive()
|
||||
|
||||
bool ExposeArmorTrigger::IsActive()
|
||||
{
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
Unit* target = AI_VALUE(Unit*, "current target"); // Get the bot's current target
|
||||
return DebuffTrigger::IsActive() && !botAI->HasAura("sunder armor", target, false, false, -1, true) &&
|
||||
AI_VALUE2(uint8, "combo", "current target") <= 3;
|
||||
}
|
||||
|
||||
@ -6,17 +6,6 @@
|
||||
#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.
|
||||
@ -85,9 +74,9 @@ void TotemOfWrathStrategy::InitTriggers(std::vector<TriggerNode*>& 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(SPELL_TOTEM_OF_WRATH))
|
||||
if (bot->HasSpell(30706))
|
||||
triggers.push_back(new TriggerNode("set totem of wrath", { NextAction("set totem of wrath", 60.0f) }));
|
||||
else if (bot->HasSpell(SPELL_FLAMETONGUE_TOTEM))
|
||||
else if (bot->HasSpell(8227))
|
||||
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) }));
|
||||
}
|
||||
@ -123,9 +112,9 @@ void CleansingTotemStrategy::InitTriggers(std::vector<TriggerNode*>& 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(SPELL_CLEANSING_TOTEM))
|
||||
if (bot->HasSpell(8170))
|
||||
triggers.push_back(new TriggerNode("set cleansing totem", { NextAction("set cleansing totem", 60.0f) }));
|
||||
else if (bot->HasSpell(SPELL_MANA_SPRING_TOTEM))
|
||||
else if (bot->HasSpell(5675))
|
||||
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) }));
|
||||
}
|
||||
@ -145,9 +134,9 @@ void WrathOfAirTotemStrategy::InitTriggers(std::vector<TriggerNode*>& 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(SPELL_WRATH_OF_AIR_TOTEM))
|
||||
if (bot->HasSpell(3738))
|
||||
triggers.push_back(new TriggerNode("set wrath of air totem", { NextAction("set wrath of air totem", 60.0f) }));
|
||||
else if (bot->HasSpell(SPELL_GROUNDING_TOTEM))
|
||||
else if (bot->HasSpell(8177))
|
||||
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) }));
|
||||
}
|
||||
@ -158,9 +147,9 @@ void WindfuryTotemStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
GenericShamanStrategy::InitTriggers(triggers);
|
||||
// If the bot hasn't learned Windfury Totem yet, set Grounding Totem instead.
|
||||
Player* bot = botAI->GetBot();
|
||||
if (bot->HasSpell(SPELL_WINDFURY_TOTEM))
|
||||
if (bot->HasSpell(8512))
|
||||
triggers.push_back(new TriggerNode("set windfury totem", { NextAction("set windfury totem", 60.0f) }));
|
||||
else if (bot->HasSpell(SPELL_GROUNDING_TOTEM))
|
||||
else if (bot->HasSpell(8177))
|
||||
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) }));
|
||||
}
|
||||
|
||||
@ -77,7 +77,11 @@ bool CastShadowflameAction::isUseful()
|
||||
bool CastRainOfFireAction::isUseful()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
return target && !botAI->HasSpell("seed of corruption");
|
||||
if (!target)
|
||||
return false;
|
||||
if (bot->HasSpell(27243) || bot->HasSpell(47835) || bot->HasSpell(47836)) // Seed of Corruption spell IDs
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks if the enemies are close enough to use Hellfire
|
||||
|
||||
@ -104,8 +104,10 @@ bool LifeTapTrigger::IsActive()
|
||||
// Checks if the Life Tap Glyph buff is active
|
||||
bool LifeTapGlyphBuffTrigger::IsActive()
|
||||
{
|
||||
constexpr uint32 SPELL_LIFE_TAP_GLYPH = 63320;
|
||||
return bot->HasAura(SPELL_LIFE_TAP_GLYPH) && BuffTrigger::IsActive();
|
||||
if (!botAI->HasAura(63320, bot))
|
||||
return false;
|
||||
|
||||
return BuffTrigger::IsActive();
|
||||
}
|
||||
|
||||
// Checks if the target has a conflicting debuff that is equal to Curse of the Elements
|
||||
|
||||
@ -5,16 +5,23 @@
|
||||
|
||||
#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 (!target)
|
||||
if (!bot || !target)
|
||||
return PullStrategy::GetPullActionName();
|
||||
|
||||
if (botAI->CanCastSpell("heroic throw", target))
|
||||
uint32 const heroicThrowSpellId = botAI->GetAiObjectContext()->GetValue<uint32>("spell id", "heroic throw")->Get();
|
||||
if (heroicThrowSpellId && bot->HasSpell(heroicThrowSpellId) &&
|
||||
botAI->CanCastSpell(heroicThrowSpellId, target))
|
||||
{
|
||||
return "heroic throw";
|
||||
}
|
||||
|
||||
return PullStrategy::GetPullActionName();
|
||||
}
|
||||
|
||||
@ -8,15 +8,6 @@
|
||||
#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))
|
||||
@ -162,8 +153,14 @@ bool CastVigilanceAction::Execute(Event /*event*/)
|
||||
|
||||
bool CastRetaliationAction::isUseful()
|
||||
{
|
||||
if (!bot->HasSpell(SPELL_RETALIATION) || bot->HasSpellCooldown(SPELL_RETALIATION) ||
|
||||
bot->HasAura(SPELL_RETALIATION))
|
||||
// Spell cooldown check
|
||||
if (!bot->HasSpell(20230))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Spell cooldown check
|
||||
if (bot->HasSpellCooldown(20230))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -202,8 +199,8 @@ bool CastRetaliationAction::isUseful()
|
||||
break;
|
||||
}
|
||||
|
||||
// Only cast Retaliation if there are at least 2 melee attackers
|
||||
return meleeAttackers >= 2;
|
||||
// Only cast Retaliation if there are at least 2 melee attackers and the buff is not active
|
||||
return meleeAttackers >= 2 && !botAI->HasAura("retaliation", bot);
|
||||
}
|
||||
|
||||
Unit* CastShatteringThrowAction::GetTarget()
|
||||
@ -217,15 +214,15 @@ Unit* CastShatteringThrowAction::GetTarget()
|
||||
continue;
|
||||
|
||||
if (bot->IsWithinDistInMap(enemy, 25.0f) &&
|
||||
(enemy->HasAura(SPELL_DIVINE_SHIELD) ||
|
||||
enemy->HasAura(SPELL_ICE_BLOCK) ||
|
||||
enemy->HasAura(SPELL_BLESSING_OF_PROTECTION)))
|
||||
(enemy->HasAura(642) || // Divine Shield
|
||||
enemy->HasAura(45438) || // Ice Block
|
||||
enemy->HasAura(41450))) // Blessing of Protection
|
||||
{
|
||||
return enemy;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return nullptr; // No valid target
|
||||
}
|
||||
|
||||
bool CastShatteringThrowAction::Execute(Event /*event*/)
|
||||
@ -239,7 +236,7 @@ bool CastShatteringThrowAction::Execute(Event /*event*/)
|
||||
|
||||
bool CastShatteringThrowAction::isUseful()
|
||||
{
|
||||
if (!bot->HasSpell(SPELL_SHATTERING_THROW) || bot->HasSpellCooldown(SPELL_SHATTERING_THROW))
|
||||
if (!bot->HasSpell(64382) || bot->HasSpellCooldown(64382))
|
||||
return false;
|
||||
|
||||
GuidVector enemies = AI_VALUE(GuidVector, "possible targets");
|
||||
@ -250,16 +247,17 @@ 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(SPELL_DIVINE_SHIELD) ||
|
||||
enemy->HasAura(SPELL_ICE_BLOCK) ||
|
||||
enemy->HasAura(SPELL_BLESSING_OF_PROTECTION)))
|
||||
(enemy->HasAura(642) || // Divine Shield
|
||||
enemy->HasAura(45438) || // Ice Block
|
||||
enemy->HasAura(41450))) // Blessing of Protection
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false; // No valid targets within range
|
||||
}
|
||||
|
||||
bool CastShatteringThrowAction::isPossible()
|
||||
|
||||
@ -6,16 +6,6 @@
|
||||
#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 &&
|
||||
@ -24,7 +14,7 @@ bool BloodrageBuffTrigger::IsActive()
|
||||
|
||||
bool VigilanceTrigger::IsActive()
|
||||
{
|
||||
if (!bot->HasSpell(SPELL_VIGILANCE))
|
||||
if (!bot->HasSpell(50720))
|
||||
return false;
|
||||
|
||||
Group* group = bot->GetGroup();
|
||||
@ -74,7 +64,7 @@ bool VigilanceTrigger::IsActive()
|
||||
|
||||
bool ShatteringThrowTrigger::IsActive()
|
||||
{
|
||||
if (!bot->HasSpell(SPELL_SHATTERING_THROW) || bot->HasSpellCooldown(SPELL_SHATTERING_THROW))
|
||||
if (!bot->HasSpell(64382) || bot->HasSpellCooldown(64382))
|
||||
return false;
|
||||
|
||||
GuidVector enemies = AI_VALUE(GuidVector, "possible targets");
|
||||
@ -86,9 +76,9 @@ bool ShatteringThrowTrigger::IsActive()
|
||||
continue;
|
||||
|
||||
if (bot->IsWithinDistInMap(enemy, 25.0f) &&
|
||||
(enemy->HasAura(SPELL_DIVINE_SHIELD) ||
|
||||
enemy->HasAura(SPELL_ICE_BLOCK) ||
|
||||
enemy->HasAura(SPELL_BLESSING_OF_PROTECTION)))
|
||||
(enemy->HasAura(642) || // Divine Shield
|
||||
enemy->HasAura(45438) || // Ice Block
|
||||
enemy->HasAura(41450))) // Blessing of Protection
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -122,13 +112,15 @@ 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(SPELL_COMMANDING_PRESENCE_RANKS[rank]))
|
||||
if (bot->HasAura(commandingPresenceSpells[rank]))
|
||||
{
|
||||
cpBonus = commandingPresenceBonus[rank];
|
||||
break;
|
||||
|
||||
@ -5,13 +5,6 @@
|
||||
#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())
|
||||
@ -49,8 +42,7 @@ bool RazuviousUseObedienceCrystalAction::Execute(Event /*event*/)
|
||||
bool tauntUseful = true;
|
||||
if (forceObedience->GetDuration() <= (duration_time - 5000))
|
||||
{
|
||||
Unit* victim = target->GetVictim();
|
||||
if (victim && victim->HasAura(SPELL_BONE_BARRIER))
|
||||
if (target->GetVictim() && botAI->HasAura(29061, target->GetVictim()))
|
||||
tauntUseful = false;
|
||||
|
||||
if (forceObedience->GetDuration() <= 3000)
|
||||
@ -63,19 +55,19 @@ bool RazuviousUseObedienceCrystalAction::Execute(Event /*event*/)
|
||||
if (tauntUseful && !charm->HasSpellCooldown(29060))
|
||||
{
|
||||
// shield
|
||||
if (!charm->HasSpellCooldown(SPELL_BONE_BARRIER))
|
||||
if (!charm->HasSpellCooldown(29061))
|
||||
{
|
||||
charm->CastSpell(charm, SPELL_BONE_BARRIER, true);
|
||||
charm->AddSpellCooldown(SPELL_BONE_BARRIER, 0, 30 * 1000);
|
||||
charm->CastSpell(charm, 29061, true);
|
||||
charm->AddSpellCooldown(29061, 0, 30 * 1000);
|
||||
}
|
||||
charm->CastSpell(target, SPELL_UNDERSTUDY_TAUNT, true);
|
||||
charm->AddSpellCooldown(SPELL_UNDERSTUDY_TAUNT, 0, 20 * 1000);
|
||||
charm->CastSpell(target, 29060, true);
|
||||
charm->AddSpellCooldown(29060, 0, 20 * 1000);
|
||||
}
|
||||
// strike
|
||||
if (!charm->HasSpellCooldown(SPELL_BLOOD_STRIKE))
|
||||
if (!charm->HasSpellCooldown(61696))
|
||||
{
|
||||
charm->CastSpell(target, SPELL_BLOOD_STRIKE, true);
|
||||
charm->AddSpellCooldown(SPELL_BLOOD_STRIKE, 0, 4 * 1000);
|
||||
charm->CastSpell(target, 61696, true);
|
||||
charm->AddSpellCooldown(61696, 0, 4 * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ bool SapphironFlightPositionAction::MoveToNearestIcebolt()
|
||||
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
||||
{
|
||||
Player* member = ref->GetSource();
|
||||
if (NaxxSpellIds::HasAnyAura(member, {NaxxSpellIds::Icebolt10, NaxxSpellIds::Icebolt25}) ||
|
||||
if (NaxxSpellIds::HasAnyAura(botAI, member, {NaxxSpellIds::Icebolt10, NaxxSpellIds::Icebolt25}) ||
|
||||
botAI->HasAura("icebolt", member, false, false, -1, true))
|
||||
{
|
||||
if (!playerWithIcebolt || minDistance > bot->GetDistance(member))
|
||||
|
||||
@ -111,13 +111,15 @@ bool ThaddiusMovePolarityAction::Execute(Event /*event*/)
|
||||
{3504.68f, -2936.68f},
|
||||
};
|
||||
uint32 idx;
|
||||
if (NaxxSpellIds::HasAnyAura(bot,
|
||||
if (NaxxSpellIds::HasAnyAura(
|
||||
botAI, bot,
|
||||
{NaxxSpellIds::NegativeCharge10, NaxxSpellIds::NegativeCharge25, NaxxSpellIds::NegativeChargeStack}) ||
|
||||
botAI->HasAura("negative charge", bot, false, false, -1, true))
|
||||
{
|
||||
idx = 0;
|
||||
}
|
||||
else if (NaxxSpellIds::HasAnyAura(bot,
|
||||
else if (NaxxSpellIds::HasAnyAura(
|
||||
botAI, bot,
|
||||
{NaxxSpellIds::PositiveCharge10, NaxxSpellIds::PositiveCharge25, NaxxSpellIds::PositiveChargeStack}) ||
|
||||
botAI->HasAura("positive charge", bot, false, false, -1, true))
|
||||
{
|
||||
|
||||
@ -192,7 +192,7 @@ public:
|
||||
{
|
||||
Player* member = ref->GetSource();
|
||||
if (member &&
|
||||
(NaxxSpellIds::HasAnyAura(member, {NaxxSpellIds::Icebolt10, NaxxSpellIds::Icebolt25}) ||
|
||||
(NaxxSpellIds::HasAnyAura(botAI, member, {NaxxSpellIds::Icebolt10, NaxxSpellIds::Icebolt25}) ||
|
||||
botAI->HasAura("icebolt", member, false, false, -1, true)))
|
||||
{
|
||||
return true;
|
||||
|
||||
@ -236,7 +236,7 @@ float AnubrekhanGenericMultiplier::GetValue(Action* action)
|
||||
return 1.0f;
|
||||
|
||||
if (NaxxSpellIds::HasAnyAura(
|
||||
boss, {NaxxSpellIds::LocustSwarm10, NaxxSpellIds::LocustSwarm10Alt, NaxxSpellIds::LocustSwarm25}) ||
|
||||
botAI, boss, {NaxxSpellIds::LocustSwarm10, NaxxSpellIds::LocustSwarm10Alt, NaxxSpellIds::LocustSwarm25}) ||
|
||||
botAI->HasAura("locust swarm", boss))
|
||||
{
|
||||
if (dynamic_cast<FleeAction*>(action))
|
||||
|
||||
@ -123,14 +123,14 @@ namespace NaxxSpellIds
|
||||
SPELL_INEVITABLE_DOOM = 29204,
|
||||
SPELL_BERSERK = 26662
|
||||
*/
|
||||
inline bool HasAnyAura(Unit* unit, std::initializer_list<uint32> spellIds)
|
||||
inline bool HasAnyAura(PlayerbotAI* botAI, Unit* unit, std::initializer_list<uint32> spellIds)
|
||||
{
|
||||
if (!unit)
|
||||
if (!botAI || !unit)
|
||||
return false;
|
||||
|
||||
for (uint32 spellId : spellIds)
|
||||
{
|
||||
if (unit->HasAura(spellId))
|
||||
if (botAI->HasAura(spellId, unit))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -1531,7 +1531,7 @@ bool VezaxShadowCrashTrigger::IsActive()
|
||||
if (!boss || !boss->IsAlive())
|
||||
return false;
|
||||
|
||||
return bot->HasAura(SPELL_VEZAX_SHADOW_CRASH);
|
||||
return botAI->HasAura(SPELL_VEZAX_SHADOW_CRASH, bot);
|
||||
}
|
||||
|
||||
bool VezaxMarkOfTheFacelessTrigger::IsActive()
|
||||
@ -1542,7 +1542,7 @@ bool VezaxMarkOfTheFacelessTrigger::IsActive()
|
||||
if (!boss || !boss->IsAlive())
|
||||
return false;
|
||||
|
||||
if (!bot->HasAura(SPELL_MARK_OF_THE_FACELESS))
|
||||
if (!botAI->HasAura(SPELL_MARK_OF_THE_FACELESS, bot))
|
||||
return false;
|
||||
|
||||
float distance = bot->GetDistance2d(ULDUAR_VEZAX_MARK_OF_THE_FACELESS_SPOT.GetPositionX(),
|
||||
|
||||
@ -26,15 +26,6 @@
|
||||
#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())
|
||||
@ -309,7 +300,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
||||
engine->addStrategiesNoInit("arcane", "bdps", nullptr);
|
||||
else if (tab == MAGE_TAB_FIRE)
|
||||
{
|
||||
if (player->HasSpell(SPELL_FROSTFIRE_BOLT) && player->HasAura(SPELL_ICE_SHARDS))
|
||||
if (player->HasSpell(44614) /*Frostfire Bolt*/ && player->HasAura(15047) /*Ice Shards*/)
|
||||
engine->addStrategiesNoInit("frostfire", "bdps", nullptr);
|
||||
else
|
||||
engine->addStrategiesNoInit("fire", "bdps", nullptr);
|
||||
@ -322,7 +313,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(SPELL_WHIRLWIND))
|
||||
else if (tab == WARRIOR_TAB_ARMS || !player->HasSpell(1680)) // Whirlwind
|
||||
engine->addStrategiesNoInit("arms", "aoe", "dps assist", nullptr);
|
||||
else // if (tab == WARRIOR_TAB_FURY)
|
||||
engine->addStrategiesNoInit("fury", "aoe", "dps assist", nullptr);
|
||||
@ -354,7 +345,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
||||
engine->addStrategiesNoInit("resto", "cure", "dps assist", "blanketing", "tranquility", nullptr);
|
||||
else
|
||||
{
|
||||
if (player->HasSpell(SPELL_CAT_FORM) && !player->HasAura(SPELL_DRUID_THICK_HIDE))
|
||||
if (player->HasSpell(768) /*cat form*/ && !player->HasAura(16931) /*thick hide*/)
|
||||
engine->addStrategiesNoInit("cat", "aoe", "cc", "dps assist", "feral charge", nullptr);
|
||||
else
|
||||
engine->addStrategiesNoInit("bear", "tank assist", "pull", "pull back", "feral charge", nullptr);
|
||||
@ -544,7 +535,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
|
||||
case CLASS_DRUID:
|
||||
if (tab == DRUID_TAB_FERAL)
|
||||
{
|
||||
if (player->GetLevel() >= 20 && !player->HasAura(SPELL_DRUID_THICK_HIDE))
|
||||
if (player->GetLevel() >= 20 && !player->HasAura(16931) /*thick hide*/)
|
||||
nonCombatEngine->addStrategy("dps assist", false);
|
||||
else
|
||||
nonCombatEngine->addStrategiesNoInit("tank assist", "pull", nullptr);
|
||||
|
||||
@ -61,56 +61,6 @@ std::vector<uint32> PlayerbotFactory::enchantGemIdCache;
|
||||
std::unordered_map<uint32, std::vector<uint32>> PlayerbotFactory::trainerIdCache;
|
||||
std::vector<uint32> 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);
|
||||
@ -1490,7 +1440,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(SPELL_DRUID_THICK_HIDE);
|
||||
bool isCat = !bot->HasAura(16931);
|
||||
if (!isCat && bot->GetLevel() == 20)
|
||||
{
|
||||
uint32 bearP = sPlayerbotAIConfig.randomClassSpecProb[cls][1];
|
||||
@ -1545,7 +1495,7 @@ uint32 PlayerbotFactory::InitTalentsTree(bool increment /*false*/, bool use_temp
|
||||
if (bot->GetFreeTalentPoints())
|
||||
InitTalents((specTab + 2) % 3);
|
||||
|
||||
if (bot->getClass() == CLASS_SHAMAN && bot->HasSpell(SPELL_SHAMAN_DUAL_WIELD))
|
||||
if (bot->getClass() == CLASS_SHAMAN && bot->HasSpell(30798))
|
||||
{
|
||||
bot->SetSkill(SKILL_DUAL_WIELD, 0, 1, 1);
|
||||
bot->SetCanDualWield(true);
|
||||
@ -1631,7 +1581,7 @@ void PlayerbotFactory::InitTalentsBySpecNo(Player* bot, int specNo, bool reset)
|
||||
}
|
||||
}
|
||||
|
||||
if (bot->getClass() == CLASS_SHAMAN && bot->HasSpell(SPELL_SHAMAN_DUAL_WIELD))
|
||||
if (bot->getClass() == CLASS_SHAMAN && bot->HasSpell(30798))
|
||||
{
|
||||
bot->SetSkill(SKILL_DUAL_WIELD, 0, 1, 1);
|
||||
bot->SetCanDualWield(true);
|
||||
@ -4220,13 +4170,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(SPELL_SECOND_WIND))
|
||||
if (bot->HasAura(29838))
|
||||
tab = 3;
|
||||
// Fury PvP (spec index 4): If the bot has the Blood Craze talent
|
||||
else if (bot->HasAura(SPELL_BLOOD_CRAZE))
|
||||
else if (bot->HasAura(16492))
|
||||
tab = 4;
|
||||
// Protection PvP (spec index 5): If the bot has the Gag Order talent
|
||||
else if (bot->HasAura(SPELL_GAG_ORDER))
|
||||
else if (bot->HasAura(12958))
|
||||
tab = 5;
|
||||
}
|
||||
|
||||
@ -4234,13 +4184,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(SPELL_SACRED_CLEANSING))
|
||||
if (bot->HasAura(53553))
|
||||
tab = 3;
|
||||
// Protection PvP (spec index 4): If the bot has the Reckoning talent
|
||||
else if (bot->HasAura(SPELL_RECKONING))
|
||||
else if (bot->HasAura(20179))
|
||||
tab = 4;
|
||||
// Retribution PvP (spec index 5): If the bot has the Divine Purpose talent
|
||||
else if (bot->HasAura(SPELL_DIVINE_PURPOSE))
|
||||
else if (bot->HasAura(31872))
|
||||
tab = 5;
|
||||
}
|
||||
|
||||
@ -4248,13 +4198,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(SPELL_HUNTER_THICK_HIDE))
|
||||
if (bot->HasAura(19612))
|
||||
tab = 3;
|
||||
// Marksmanship PvP (spec index 4): If the bot has the Concussive Barrage talent
|
||||
else if (bot->HasAura(SPELL_CONCUSSIVE_BARRAGE))
|
||||
else if (bot->HasAura(35102))
|
||||
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(SPELL_ENTRAPMENT) && !bot->HasAura(SPELL_CONCUSSIVE_BARRAGE))
|
||||
else if (bot->HasAura(19388) && !bot->HasAura(35102))
|
||||
tab = 5;
|
||||
}
|
||||
|
||||
@ -4262,13 +4212,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(SPELL_DEADLY_BREW))
|
||||
if (bot->HasAura(51626))
|
||||
tab = 3;
|
||||
// Combat PvP (spec index 4): If the bot has the Throwing Specialization talent
|
||||
else if (bot->HasAura(SPELL_THROWING_SPECIALIZATION))
|
||||
else if (bot->HasAura(51679))
|
||||
tab = 4;
|
||||
// Subtlety PvP (spec index 5): If the bot has the Waylay talent
|
||||
else if (bot->HasAura(SPELL_WAYLAY))
|
||||
else if (bot->HasAura(51696))
|
||||
tab = 5;
|
||||
}
|
||||
|
||||
@ -4276,13 +4226,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(SPELL_IMPROVED_MANA_BURN))
|
||||
if (bot->HasAura(14772))
|
||||
tab = 3;
|
||||
// Holy PvP (spec index 4): If the bot has the Body and Soul talent
|
||||
else if (bot->HasAura(SPELL_BODY_AND_SOUL))
|
||||
else if (bot->HasAura(64129))
|
||||
tab = 4;
|
||||
// Shadow PvP (spec index 5): If the bot has the Improved Vampiric Embrace talent
|
||||
else if (bot->HasAura(SPELL_IMPROVED_VAMPIRIC_EMBRACE))
|
||||
else if (bot->HasAura(27840))
|
||||
tab = 5;
|
||||
}
|
||||
|
||||
@ -4291,16 +4241,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(SPELL_ABOMINATIONS_MIGHT) && bot->HasAura(SPELL_IMPROVED_ICY_TALONS))
|
||||
if (bot->HasAura(53138) && bot->HasAura(55610))
|
||||
tab = 3;
|
||||
// Blood PvP (spec index 4): If the bot has the Sudden Doom talent
|
||||
else if (bot->HasAura(SPELL_SUDDEN_DOOM))
|
||||
else if (bot->HasAura(49529))
|
||||
tab = 4;
|
||||
// Frost PvP (spec index 5): If the bot has the Acclimation talent
|
||||
else if (bot->HasAura(SPELL_ACCLIMATION))
|
||||
else if (bot->HasAura(50152))
|
||||
tab = 5;
|
||||
// Unholy PvP (spec index 6): If the bot has the Magic Suppression talent
|
||||
else if (bot->HasAura(SPELL_MAGIC_SUPPRESSION))
|
||||
else if (bot->HasAura(49611))
|
||||
tab = 6;
|
||||
}
|
||||
|
||||
@ -4308,13 +4258,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(SPELL_ASTRAL_SHIFT))
|
||||
if (bot->HasAura(51479))
|
||||
tab = 3;
|
||||
// Enhancement PvP (spec index 4): If the bot has the Earthen Power talent
|
||||
else if (bot->HasAura(SPELL_EARTHEN_POWER))
|
||||
else if (bot->HasAura(51524))
|
||||
tab = 4;
|
||||
// Restoration PvP (spec index 5): If the bot has the Focused Mind talent
|
||||
else if (bot->HasAura(SPELL_FOCUSED_MIND))
|
||||
else if (bot->HasAura(30866))
|
||||
tab = 5;
|
||||
}
|
||||
|
||||
@ -4322,16 +4272,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(SPELL_BURNOUT) && bot->HasAura(SPELL_ICE_SHARDS))
|
||||
if (bot->HasAura(44472) && bot->HasAura(15047))
|
||||
tab = 3;
|
||||
// Arcane PvP (spec index 4): If the bot has the Improved Blink talent
|
||||
else if (bot->HasAura(SPELL_IMPROVED_BLINK))
|
||||
else if (bot->HasAura(31570))
|
||||
tab = 4;
|
||||
// Fire PvP (spec index 5): If the bot has the Fiery Payback talent
|
||||
else if (bot->HasAura(SPELL_FIERY_PAYBACK))
|
||||
else if (bot->HasAura(64357))
|
||||
tab = 5;
|
||||
// Frost PvP (spec index 6): If the bot has the Shattered Barrier talent
|
||||
else if (bot->HasAura(SPELL_SHATTERED_BARRIER))
|
||||
else if (bot->HasAura(54787))
|
||||
tab = 6;
|
||||
}
|
||||
|
||||
@ -4339,13 +4289,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(SPELL_IMPROVED_HOWL_OF_TERROR))
|
||||
if (bot->HasAura(30057))
|
||||
tab = 3;
|
||||
// Demonology PvP (spec index 4): If the bot has both the Nemesis talent and the Intensity talent
|
||||
else if (bot->HasAura(SPELL_NEMESIS) && bot->HasAura(SPELL_INTENSITY))
|
||||
else if (bot->HasAura(63123) && bot->HasAura(18136))
|
||||
tab = 4;
|
||||
// Destruction PvP (spec index 5): If the bot has the Nether Protection talent
|
||||
else if (bot->HasAura(SPELL_NETHER_PROTECTION))
|
||||
else if (bot->HasAura(30302))
|
||||
tab = 5;
|
||||
}
|
||||
|
||||
@ -4353,16 +4303,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(SPELL_DRUID_THICK_HIDE))
|
||||
if (tab == DRUID_TAB_FERAL && bot->GetLevel() >= 20 && !bot->HasAura(16931))
|
||||
tab = 3;
|
||||
// Balance PvP (spec index 4): If the bot has the Owlkin Frenzy talent
|
||||
else if (bot->HasAura(SPELL_OWLKIN_FRENZY))
|
||||
else if (bot->HasAura(48393))
|
||||
tab = 4;
|
||||
// Feral PvP (spec index 5): If the bot has the Primal Tenacity talent
|
||||
else if (bot->HasAura(SPELL_PRIMAL_TENACITY))
|
||||
else if (bot->HasAura(33957))
|
||||
tab = 5;
|
||||
// Resto PvP (spec index 6): If the bot has the Improved Barkskin talent
|
||||
else if (bot->HasAura(SPELL_IMPROVED_BARKSKIN))
|
||||
else if (bot->HasAura(63411))
|
||||
tab = 6;
|
||||
}
|
||||
|
||||
|
||||
@ -3027,8 +3027,6 @@ bool PlayerbotAI::TellMaster(std::string const text, PlayerbotSecurityLevel secu
|
||||
{
|
||||
if (sPlayerbotAIConfig.randomBotSayWithoutMaster)
|
||||
return TellMasterNoFacing(text, securityLevel);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!TellMasterNoFacing(text, securityLevel))
|
||||
return false;
|
||||
@ -3152,10 +3150,20 @@ bool PlayerbotAI::HasAura(std::string const name, Unit* unit, bool maxStack, boo
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlayerbotAI::HasSpell(std::string const spellName) const
|
||||
bool PlayerbotAI::HasAura(uint32 spellId, Unit const* unit)
|
||||
{
|
||||
uint32 const spellId = aiObjectContext->GetValue<uint32>("spell id", spellName)->Get();
|
||||
return spellId && bot->HasSpell(spellId);
|
||||
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;
|
||||
}
|
||||
|
||||
Aura* PlayerbotAI::GetAura(std::string const name, Unit* unit, bool checkIsOwner, bool checkDuration, int checkStack)
|
||||
@ -4259,7 +4267,7 @@ void PlayerbotAI::InterruptSpell()
|
||||
void PlayerbotAI::RemoveAura(std::string const name)
|
||||
{
|
||||
uint32 spellid = aiObjectContext->GetValue<uint32>("spell id", name)->Get();
|
||||
if (spellid && bot->HasAura(spellid))
|
||||
if (spellid && HasAura(spellid, bot))
|
||||
bot->RemoveAurasDueToSpell(spellid);
|
||||
}
|
||||
|
||||
|
||||
@ -497,7 +497,6 @@ 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, ...);
|
||||
@ -510,6 +509,7 @@ 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);
|
||||
|
||||
@ -23,29 +23,13 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
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 <size_t Size>
|
||||
bool HasAnySpell(Player* player, uint32 const (&spellIds)[Size])
|
||||
{
|
||||
for (uint32 const spellId : spellIds)
|
||||
{
|
||||
if (player->HasSpell(spellId))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
|
||||
StatsWeightCalculator::StatsWeightCalculator(Player* player) : player_(player)
|
||||
@ -528,24 +512,26 @@ void StatsWeightCalculator::GenerateAdditionalWeights(Player* player)
|
||||
// int tab = AiFactory::GetPlayerSpecTab(player);
|
||||
if (cls == CLASS_HUNTER)
|
||||
{
|
||||
if (player->HasAura(SPELL_CAREFUL_AIM))
|
||||
if (player->HasAura(34484))
|
||||
stats_weights_[STATS_TYPE_INTELLECT] += 1.1f;
|
||||
if (player->HasAura(SPELL_HUNTER_VS_WILD))
|
||||
if (player->HasAura(56341))
|
||||
stats_weights_[STATS_TYPE_STAMINA] += 0.3f;
|
||||
}
|
||||
else if (cls == CLASS_WARRIOR)
|
||||
{
|
||||
if (player->HasAura(SPELL_ARMORED_TO_THE_TEETH))
|
||||
if (player->HasAura(61222))
|
||||
stats_weights_[STATS_TYPE_ARMOR] += 0.03f;
|
||||
}
|
||||
else if (cls == CLASS_SHAMAN)
|
||||
{
|
||||
if (player->HasAura(SPELL_MENTAL_DEXTERITY))
|
||||
if (player->HasAura(51885))
|
||||
stats_weights_[STATS_TYPE_INTELLECT] += 1.1f;
|
||||
}
|
||||
else if (cls == CLASS_MAGE)
|
||||
{
|
||||
if (!HasAnySpell(player, SPELL_MOLTEN_ARMOR_RANKS))
|
||||
if (!player->HasSpell(SPELL_MOLTEN_ARMOR_RANK_1)
|
||||
&& !player->HasSpell(SPELL_MOLTEN_ARMOR_RANK_2)
|
||||
&& !player->HasSpell(SPELL_MOLTEN_ARMOR_RANK_3))
|
||||
{
|
||||
if (tab != MAGE_TAB_FIRE)
|
||||
stats_weights_[STATS_TYPE_SPIRIT] -= 0.6f;
|
||||
@ -555,7 +541,8 @@ void StatsWeightCalculator::GenerateAdditionalWeights(Player* player)
|
||||
}
|
||||
else if (cls == CLASS_WARLOCK)
|
||||
{
|
||||
if (!HasAnySpell(player, SPELL_FEL_ARMOR_RANKS))
|
||||
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))
|
||||
stats_weights_[STATS_TYPE_SPIRIT] -= 0.4f;
|
||||
}
|
||||
|
||||
@ -703,17 +690,17 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto)
|
||||
weight_ *= 1.5;
|
||||
}
|
||||
|
||||
if (cls == CLASS_ROGUE && player_->HasAura(SPELL_ROGUE_SWORD_SPECIALIZATION) &&
|
||||
if (cls == CLASS_ROGUE && player_->HasAura(13964) &&
|
||||
(proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE))
|
||||
{
|
||||
weight_ *= 1.1;
|
||||
}
|
||||
if (cls == CLASS_WARRIOR && player_->HasAura(SPELL_POLEAXE_SPECIALIZATION) &&
|
||||
if (cls == CLASS_WARRIOR && player_->HasAura(12785) &&
|
||||
(proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2))
|
||||
{
|
||||
weight_ *= 1.1;
|
||||
}
|
||||
if (cls == CLASS_DEATH_KNIGHT && player_->HasAura(SPELL_NERVES_OF_COLD_STEEL) && !isDoubleHand)
|
||||
if (cls == CLASS_DEATH_KNIGHT && player_->HasAura(50138) && !isDoubleHand)
|
||||
{
|
||||
weight_ *= 1.3;
|
||||
}
|
||||
@ -752,9 +739,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(SPELL_SHADOW_FOCUS))
|
||||
if (cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW && player->HasAura(15835)) // Shadow Focus
|
||||
hit_current += 3;
|
||||
if (cls == CLASS_MAGE && tab == MAGE_TAB_ARCANE && player->HasAura(SPELL_ARCANE_FOCUS))
|
||||
if (cls == CLASS_MAGE && tab == MAGE_TAB_ARCANE && player->HasAura(12840)) // Arcane Focus
|
||||
hit_current += 3;
|
||||
|
||||
hit_overflow = SPELL_HIT_OVERFLOW;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user