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
|
else
|
||||||
{
|
{
|
||||||
// attack can be redirected to another target
|
// attack can be redirected to another target
|
||||||
victim = SelectMagnetTarget(victim);
|
victim = GetMeleeHitRedirectTarget(victim);
|
||||||
|
|
||||||
CalcDamageInfo damageInfo;
|
CalcDamageInfo damageInfo;
|
||||||
CalculateMeleeDamage(victim, 0, &damageInfo, attType);
|
CalculateMeleeDamage(victim, 0, &damageInfo, attType);
|
||||||
@@ -9988,44 +9988,43 @@ int32 Unit::DealHeal(Unit* victim, uint32 addhealth)
|
|||||||
return gain;
|
return gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
Unit* Unit::SelectMagnetTarget(Unit* victim, SpellInfo const* spellInfo)
|
Unit* Unit::GetMagicHitRedirectTarget(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))
|
|
||||||
{
|
{
|
||||||
// Patch 1.2 notes: Spell Reflection no longer reflects abilities
|
// 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)
|
if (spellInfo->Attributes & SPELL_ATTR0_ABILITY || spellInfo->AttributesEx & SPELL_ATTR1_CANT_BE_REDIRECTED || spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)
|
||||||
return victim;
|
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);
|
Unit::AuraEffectList const& magnetAuras = victim->GetAuraEffectsByType(SPELL_AURA_SPELL_MAGNET);
|
||||||
for (Unit::AuraEffectList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr)
|
for (Unit::AuraEffectList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr)
|
||||||
|
{
|
||||||
if (Unit* magnet = (*itr)->GetBase()->GetUnitOwner())
|
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);
|
(*itr)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE);
|
||||||
return magnet;
|
return magnet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Melee && ranged case
|
return victim;
|
||||||
else
|
}
|
||||||
|
|
||||||
|
Unit* Unit::GetMeleeHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo)
|
||||||
{
|
{
|
||||||
AuraEffectList const& hitTriggerAuras = victim->GetAuraEffectsByType(SPELL_AURA_ADD_CASTER_HIT_TRIGGER);
|
AuraEffectList const& hitTriggerAuras = victim->GetAuraEffectsByType(SPELL_AURA_ADD_CASTER_HIT_TRIGGER);
|
||||||
for (AuraEffectList::const_iterator i = hitTriggerAuras.begin(); i != hitTriggerAuras.end(); ++i)
|
for (AuraEffectList::const_iterator i = hitTriggerAuras.begin(); i != hitTriggerAuras.end(); ++i)
|
||||||
|
{
|
||||||
if (Unit* magnet = (*i)->GetBase()->GetCaster())
|
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()))
|
if (roll_chance_i((*i)->GetAmount()))
|
||||||
{
|
{
|
||||||
(*i)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE);
|
(*i)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE);
|
||||||
return magnet;
|
return magnet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return victim;
|
return victim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2008,7 +2008,8 @@ class Unit : public WorldObject
|
|||||||
uint32 BuildAuraStateUpdateForTarget(Unit* target) const;
|
uint32 BuildAuraStateUpdateForTarget(Unit* target) const;
|
||||||
bool HasAuraState(AuraStateType flag, SpellInfo const* spellProto = NULL, Unit const* Caster = NULL) const ;
|
bool HasAuraState(AuraStateType flag, SpellInfo const* spellProto = NULL, Unit const* Caster = NULL) const ;
|
||||||
void UnsummonAllTotems();
|
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 SpellBaseDamageBonus(SpellSchoolMask schoolMask);
|
||||||
int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask);
|
int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask);
|
||||||
int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit* pVictim);
|
int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit* pVictim);
|
||||||
|
|||||||
@@ -674,8 +674,39 @@ void Spell::InitExplicitTargets(SpellCastTargets const& targets)
|
|||||||
m_targets.RemoveSrc();
|
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()
|
void Spell::SelectSpellTargets()
|
||||||
{
|
{
|
||||||
|
// select targets for cast phase
|
||||||
|
SelectExplicitTargets();
|
||||||
uint32 processedTargets = 0;
|
uint32 processedTargets = 0;
|
||||||
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||||
{
|
{
|
||||||
@@ -2079,16 +2110,7 @@ uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur)
|
|||||||
switch (cur.GetTarget())
|
switch (cur.GetTarget())
|
||||||
{
|
{
|
||||||
case TARGET_UNIT_TARGET_ENEMY:
|
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:
|
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;
|
pushType = PUSH_CHAIN;
|
||||||
break;
|
break;
|
||||||
case TARGET_UNIT_TARGET_CHAINHEAL_ALLY:
|
case TARGET_UNIT_TARGET_CHAINHEAL_ALLY:
|
||||||
|
|||||||
@@ -405,6 +405,7 @@ class Spell
|
|||||||
void WriteAmmoToPacket(WorldPacket* data);
|
void WriteAmmoToPacket(WorldPacket* data);
|
||||||
|
|
||||||
void InitExplicitTargets(SpellCastTargets const& targets);
|
void InitExplicitTargets(SpellCastTargets const& targets);
|
||||||
|
void SelectExplicitTargets();
|
||||||
void SelectSpellTargets();
|
void SelectSpellTargets();
|
||||||
void SelectEffectTypeImplicitTargets(uint8 effIndex);
|
void SelectEffectTypeImplicitTargets(uint8 effIndex);
|
||||||
uint32 SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur);
|
uint32 SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur);
|
||||||
|
|||||||
Reference in New Issue
Block a user