diff options
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 99 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 2 |
2 files changed, 54 insertions, 47 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index e83c236ad69..f59e27da9c1 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -753,10 +753,53 @@ void Spell::SelectSpellTargets() if (implicitTargetMask & (TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM)) m_targets.SetTargetFlag(TARGET_FLAG_GAMEOBJECT); - uint32 currentlyProcessedEffectMask = processedEffectsMaskForSpell; - SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetA, processedEffectsMaskForSpell); - SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetB, processedEffectsMaskForSpell); - currentlyProcessedEffectMask = processedEffectsMaskForSpell & ~currentlyProcessedEffectMask; + uint32 implicitTargetEffectMaskToSelect = [&] + { + uint32 effectMask = 1u << spellEffectInfo.EffectIndex; + // set the same target list for all effects + // some spells appear to need this, however this requires more research + std::array<SpellEffectInfo, MAX_SPELL_EFFECTS> const& effects = GetSpellInfo()->GetEffects(); + // choose which targets we can select at once + for (uint32 j = spellEffectInfo.EffectIndex + 1; j < effects.size(); ++j) + { + if (effects[j].IsEffect() && + spellEffectInfo.TargetA.GetTarget() == effects[j].TargetA.GetTarget() && + spellEffectInfo.TargetB.GetTarget() == effects[j].TargetB.GetTarget() && + spellEffectInfo.ImplicitTargetConditions == effects[j].ImplicitTargetConditions && + CheckScriptEffectImplicitTargets(spellEffectInfo.EffectIndex, j)) + { + auto shouldCheckRadius = [](SpellImplicitTargetInfo const& targetInfo) + { + switch (targetInfo.GetSelectionCategory()) + { + case TARGET_SELECT_CATEGORY_NEARBY: + case TARGET_SELECT_CATEGORY_CONE: + case TARGET_SELECT_CATEGORY_AREA: + return true; + default: + break; + } + return false; + }; + + if (shouldCheckRadius(spellEffectInfo.TargetA) || shouldCheckRadius(spellEffectInfo.TargetB)) + if (spellEffectInfo.CalcRadius(m_caster) != effects[j].CalcRadius(m_caster)) + continue; + + effectMask |= 1 << j; + } + } + + return effectMask; + }(); + + implicitTargetEffectMaskToSelect &= ~processedEffectsMaskForSpell; + if (implicitTargetEffectMaskToSelect) + { + SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetA, implicitTargetEffectMaskToSelect); + SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetB, implicitTargetEffectMaskToSelect); + processedEffectsMaskForSpell |= implicitTargetEffectMaskToSelect; + } // Select targets of effect based on effect type // those are used when no valid target could be added for spell effect based on spell target type @@ -768,7 +811,7 @@ void Spell::SelectSpellTargets() if (m_targets.HasDst()) AddDestTarget(*m_targets.GetDst(), spellEffectInfo.EffectIndex); - if (currentlyProcessedEffectMask + if (implicitTargetEffectMaskToSelect && (spellEffectInfo.TargetA.GetObjectType() == TARGET_OBJECT_TYPE_UNIT || spellEffectInfo.TargetA.GetObjectType() == TARGET_OBJECT_TYPE_UNIT_AND_DEST || spellEffectInfo.TargetB.GetObjectType() == TARGET_OBJECT_TYPE_UNIT @@ -776,9 +819,9 @@ void Spell::SelectSpellTargets() { if (m_spellInfo->HasAttribute(SPELL_ATTR1_REQUIRE_ALL_TARGETS)) { - bool noTargetFound = std::ranges::none_of(m_UniqueTargetInfo, [currentlyProcessedEffectMask](TargetInfo const& target) + bool noTargetFound = std::ranges::none_of(m_UniqueTargetInfo, [implicitTargetEffectMaskToSelect](TargetInfo const& target) { - return target.EffectMask & currentlyProcessedEffectMask; + return target.EffectMask & implicitTargetEffectMaskToSelect; }); if (noTargetFound) @@ -790,9 +833,9 @@ void Spell::SelectSpellTargets() } if (m_spellInfo->HasAttribute(SPELL_ATTR2_FAIL_ON_ALL_TARGETS_IMMUNE)) { - bool anyNonImmuneTargetFound = std::ranges::any_of(m_UniqueTargetInfo, [currentlyProcessedEffectMask](TargetInfo const& target) + bool anyNonImmuneTargetFound = std::ranges::any_of(m_UniqueTargetInfo, [implicitTargetEffectMaskToSelect](TargetInfo const& target) { - return target.EffectMask & currentlyProcessedEffectMask && target.MissCondition != SPELL_MISS_IMMUNE && target.MissCondition != SPELL_MISS_IMMUNE2; + return target.EffectMask & implicitTargetEffectMaskToSelect && target.MissCondition != SPELL_MISS_IMMUNE && target.MissCondition != SPELL_MISS_IMMUNE2; }); if (!anyNonImmuneTargetFound) @@ -879,47 +922,11 @@ void Spell::RecalculateDelayMomentForDst() m_caster->m_Events.ModifyEventTime(_spellEvent, Milliseconds(GetDelayStart() + m_delayMoment)); } -void Spell::SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask) +void Spell::SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effectMask) { if (!targetType.GetTarget()) return; - uint32 effectMask = 1 << spellEffectInfo.EffectIndex; - - // targets for effect already selected - if (effectMask & processedEffectMask) - return; - - // set the same target list for all effects - // some spells appear to need this, however this requires more research - std::array<SpellEffectInfo, MAX_SPELL_EFFECTS> const& effects = GetSpellInfo()->GetEffects(); - // choose which targets we can select at once - for (uint32 j = spellEffectInfo.EffectIndex + 1; j < effects.size(); ++j) - { - if (effects[j].IsEffect() && - spellEffectInfo.TargetA.GetTarget() == effects[j].TargetA.GetTarget() && - spellEffectInfo.TargetB.GetTarget() == effects[j].TargetB.GetTarget() && - spellEffectInfo.ImplicitTargetConditions == effects[j].ImplicitTargetConditions && - CheckScriptEffectImplicitTargets(spellEffectInfo.EffectIndex, j)) - { - switch (targetType.GetSelectionCategory()) - { - case TARGET_SELECT_CATEGORY_NEARBY: - case TARGET_SELECT_CATEGORY_CONE: - case TARGET_SELECT_CATEGORY_AREA: - if (spellEffectInfo.CalcRadius(m_caster) != effects[j].CalcRadius(m_caster)) - continue; - break; - default: - break; - } - - effectMask |= 1 << j; - } - } - - processedEffectMask |= effectMask; - switch (targetType.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_CHANNEL: diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 5f36ea02b85..496dd23e698 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -287,7 +287,7 @@ class TC_GAME_API Spell void SelectExplicitTargets(); void SelectSpellTargets(); - void SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask); + void SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effectMask); void SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask); void SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask); void SelectImplicitConeTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask); |