diff options
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 6 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 33 |
2 files changed, 36 insertions, 3 deletions
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index d950b89122a..79561280d05 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1662,6 +1662,12 @@ class TC_GAME_API Unit : public WorldObject } void AddChannelObject(ObjectGuid guid) { AddDynamicUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ChannelObjects)) = guid; } void SetChannelObject(uint32 slot, ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ChannelObjects, slot), guid); } + void RemoveChannelObject(ObjectGuid guid) + { + int32 index = m_unitData->ChannelObjects.FindIndex(guid); + if (index >= 0) + RemoveDynamicUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ChannelObjects), index); + } void ClearChannelObjects() { ClearDynamicUpdateFieldValues(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ChannelObjects)); } void SetCurrentCastSpell(Spell* pSpell); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 988bd60921b..754e25011d7 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -992,7 +992,7 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa else { auto const& channelObjects = m_originalCaster->m_unitData->ChannelObjects; - WorldObject* target = channelObjects.size() > 0 ? ObjectAccessor::GetWorldObject(*m_caster, *channelObjects.begin()) : nullptr; + WorldObject* target = !channelObjects.empty() ? ObjectAccessor::GetWorldObject(*m_caster, *channelObjects.begin()) : nullptr; if (target) { CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); @@ -2883,7 +2883,10 @@ bool Spell::UpdateChanneledTargetList() Unit* unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); if (!unit) + { + m_caster->RemoveChannelObject(ihit->targetGUID); continue; + } if (IsValidDeadOrAliveTarget(unit)) { @@ -2895,11 +2898,15 @@ bool Spell::UpdateChanneledTargetList() { ihit->effectMask &= ~aurApp->GetEffectMask(); unit->RemoveAura(aurApp); + m_caster->RemoveChannelObject(ihit->targetGUID); continue; } } else // aura is dispelled + { + m_caster->RemoveChannelObject(ihit->targetGUID); continue; + } } channelTargetEffectMask &= ~ihit->effectMask; // remove from need alive mask effect that have alive target @@ -4509,9 +4516,28 @@ void Spell::SendChannelStart(uint32 duration) } m_timer = duration; + + uint32 channelAuraMask = 0; + uint32 explicitTargetEffectMask = 0xFFFFFFFF; + // if there is an explicit target, only add channel objects from effects that also hit ut + if (!m_targets.GetUnitTargetGUID().IsEmpty()) + { + auto explicitTargetItr = std::find_if(m_UniqueTargetInfo.begin(), m_UniqueTargetInfo.end(), [&](TargetInfo const& target) + { + return target.targetGUID == m_targets.GetUnitTargetGUID(); + }); + if (explicitTargetItr != m_UniqueTargetInfo.end()) + explicitTargetEffectMask = explicitTargetItr->effectMask; + } + + for (SpellEffectInfo const* effect : m_spellInfo->GetEffects()) + if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA && (explicitTargetEffectMask & (1u << effect->EffectIndex))) + channelAuraMask |= 1 << effect->EffectIndex; + for (TargetInfo const& target : m_UniqueTargetInfo) { - m_caster->AddChannelObject(target.targetGUID); + if (target.effectMask & channelAuraMask) + m_caster->AddChannelObject(target.targetGUID); if (m_UniqueTargetInfo.size() == 1 && m_UniqueGOTargetInfo.empty()) if(target.targetGUID != m_caster->GetGUID()) @@ -4521,7 +4547,8 @@ void Spell::SendChannelStart(uint32 duration) } for (GOTargetInfo const& target : m_UniqueGOTargetInfo) - m_caster->AddChannelObject(target.targetGUID); + if (target.effectMask & channelAuraMask) + m_caster->AddChannelObject(target.targetGUID); m_caster->SetChannelSpellId(m_spellInfo->Id); m_caster->SetChannelVisual(m_SpellVisual); |