diff options
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 37 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 9 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 34 |
3 files changed, 27 insertions, 53 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index ae0a2979fc7..d8d11fca1c9 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -3133,42 +3133,15 @@ void Creature::SetSpellFocus(Spell const* focusSpell, WorldObject const* target) _spellFocusInfo.Spell = focusSpell; bool const noTurnDuringCast = spellInfo->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST); + bool const turnDisabled = HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISABLE_TURN); // set target, then force send update packet to players if it changed to provide appropriate facing - ObjectGuid newTarget = target ? target->GetGUID() : ObjectGuid::Empty; + ObjectGuid newTarget = (target && !noTurnDuringCast && !turnDisabled) ? target->GetGUID() : ObjectGuid::Empty; if (GetGuidValue(UNIT_FIELD_TARGET) != newTarget) - { SetGuidValue(UNIT_FIELD_TARGET, newTarget); - if ( // here we determine if the (relatively expensive) forced update is worth it, or whether we can afford to wait until the scheduled update tick - ( // only require instant update for spells that actually have a visual - spellInfo->SpellVisual[0] || - spellInfo->SpellVisual[1] - ) && ( - !focusSpell->GetCastTime() || // if the spell is instant cast - noTurnDuringCast // client gets confused if we attempt to turn at the regularly scheduled update packet - ) - ) - { - std::vector<Player*> playersNearby; - GetPlayerListInGrid(playersNearby, GetVisibilityRange()); - for (Player* player : playersNearby) - { - // only update players that are known to the client (have already been created) - if (player->HaveAtClient(this)) - SendUpdateToPlayer(player); - } - } - } - - if (!HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISABLE_TURN)) - { - // Face the target - we need to do this before the unit state is modified for no-turn spells - if (target) - SetFacingToObject(target, false); - else if (noTurnDuringCast) - if (Unit* victim = GetVictim()) - SetFacingToObject(victim, false); // ensure orientation is correct at beginning of cast - } + // If we are not allowed to turn during cast but have a focus target, face the target + if (!turnDisabled && noTurnDuringCast && target) + SetFacingToObject(target, false); if (noTurnDuringCast) AddUnitState(UNIT_STATE_FOCUSING); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index b49f3b9b6df..cf6155a5874 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -868,6 +868,15 @@ void AuraEffect::PeriodicTick(AuraApplication* aurApp, Unit* caster) const Unit* target = aurApp->GetTarget(); + // Update serverside orientation of tracking channeled auras on periodic update ticks + if (caster && m_spellInfo->IsChanneled() && m_spellInfo->HasAttribute(SPELL_ATTR1_CHANNEL_TRACK_TARGET)) + { + ObjectGuid const channelGuid = caster->GetChannelObjectGuid(); + if (!channelGuid.IsEmpty() && channelGuid != caster->GetGUID()) + if (WorldObject const* objectTarget = ObjectAccessor::GetWorldObject(*caster, channelGuid)) + caster->SetInFront(objectTarget); + } + switch (GetAuraType()) { case SPELL_AURA_PERIODIC_DUMMY: diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 012d95132f7..ea34d8c2ddc 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3116,16 +3116,15 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const } } - // focus if not controlled creature - if (m_caster->GetTypeId() == TYPEID_UNIT && !m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_POSSESSED)) + // Creatures focus their target when possible + if (m_casttime && m_caster->IsCreature() && !m_spellInfo->IsNextMeleeSwingSpell() && !IsAutoRepeat() && !m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_POSSESSED)) { - if (!(m_spellInfo->IsNextMeleeSwingSpell() || IsAutoRepeat())) - { - if (m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget()) - m_caster->ToCreature()->SetSpellFocus(this, m_targets.GetObjectTarget()); - else if (m_spellInfo->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST)) - m_caster->ToCreature()->SetSpellFocus(this, nullptr); - } + // Channeled spells and some triggered spells do not focus a cast target. They face their target later on via channel object guid and via spell attribute or not at all + bool const focusTarget = !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_SET_FACING); + if (focusTarget && m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget()) + m_caster->ToCreature()->SetSpellFocus(this, m_targets.GetObjectTarget()); + else + m_caster->ToCreature()->SetSpellFocus(this, nullptr); } // set timer base at cast time @@ -3282,10 +3281,6 @@ void Spell::_cast(bool skipCheck) SetExecutedCurrently(true); - if (!(_triggeredCastFlags & TRIGGERED_IGNORE_SET_FACING)) - if (m_caster->GetTypeId() == TYPEID_UNIT && m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget()) - m_caster->ToCreature()->SetInFront(m_targets.GetObjectTarget()); - // Should this be done for original caster? Player* modOwner = m_caster->GetSpellModOwner(); if (modOwner) @@ -3368,13 +3363,10 @@ void Spell::_cast(bool skipCheck) } } } - - // if the spell allows the creature to turn while casting, then adjust server-side orientation to face the target now - // client-side orientation is handled by the client itself, as the cast target is targeted due to Creature::SetSpellFocusTarget - if (m_caster->GetTypeId() == TYPEID_UNIT && !m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_POSSESSED)) - if (!m_spellInfo->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST)) - if (WorldObject* objTarget = m_targets.GetObjectTarget()) - m_caster->ToCreature()->SetInFront(objTarget); + // The spell focusing is making sure that we have a valid cast target guid when we need it so only check for a guid value here. + if (Creature* creatureCaster = m_caster->ToCreature()) + if (!creatureCaster->GetTarget().IsEmpty() && !creatureCaster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_POSSESSED)) + creatureCaster->SetInFront(ObjectAccessor::GetUnit(*creatureCaster, creatureCaster->GetTarget())); SelectSpellTargets(); @@ -4615,7 +4607,7 @@ void Spell::SendChannelStart(uint32 duration) if (!unitCaster) return; - ObjectGuid channelTarget = m_targets.GetObjectTargetGUID(); + ObjectGuid channelTarget = m_targets.HasDst() ? unitCaster->GetGUID() : m_targets.GetObjectTargetGUID(); if (!channelTarget && !m_spellInfo->NeedsExplicitUnitTarget()) if (m_UniqueTargetInfo.size() + m_UniqueGOTargetInfo.size() == 1) // this is for TARGET_SELECT_CATEGORY_NEARBY channelTarget = !m_UniqueTargetInfo.empty() ? m_UniqueTargetInfo.front().TargetGUID : m_UniqueGOTargetInfo.front().TargetGUID; |