aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Spells/Spell.cpp108
-rw-r--r--src/server/game/Spells/Spell.h6
2 files changed, 60 insertions, 54 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 4694b85abaf..e83c236ad69 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -738,7 +738,7 @@ void Spell::SelectSpellTargets()
// select targets for cast phase
SelectExplicitTargets();
- uint32 processedAreaEffectsMask = 0;
+ uint32 processedEffectsMaskForSpell = 0;
for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects())
{
// not call for empty effect.
@@ -753,8 +753,10 @@ void Spell::SelectSpellTargets()
if (implicitTargetMask & (TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM))
m_targets.SetTargetFlag(TARGET_FLAG_GAMEOBJECT);
- SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetA, processedAreaEffectsMask);
- SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetB, processedAreaEffectsMask);
+ uint32 currentlyProcessedEffectMask = processedEffectsMaskForSpell;
+ SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetA, processedEffectsMaskForSpell);
+ SelectEffectImplicitTargets(spellEffectInfo, spellEffectInfo.TargetB, processedEffectsMaskForSpell);
+ currentlyProcessedEffectMask = processedEffectsMaskForSpell & ~currentlyProcessedEffectMask;
// 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
@@ -766,16 +768,17 @@ void Spell::SelectSpellTargets()
if (m_targets.HasDst())
AddDestTarget(*m_targets.GetDst(), spellEffectInfo.EffectIndex);
- if (spellEffectInfo.TargetA.GetObjectType() == TARGET_OBJECT_TYPE_UNIT
- || spellEffectInfo.TargetA.GetObjectType() == TARGET_OBJECT_TYPE_UNIT_AND_DEST
- || spellEffectInfo.TargetB.GetObjectType() == TARGET_OBJECT_TYPE_UNIT
- || spellEffectInfo.TargetB.GetObjectType() == TARGET_OBJECT_TYPE_UNIT_AND_DEST)
+ if (currentlyProcessedEffectMask
+ && (spellEffectInfo.TargetA.GetObjectType() == TARGET_OBJECT_TYPE_UNIT
+ || spellEffectInfo.TargetA.GetObjectType() == TARGET_OBJECT_TYPE_UNIT_AND_DEST
+ || spellEffectInfo.TargetB.GetObjectType() == TARGET_OBJECT_TYPE_UNIT
+ || spellEffectInfo.TargetB.GetObjectType() == TARGET_OBJECT_TYPE_UNIT_AND_DEST))
{
if (m_spellInfo->HasAttribute(SPELL_ATTR1_REQUIRE_ALL_TARGETS))
{
- bool noTargetFound = std::none_of(m_UniqueTargetInfo.begin(), m_UniqueTargetInfo.end(), [effectMask = 1u << spellEffectInfo.EffectIndex](TargetInfo const& target)
+ bool noTargetFound = std::ranges::none_of(m_UniqueTargetInfo, [currentlyProcessedEffectMask](TargetInfo const& target)
{
- return target.EffectMask & effectMask;
+ return target.EffectMask & currentlyProcessedEffectMask;
});
if (noTargetFound)
@@ -787,9 +790,9 @@ void Spell::SelectSpellTargets()
}
if (m_spellInfo->HasAttribute(SPELL_ATTR2_FAIL_ON_ALL_TARGETS_IMMUNE))
{
- bool anyNonImmuneTargetFound = std::any_of(m_UniqueTargetInfo.begin(), m_UniqueTargetInfo.end(), [effectMask = 1u << spellEffectInfo.EffectIndex](TargetInfo const& target)
+ bool anyNonImmuneTargetFound = std::ranges::any_of(m_UniqueTargetInfo, [currentlyProcessedEffectMask](TargetInfo const& target)
{
- return target.EffectMask & effectMask && target.MissCondition != SPELL_MISS_IMMUNE && target.MissCondition != SPELL_MISS_IMMUNE2;
+ return target.EffectMask & currentlyProcessedEffectMask && target.MissCondition != SPELL_MISS_IMMUNE && target.MissCondition != SPELL_MISS_IMMUNE2;
});
if (!anyNonImmuneTargetFound)
@@ -882,42 +885,45 @@ void Spell::SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo,
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
- switch (targetType.GetSelectionCategory())
- {
- case TARGET_SELECT_CATEGORY_NEARBY:
- case TARGET_SELECT_CATEGORY_CONE:
- case TARGET_SELECT_CATEGORY_AREA:
- {
- // targets for effect already selected
- if (effectMask & processedEffectMask)
- return;
- 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 &&
- spellEffectInfo.CalcRadius(m_caster) == effects[j].CalcRadius(m_caster) &&
- CheckScriptEffectImplicitTargets(spellEffectInfo.EffectIndex, j))
- {
- effectMask |= 1 << j;
- }
+ 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;
}
- processedEffectMask |= effectMask;
- break;
+
+ effectMask |= 1 << j;
}
- default:
- break;
}
+ processedEffectMask |= effectMask;
+
switch (targetType.GetSelectionCategory())
{
case TARGET_SELECT_CATEGORY_CHANNEL:
- SelectImplicitChannelTargets(spellEffectInfo, targetType);
+ SelectImplicitChannelTargets(spellEffectInfo, targetType, effectMask);
break;
case TARGET_SELECT_CATEGORY_NEARBY:
SelectImplicitNearbyTargets(spellEffectInfo, targetType, effectMask);
@@ -969,10 +975,10 @@ void Spell::SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo,
switch (targetType.GetReferenceType())
{
case TARGET_REFERENCE_TYPE_CASTER:
- SelectImplicitCasterObjectTargets(spellEffectInfo, targetType);
+ SelectImplicitCasterObjectTargets(spellEffectInfo, targetType, effectMask);
break;
case TARGET_REFERENCE_TYPE_TARGET:
- SelectImplicitTargetObjectTargets(spellEffectInfo, targetType);
+ SelectImplicitTargetObjectTargets(spellEffectInfo, targetType, effectMask);
break;
default:
ABORT_MSG("Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT");
@@ -990,7 +996,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo,
}
}
-void Spell::SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType)
+void Spell::SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask)
{
if (targetType.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER)
{
@@ -1012,7 +1018,7 @@ void Spell::SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo,
CallScriptObjectTargetSelectHandlers(target, spellEffectInfo.EffectIndex, targetType);
// unit target may be no longer avalible - teleported out of map for example
if (target && target->ToUnit())
- AddUnitTarget(target->ToUnit(), 1 << spellEffectInfo.EffectIndex);
+ AddUnitTarget(target->ToUnit(), effMask);
else
TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell target for spell ID {}, effect {}", m_spellInfo->Id, uint32(spellEffectInfo.EffectIndex));
break;
@@ -1511,7 +1517,7 @@ void Spell::SelectImplicitDestDestTargets(SpellEffectInfo const& spellEffectInfo
m_targets.ModDst(dest);
}
-void Spell::SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType)
+void Spell::SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask)
{
WorldObject* target = nullptr;
bool checkIfValid = true;
@@ -1559,13 +1565,13 @@ void Spell::SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffect
if (target)
{
if (Unit* unit = target->ToUnit())
- AddUnitTarget(unit, 1 << spellEffectInfo.EffectIndex, checkIfValid);
+ AddUnitTarget(unit, effMask, checkIfValid);
else if (GameObject* go = target->ToGameObject())
- AddGOTarget(go, 1 << spellEffectInfo.EffectIndex);
+ AddGOTarget(go, effMask);
}
}
-void Spell::SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType)
+void Spell::SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask)
{
ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!");
@@ -1576,17 +1582,17 @@ void Spell::SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffect
if (target)
{
if (Unit* unit = target->ToUnit())
- AddUnitTarget(unit, 1 << spellEffectInfo.EffectIndex, true, false);
+ AddUnitTarget(unit, effMask, true, false);
else if (GameObject* gobj = target->ToGameObject())
- AddGOTarget(gobj, 1 << spellEffectInfo.EffectIndex);
+ AddGOTarget(gobj, effMask);
else if (Corpse* corpse = target->ToCorpse())
- AddCorpseTarget(corpse, 1 << spellEffectInfo.EffectIndex);
+ AddCorpseTarget(corpse, effMask);
- SelectImplicitChainTargets(spellEffectInfo, targetType, target, 1 << spellEffectInfo.EffectIndex);
+ SelectImplicitChainTargets(spellEffectInfo, targetType, target, effMask);
}
// Script hook can remove object target and we would wrongly land here
else if (Item* item = m_targets.GetItemTarget())
- AddItemTarget(item, 1 << spellEffectInfo.EffectIndex);
+ AddItemTarget(item, effMask);
}
void Spell::SelectImplicitChainTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask)
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 8dbcdd9ad7d..5f36ea02b85 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -288,15 +288,15 @@ class TC_GAME_API Spell
void SelectSpellTargets();
void SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask);
- void SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
+ 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);
void SelectImplicitAreaTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask);
void SelectImplicitCasterDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
void SelectImplicitTargetDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
void SelectImplicitDestDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
- void SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
- void SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);
+ void SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask);
+ void SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, uint32 effMask);
void SelectImplicitChainTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask);
void SelectImplicitTrajTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType);