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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user