aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorQAston <qaston@gmail.com>2012-02-19 00:40:22 +0100
committerQAston <qaston@gmail.com>2012-02-19 00:40:55 +0100
commit9abc47736f6def09041a067d07ef279c87a5c423 (patch)
tree7959df6cb7eddfb27e2312b54a07f7fe95efb745 /src
parentde823937b715c638b210ad526d069b90966f03f9 (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-xsrc/server/game/Entities/Unit/Unit.cpp61
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h3
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp40
-rwxr-xr-xsrc/server/game/Spells/Spell.h1
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);