diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 96e4177d6ae..520f5bda9bd 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -279,6 +279,7 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) me->SetLastDamagedTime(0); me->SetCannotReachTarget(false); me->DoNotReacquireSpellFocusTarget(); + me->SetTarget(ObjectGuid::Empty); if (me->IsInEvadeMode()) return false; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index f066a019fa4..fc2df30d2b8 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2951,11 +2951,11 @@ void Creature::SetTarget(ObjectGuid guid) void Creature::SetSpellFocus(Spell const* focusSpell, WorldObject const* target) { - // already focused - if (_spellFocusInfo.spell) + // Pointer validation and checking for a already existing focus + if (_spellFocusInfo.spell || !focusSpell) return; - // Prevent dead/feigning death creatures from setting a focus target, so they won't turn + // Prevent dead / feign death creatures from setting a focus target if (!IsAlive() || HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH) || HasAuraType(SPELL_AURA_FEIGN_DEATH)) return; @@ -2973,7 +2973,8 @@ void Creature::SetSpellFocus(Spell const* focusSpell, WorldObject const* target) if (spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) return; - if ((!target || target == this) && !focusSpell->GetCastTime()) // instant cast, untargeted (or self-targeted) spell doesn't need any facing updates + // instant non-channeled casts and non-target spells don't need facing updates + if (!target && (!focusSpell->GetCastTime() && !spellInfo->IsChanneled())) return; // store pre-cast values for target and orientation (used to later restore) @@ -3072,12 +3073,11 @@ void Creature::ReleaseSpellFocus(Spell const* focusSpell, bool withDelay) void Creature::ReacquireSpellFocusTarget() { - if (!HasSpellFocus()) - return; + ASSERT(HasSpellFocus()); - SetTarget(_spellFocusInfo.target); + SetGuidValue(UNIT_FIELD_TARGET, _spellFocusInfo.target); - if (!HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISABLE_TURN) && !IsMovementPreventedByCasting()) + if (!HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISABLE_TURN)) { if (_spellFocusInfo.target) { @@ -3090,6 +3090,12 @@ void Creature::ReacquireSpellFocusTarget() _spellFocusInfo.delay = 0; } +void Creature::DoNotReacquireSpellFocusTarget() +{ + _spellFocusInfo.delay = 0; + _spellFocusInfo.spell = nullptr; +} + bool Creature::IsMovementPreventedByCasting() const { // first check if currently a movement allowed channel is active and we're not casting diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 1c18e11870a..52de4321118 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -328,7 +328,7 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma // Handling caster facing during spellcast void SetTarget(ObjectGuid guid) override; void ReacquireSpellFocusTarget(); - void DoNotReacquireSpellFocusTarget() { _spellFocusInfo.delay = 0; } + void DoNotReacquireSpellFocusTarget(); void SetSpellFocus(Spell const* focusSpell, WorldObject const* target); bool HasSpellFocus(Spell const* focusSpell = nullptr) const override; void ReleaseSpellFocus(Spell const* focusSpell = nullptr, bool withDelay = true); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 4b7bd132123..e2d5161ef68 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4679,6 +4679,10 @@ void Spell::SendChannelStart(uint32 duration) } } + // There must always be a caster + if (!channelTarget) + channelTarget = m_caster->GetGUID(); + uint32 castFlags = CAST_FLAG_HAS_TRAJECTORY; uint32 schoolImmunityMask = m_caster->GetSchoolImmunityMask(); uint32 mechanicImmunityMask = m_caster->GetMechanicImmunityMask(); @@ -4733,10 +4737,9 @@ void Spell::SendChannelStart(uint32 duration) { m_caster->SetChannelObjectGuid(channelTarget); - if (channelTarget != m_caster->GetGUID()) - if (Creature* creatureCaster = m_caster->ToCreature()) - if (!creatureCaster->HasSpellFocus(this)) - creatureCaster->SetSpellFocus(this, ObjectAccessor::GetWorldObject(*creatureCaster, channelTarget)); + if (Creature* creatureCaster = m_caster->ToCreature()) + if (!creatureCaster->HasSpellFocus(this)) + creatureCaster->SetSpellFocus(this, ObjectAccessor::GetWorldObject(*creatureCaster, channelTarget)); } m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL, m_spellInfo->Id);