diff options
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 4ba4c975c6e..6a5d1eb855e 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -920,6 +920,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffectInfo const& spellEffectInfo, spellEffectInfo.ImplicitTargetConditions == effects[j].ImplicitTargetConditions && spellEffectInfo.CalcRadius(m_caster, SpellTargetIndex::TargetA) == effects[j].CalcRadius(m_caster, SpellTargetIndex::TargetA) && spellEffectInfo.CalcRadius(m_caster, SpellTargetIndex::TargetB) == effects[j].CalcRadius(m_caster, SpellTargetIndex::TargetB) && + spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes::PlayersOnly) == effects[j].EffectAttributes.HasFlag(SpellEffectAttributes::PlayersOnly) && CheckScriptEffectImplicitTargets(spellEffectInfo.EffectIndex, j)) { effectMask |= 1 << j; @@ -1176,7 +1177,7 @@ void Spell::SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo, } } - WorldObject* target = SearchNearbyTarget(range, targetType.GetObjectType(), targetType.GetCheckType(), condList); + WorldObject* target = SearchNearbyTarget(spellEffectInfo, range, targetType.GetObjectType(), targetType.GetCheckType(), condList); float randomRadius = 0.0f; switch (targetType.GetTarget()) { @@ -1298,7 +1299,7 @@ void Spell::SelectImplicitConeTargets(SpellEffectInfo const& spellEffectInfo, Sp ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; float radius = spellEffectInfo.CalcRadius(m_caster, targetIndex) * m_spellValue->RadiusMod; - if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList)) + if (uint32 containerTypeMask = GetSearcherTypeMask(m_spellInfo, spellEffectInfo, objectType, condList)) { float extraSearchRadius = radius > 0.0f ? EXTRA_CELL_SEARCH_RADIUS : 0.0f; Trinity::WorldObjectSpellConeTargetCheck check(coneSrc, DegToRad(coneAngle), m_spellInfo->Width ? m_spellInfo->Width : m_caster->GetCombatReach(), radius, m_caster, m_spellInfo, selectionType, condList, objectType); @@ -1399,15 +1400,15 @@ void Spell::SelectImplicitAreaTargets(SpellEffectInfo const& spellEffectInfo, Sp if (!m_caster->IsUnit() || !m_caster->ToUnit()->IsInRaidWith(targetedUnit)) targets.push_back(m_targets.GetUnitTarget()); else - SearchAreaTargets(targets, radius, targetedUnit, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions); + SearchAreaTargets(targets, spellEffectInfo, radius, targetedUnit, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions); } break; case TARGET_UNIT_CASTER_AND_SUMMONS: targets.push_back(m_caster); - SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions); + SearchAreaTargets(targets, spellEffectInfo, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions); break; default: - SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions); + SearchAreaTargets(targets, spellEffectInfo, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), spellEffectInfo.ImplicitTargetConditions); break; } @@ -1958,7 +1959,7 @@ void Spell::SelectImplicitLineTargets(SpellEffectInfo const& spellEffectInfo, Sp ConditionContainer* condList = spellEffectInfo.ImplicitTargetConditions; float radius = spellEffectInfo.CalcRadius(m_caster, targetIndex) * m_spellValue->RadiusMod; - if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList)) + if (uint32 containerTypeMask = GetSearcherTypeMask(m_spellInfo, spellEffectInfo, objectType, condList)) { Trinity::WorldObjectSpellLineTargetCheck check(m_caster, dst, m_spellInfo->Width ? m_spellInfo->Width : m_caster->GetCombatReach(), radius, m_caster, m_spellInfo, selectionType, condList, objectType); Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellLineTargetCheck> searcher(m_caster, targets, check, containerTypeMask); @@ -2091,7 +2092,7 @@ void Spell::SelectEffectTypeImplicitTargets(SpellEffectInfo const& spellEffectIn } } -uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionContainer* condList) +uint32 Spell::GetSearcherTypeMask(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, SpellTargetObjectTypes objType, ConditionContainer const* condList) { // this function selects which containers need to be searched for spell target uint32 retMask = GRID_MAP_TYPE_MASK_ALL; @@ -2116,11 +2117,11 @@ uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionConta break; } - if (m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER)) + if (spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER) || spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes::PlayersOnly)) retMask &= GRID_MAP_TYPE_MASK_CORPSE | GRID_MAP_TYPE_MASK_PLAYER; - if (m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_GHOSTS)) + if (spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_GHOSTS)) retMask &= GRID_MAP_TYPE_MASK_PLAYER; - if (m_spellInfo->HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER)) + if (spellInfo->HasAttribute(SPELL_ATTR5_NOT_ON_PLAYER)) retMask &= ~GRID_MAP_TYPE_MASK_PLAYER; if (condList) @@ -2157,10 +2158,10 @@ void Spell::SearchTargets(SEARCHER& searcher, uint32 containerMask, WorldObject* } } -WorldObject* Spell::SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer* condList) +WorldObject* Spell::SearchNearbyTarget(SpellEffectInfo const& spellEffectInfo, float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer const* condList) { WorldObject* target = nullptr; - uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList); + uint32 containerTypeMask = GetSearcherTypeMask(m_spellInfo, spellEffectInfo, objectType, condList); if (!containerTypeMask) return nullptr; @@ -2171,9 +2172,9 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargetObjectTypes objec return target; } -void Spell::SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, WorldObject* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer* condList) +void Spell::SearchAreaTargets(std::list<WorldObject*>& targets, SpellEffectInfo const& spellEffectInfo, float range, Position const* position, WorldObject* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer const* condList) { - uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList); + uint32 containerTypeMask = GetSearcherTypeMask(m_spellInfo, spellEffectInfo, objectType, condList); if (!containerTypeMask) return; @@ -2226,7 +2227,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar WorldObject* chainSource = m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER) ? m_caster : target; std::list<WorldObject*> tempTargets; - SearchAreaTargets(tempTargets, searchRadius, chainSource, m_caster, objectType, selectType, spellEffectInfo.ImplicitTargetConditions); + SearchAreaTargets(tempTargets, spellEffectInfo, searchRadius, chainSource, m_caster, objectType, selectType, spellEffectInfo.ImplicitTargetConditions); tempTargets.remove(target); // remove targets which are always invalid for chain spells @@ -2265,13 +2266,17 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar { for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr) { - if (foundItr == tempTargets.end()) - { - if (chainSource->IsWithinDist(*itr, jumpRadius) && IsWithinLOS(chainSource, *itr, false, VMAP::ModelIgnoreFlags::M2)) - foundItr = itr; - } - else if (chainSource->GetDistanceOrder(*itr, *foundItr) && IsWithinLOS(chainSource, *itr, false, VMAP::ModelIgnoreFlags::M2)) - foundItr = itr; + bool isBestDistanceMatch = foundItr != tempTargets.end() ? chainSource->GetDistanceOrder(*itr, *foundItr) : chainSource->IsWithinDist(*itr, jumpRadius); + if (!isBestDistanceMatch) + continue; + + if (!IsWithinLOS(chainSource, *itr, false, VMAP::ModelIgnoreFlags::M2)) + continue; + + if (spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes::EnforceLineOfSightToChainTargets) && !IsWithinLOS(m_caster, *itr, false, VMAP::ModelIgnoreFlags::M2)) + continue; + + foundItr = itr; } } // not found any valid target - chain ends @@ -7991,7 +7996,7 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const& spellEf } default: { - if (!losPosition || m_spellInfo->HasAttribute(SPELL_ATTR5_ALWAYS_AOE_LINE_OF_SIGHT)) + if (!losPosition || m_spellInfo->HasAttribute(SPELL_ATTR5_ALWAYS_AOE_LINE_OF_SIGHT) || spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes::AlwaysAoeLineOfSight)) { // Get GO cast coordinates if original caster -> GO WorldObject* caster = nullptr; |
