diff options
author | QAston <qaston@gmail.com> | 2012-02-19 00:40:22 +0100 |
---|---|---|
committer | QAston <qaston@gmail.com> | 2012-02-19 00:40:55 +0100 |
commit | 9abc47736f6def09041a067d07ef279c87a5c423 (patch) | |
tree | 7959df6cb7eddfb27e2312b54a07f7fe95efb745 /src | |
parent | de823937b715c638b210ad526d069b90966f03f9 (diff) |
Core/Spells: Changes in code related to spell explicit target redirection (cleanups, added target validation, prevent unexpected behaviour in some cases)
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 61 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.h | 3 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.cpp | 40 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.h | 1 |
4 files changed, 64 insertions, 41 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 91263882a8c..d4a702bd3cf 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1884,7 +1884,7 @@ void Unit::AttackerStateUpdate (Unit* victim, WeaponAttackType attType, bool ext else { // attack can be redirected to another target - victim = SelectMagnetTarget(victim); + victim = GetMeleeHitRedirectTarget(victim); CalcDamageInfo damageInfo; CalculateMeleeDamage(victim, 0, &damageInfo, attType); @@ -9988,44 +9988,43 @@ int32 Unit::DealHeal(Unit* victim, uint32 addhealth) return gain; } -Unit* Unit::SelectMagnetTarget(Unit* victim, SpellInfo const* spellInfo) +Unit* Unit::GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo) { - if (!victim) - return NULL; + // Patch 1.2 notes: Spell Reflection no longer reflects abilities + if (spellInfo->Attributes & SPELL_ATTR0_ABILITY || spellInfo->AttributesEx & SPELL_ATTR1_CANT_BE_REDIRECTED || spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY) + return victim; - // Magic case - if (spellInfo && (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE || spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC)) + Unit::AuraEffectList const& magnetAuras = victim->GetAuraEffectsByType(SPELL_AURA_SPELL_MAGNET); + for (Unit::AuraEffectList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr) { - // Patch 1.2 notes: Spell Reflection no longer reflects abilities - if (spellInfo->Attributes & SPELL_ATTR0_ABILITY || spellInfo->AttributesEx & SPELL_ATTR1_CANT_BE_REDIRECTED || spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY) - return victim; - // I am not sure if this should be redirected. - if (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE) - return victim; + if (Unit* magnet = (*itr)->GetBase()->GetUnitOwner()) + if (spellInfo->CheckExplicitTarget(this, magnet) == SPELL_CAST_OK + && spellInfo->CheckTarget(this, magnet, false) == SPELL_CAST_OK + && _IsValidAttackTarget(magnet, spellInfo) + && IsWithinLOSInMap(magnet)) + { + (*itr)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE); + return magnet; + } + } + return victim; +} - Unit::AuraEffectList const& magnetAuras = victim->GetAuraEffectsByType(SPELL_AURA_SPELL_MAGNET); - for (Unit::AuraEffectList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr) - if (Unit* magnet = (*itr)->GetBase()->GetUnitOwner()) - if (magnet->isAlive() && IsWithinLOSInMap(magnet)) +Unit* Unit::GetMeleeHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo) +{ + AuraEffectList const& hitTriggerAuras = victim->GetAuraEffectsByType(SPELL_AURA_ADD_CASTER_HIT_TRIGGER); + for (AuraEffectList::const_iterator i = hitTriggerAuras.begin(); i != hitTriggerAuras.end(); ++i) + { + if (Unit* magnet = (*i)->GetBase()->GetCaster()) + if (_IsValidAttackTarget(magnet, spellInfo) && magnet->IsWithinLOSInMap(this) + && (!spellInfo || (spellInfo->CheckExplicitTarget(this, magnet) == SPELL_CAST_OK + && spellInfo->CheckTarget(this, magnet, false) == SPELL_CAST_OK))) + if (roll_chance_i((*i)->GetAmount())) { - (*itr)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE); + (*i)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE); return magnet; } } - // Melee && ranged case - else - { - AuraEffectList const& hitTriggerAuras = victim->GetAuraEffectsByType(SPELL_AURA_ADD_CASTER_HIT_TRIGGER); - for (AuraEffectList::const_iterator i = hitTriggerAuras.begin(); i != hitTriggerAuras.end(); ++i) - if (Unit* magnet = (*i)->GetBase()->GetCaster()) - if (magnet->isAlive() && magnet->IsWithinLOSInMap(this)) - if (roll_chance_i((*i)->GetAmount())) - { - (*i)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE); - return magnet; - } - } - return victim; } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 423f83844d3..66b0bcbeb54 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -2008,7 +2008,8 @@ class Unit : public WorldObject uint32 BuildAuraStateUpdateForTarget(Unit* target) const; bool HasAuraState(AuraStateType flag, SpellInfo const* spellProto = NULL, Unit const* Caster = NULL) const ; void UnsummonAllTotems(); - Unit* SelectMagnetTarget(Unit* victim, SpellInfo const* spellInfo = NULL); + Unit* GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo); + Unit* GetMeleeHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo = NULL); int32 SpellBaseDamageBonus(SpellSchoolMask schoolMask); int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask); int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit* pVictim); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index cbfa739fb69..53356772ff6 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -674,8 +674,39 @@ void Spell::InitExplicitTargets(SpellCastTargets const& targets) m_targets.RemoveSrc(); } +void Spell::SelectExplicitTargets() +{ + // here go all explicit target changes made to explicit targets after spell prepare phase is finished + if (Unit* target = m_targets.GetUnitTarget()) + { + // check for explicit target redirection, for Grounding Totem for example + if (m_spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT_ENEMY + || (m_spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT && !m_spellInfo->IsPositive())) + { + Unit* redirect; + switch (m_spellInfo->DmgClass) + { + case SPELL_DAMAGE_CLASS_MAGIC: + redirect = m_caster->GetMagicHitRedirectTarget(target, m_spellInfo); + break; + case SPELL_DAMAGE_CLASS_MELEE: + case SPELL_DAMAGE_CLASS_RANGED: + redirect = m_caster->GetMeleeHitRedirectTarget(target, m_spellInfo); + break; + default: + redirect = NULL; + break; + } + if (redirect && (redirect != target)) + m_targets.SetUnitTarget(redirect); + } + } +} + void Spell::SelectSpellTargets() { + // select targets for cast phase + SelectExplicitTargets(); uint32 processedTargets = 0; for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { @@ -2079,16 +2110,7 @@ uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) switch (cur.GetTarget()) { case TARGET_UNIT_TARGET_ENEMY: - if (Unit* magnet = m_caster->SelectMagnetTarget(target, m_spellInfo)) - if (magnet != target) - m_targets.SetUnitTarget(magnet); - pushType = PUSH_CHAIN; - break; case TARGET_UNIT_TARGET_ANY: - if (!m_spellInfo->IsPositive()) - if (Unit* magnet = m_caster->SelectMagnetTarget(target, m_spellInfo)) - if (magnet != target) - m_targets.SetUnitTarget(magnet); pushType = PUSH_CHAIN; break; case TARGET_UNIT_TARGET_CHAINHEAL_ALLY: diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index b20ec345cce..583123eb261 100755 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -405,6 +405,7 @@ class Spell void WriteAmmoToPacket(WorldPacket* data); void InitExplicitTargets(SpellCastTargets const& targets); + void SelectExplicitTargets(); void SelectSpellTargets(); void SelectEffectTypeImplicitTargets(uint8 effIndex); uint32 SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur); |