Core/Spells: Changes in code related to spell explicit target redirection (cleanups, added target validation, prevent unexpected behaviour in some cases)

This commit is contained in:
QAston
2012-02-19 00:40:55 +01:00
parent de823937b7
commit 9abc47736f
4 changed files with 64 additions and 41 deletions
+15 -16
View File
@@ -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)
{
if (!victim)
return NULL;
// Magic case
if (spellInfo && (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE || spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC))
Unit* Unit::GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo)
{
// 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;
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))
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;
}
}
// Melee && ranged case
else
return victim;
}
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 (magnet->isAlive() && magnet->IsWithinLOSInMap(this))
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()))
{
(*i)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE);
return magnet;
}
}
return victim;
}
+2 -1
View File
@@ -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);
+31 -9
View File
@@ -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:
+1
View File
@@ -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);