From 95fa94af53eba3d272db070be999fe1f53dc2ab7 Mon Sep 17 00:00:00 2001 From: Yury Date: Fri, 3 Nov 2023 14:44:14 +0200 Subject: [PATCH] PetAI: Add basic conditions for some autocasted spells --- src/game/AI/BaseAI/PetAI.cpp | 51 +++++++++++++++++++++++++++++++++--- src/game/AI/BaseAI/PetAI.h | 1 + 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/game/AI/BaseAI/PetAI.cpp b/src/game/AI/BaseAI/PetAI.cpp index e0257d7c40..cb55064996 100644 --- a/src/game/AI/BaseAI/PetAI.cpp +++ b/src/game/AI/BaseAI/PetAI.cpp @@ -288,10 +288,10 @@ std::pair PetAI::PickSpellWithTarget(Unit* owner, Unit* victim, C Spell* spell = new Spell(m_unit, spellInfo, flags); - // Try to cast a spell on self if the spell allows only targeting self (like Lesser Invisibility and Blood Pact) + // Try to cast a spell on self if the spell allows only targeting self (Lesser Invisibility, Blood Pact) or AoE (Furious Howl, Thunderstomp) if (IsOnlySelfTargeting(spellInfo)) { - // Skip the spell in case it's already applied to self - if (!spell->CanAutoCast(m_unit)) + // Skip the spell in case it's already applied to self or doesn't meet specific conditions + if (!ShouldSelfCast(spellInfo, victim) || !spell->CanAutoCast(m_unit)) { delete spell; continue; @@ -304,6 +304,33 @@ std::pair PetAI::PickSpellWithTarget(Unit* owner, Unit* victim, C // don't require target but need to be targeted at specific victim for distance check. else if (victim && spell->CanAutoCast(victim)) return { victim, spell }; + // Try to cast a spell if the spell is AoE + else if (IsAreaOfEffectSpell(spellInfo)) + { + // If it's a harmful spell (Thunderstomp, Suffering) + if (!IsPositiveSpell(spellInfo->Id)) + { + // Keep spell until the victim is in melee range + if (!victim || !m_unit->CanReachWithMeleeAttack(victim)) + { + delete spell; + continue; + } + } + else + // If it's a positive spell (Furious Howl) + { + // Use it only in combat + if (!m_inCombat) + { + delete spell; + continue; + } + } + + // Target is not required for pet AoE spells + return { nullptr, spell }; + } // In all other cases, try to find a good use for the spell else { @@ -327,6 +354,24 @@ std::pair PetAI::PickSpellWithTarget(Unit* owner, Unit* victim, C return { nullptr, nullptr }; } +bool PetAI::ShouldSelfCast(SpellEntry const* spellInfo, Unit* victim) +{ + switch (spellInfo->Id) { + case 23145: // Dive Rank 1-3 + case 23147: + case 23148: + case 23099: // Dash Rank 1-3 + case 23109: + case 23110: + // Cast only when there is a victim and it is not within melee range + return victim && !m_unit->CanReachWithMeleeAttack(victim); + case 26064: // Shell Shield Rank 1 + // Cast only in combat and when HP is lower than 50% + return m_inCombat && m_unit->GetHealthPercent() < 50; + } + return true; +} + Player* PetAI::PickGroupMemberForSpell(Player* player, Spell* spell) { Group* group = player->GetGroup(); diff --git a/src/game/AI/BaseAI/PetAI.h b/src/game/AI/BaseAI/PetAI.h index 10fce1bcbf..054e110b96 100644 --- a/src/game/AI/BaseAI/PetAI.h +++ b/src/game/AI/BaseAI/PetAI.h @@ -50,6 +50,7 @@ class PetAI : public CreatureAI Player* PickGroupMemberForSpell(Player* player, Spell* spell); std::pair PickSpellWithTarget(Unit* owner, Unit* victim, CharmInfo* charminfo); void Cast(std::pair spellWithTarget); + bool ShouldSelfCast(SpellEntry const* spellInfo, Unit* victim); bool m_inCombat;