[11766] fix spell redirection and totem destruction on hit by redirected spell

This commit is contained in:
Laise 2011-08-04 19:33:43 +03:00
parent 61f31980cf
commit c60425c6bd
11 changed files with 73 additions and 26 deletions

View file

@ -392,6 +392,8 @@ Spell::Spell( Unit* caster, SpellEntry const *info, bool triggered, ObjectGuid o
// determine reflection
m_canReflect = false;
m_spellFlags = SPELL_FLAG_NORMAL;
if(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_CANT_REFLECTED))
{
for(int j = 0; j < MAX_EFFECT_INDEX; ++j)
@ -804,6 +806,9 @@ void Spell::AddUnitTarget(Unit* pVictim, SpellEffectIndex effIndex)
// Check for effect immune skip if immuned
bool immuned = pVictim->IsImmuneToSpellEffect(m_spellInfo, effIndex);
if (pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsTotem() && (m_spellFlags & SPELL_FLAG_REDIRECTED))
immuned = false;
ObjectGuid targetGUID = pVictim->GetObjectGuid();
// Lookup target in already in list
@ -858,6 +863,8 @@ void Spell::AddUnitTarget(Unit* pVictim, SpellEffectIndex effIndex)
// Increase time interval for reflected spells by 1.5
target.timeDelay += target.timeDelay >> 1;
m_spellFlags |= SPELL_FLAG_REFLECTED;
}
else
target.reflectResult = SPELL_MISS_NONE;
@ -1004,7 +1011,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
{
if (target->reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him
{
DoSpellHitOnUnit(m_caster, mask, true);
DoSpellHitOnUnit(m_caster, mask);
unitTarget = m_caster;
}
}
@ -1147,7 +1154,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
((Creature*)m_caster)->AI()->SpellHitTarget(unit, m_spellInfo);
}
void Spell::DoSpellHitOnUnit(Unit *unit, uint32 effectMask, bool isReflected)
void Spell::DoSpellHitOnUnit(Unit *unit, uint32 effectMask)
{
if (!unit || !effectMask)
return;
@ -1298,7 +1305,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, uint32 effectMask, bool isReflected)
if (duration > 0)
{
int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup, m_spellInfo);
unit->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel, limitduration, isReflected);
unit->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel, limitduration, m_spellFlags & SPELL_FLAG_REFLECTED);
// Fully diminished
if (duration == 0)
@ -1819,6 +1826,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
if(Unit* pUnitTarget = m_caster->SelectMagnetTarget(m_targets.getUnitTarget(), this, effIndex))
{
m_targets.setUnitTarget(pUnitTarget);
m_spellFlags |= SPELL_FLAG_REDIRECTED;
targetUnitMap.push_back(pUnitTarget);
}
}
@ -2257,6 +2265,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
if(Unit* pUnitTarget = m_caster->SelectMagnetTarget(m_targets.getUnitTarget(), this, effIndex))
{
m_targets.setUnitTarget(pUnitTarget);
m_spellFlags |= SPELL_FLAG_REDIRECTED;
targetUnitMap.push_back(pUnitTarget);
}
}
@ -2287,6 +2296,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
if(Unit* pUnitTarget = m_caster->SelectMagnetTarget(m_targets.getUnitTarget(), this, effIndex))
{
m_targets.setUnitTarget(pUnitTarget);
m_spellFlags |= SPELL_FLAG_REDIRECTED;
targetUnitMap.push_back(pUnitTarget);
}
break;
@ -2902,13 +2912,18 @@ void Spell::cancel()
case SPELL_STATE_CASTING:
{
for(TargetList::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
for(TargetList::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
{
if (ihit->missCondition == SPELL_MISS_NONE)
{
Unit* unit = m_caster->GetObjectGuid() == (*ihit).targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
if (unit && unit->isAlive())
unit->RemoveAurasByCasterSpell(m_spellInfo->Id, m_caster->GetObjectGuid());
// prevent other effects applying if spell is already interrupted
// i.e. if effects have different targets and it was interrupted on one of them when
// haven't yet applied to another
ihit->processed = true;
}
}

View file

@ -64,6 +64,13 @@ enum SpellCastFlags
CAST_FLAG_IMMUNITY = 0x04000000 // spell cast school imminity info
};
enum SpellFlags
{
SPELL_FLAG_NORMAL = 0x00,
SPELL_FLAG_REFLECTED = 0x01, // reflected spell
SPELL_FLAG_REDIRECTED = 0x02 // redirected spell
};
enum SpellNotifyPushType
{
PUSH_IN_FRONT,
@ -514,6 +521,7 @@ class Spell
int32 m_casttime; // Calculated spell cast time initialized only in Spell::prepare
int32 m_duration;
bool m_canReflect; // can reflect this spell?
uint8 m_spellFlags; // for spells whose target was changed in cast i.e. due to reflect
bool m_autoRepeat;
uint8 m_runesState;
@ -615,7 +623,7 @@ class Spell
void HandleDelayedSpellLaunch(TargetInfo *target);
void InitializeDamageMultipliers();
void ResetEffectDamageAndHeal();
void DoSpellHitOnUnit(Unit *unit, uint32 effectMask, bool isReflected = false);
void DoSpellHitOnUnit(Unit *unit, uint32 effectMask);
void DoAllEffectOnTarget(GOTargetInfo *target);
void DoAllEffectOnTarget(ItemTargetInfo *target);
bool IsAliveUnitPresentInTargetList();

View file

@ -8383,9 +8383,9 @@ void Aura::HandleAuraModAllCritChance(bool apply, bool Real)
((Player*)target)->UpdateAllSpellCritChances();
}
void Aura::HandleAuraStopNaturalManaRegen(bool apply, bool real)
void Aura::HandleAuraStopNaturalManaRegen(bool apply, bool Real)
{
if (!real)
if (!Real)
return;
GetTarget()->ApplyModFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER, !apply && !GetTarget()->IsUnderLastManaUseEffect());

View file

@ -373,7 +373,7 @@ class MANGOS_DLL_SPEC Aura
void HandleAuraModAllCritChance(bool Apply, bool Real);
void HandleAuraOpenStable(bool apply, bool Real);
void HandleAuraAddMechanicAbilities(bool apply, bool Real);
void HandleAuraStopNaturalManaRegen(bool apply, bool real);
void HandleAuraStopNaturalManaRegen(bool apply, bool Real);
virtual ~Aura();

View file

@ -6042,7 +6042,7 @@ Unit* Unit::SelectMagnetTarget(Unit *victim, Spell* spell, SpellEffectIndex eff)
return NULL;
// Magic case
if (spell && (spell->m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE || spell->m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC))
if (spell && spell->m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC)
{
Unit::AuraList const& magnetAuras = victim->GetAurasByType(SPELL_AURA_SPELL_MAGNET);
for(Unit::AuraList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr)
@ -6050,12 +6050,7 @@ Unit* Unit::SelectMagnetTarget(Unit *victim, Spell* spell, SpellEffectIndex eff)
if (Unit* magnet = (*itr)->GetCaster())
{
if (magnet->isAlive() && magnet->IsWithinLOSInMap(this) && spell->CheckTarget(magnet, eff))
{
if (SpellAuraHolder *holder = (*itr)->GetHolder())
if (holder->DropAuraCharge())
victim->RemoveSpellAuraHolder(holder);
return magnet;
}
}
}
}
@ -6070,12 +6065,7 @@ Unit* Unit::SelectMagnetTarget(Unit *victim, Spell* spell, SpellEffectIndex eff)
if (magnet->isAlive() && magnet->IsWithinLOSInMap(this) && (!spell || spell->CheckTarget(magnet, eff)))
{
if (roll_chance_i((*i)->GetModifier()->m_amount))
{
if (SpellAuraHolder *holder = (*i)->GetHolder())
if (holder->DropAuraCharge())
victim->RemoveSpellAuraHolder(holder);
return magnet;
}
}
}
}
@ -9739,8 +9729,6 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
if (!triggeredByAura)
continue;
Modifier *auraModifier = triggeredByAura->GetModifier();
if (procSpell)
{
if (spellProcEvent)
@ -9769,7 +9757,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
continue;
}
SpellAuraProcResult procResult = (*this.*AuraProcHandler[auraModifier->m_auraname])(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown);
SpellAuraProcResult procResult = (*this.*AuraProcHandler[triggeredByHolder->GetSpellProto()->EffectApplyAuraName[i]])(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown);
switch (procResult)
{
case SPELL_AURA_PROC_CANT_TRIGGER:

View file

@ -1849,6 +1849,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
SpellAuraProcResult HandleAddPctModifierAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
SpellAuraProcResult HandleModDamagePercentDoneAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
SpellAuraProcResult HandleModRating(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
SpellAuraProcResult HandleSpellMagnetAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
SpellAuraProcResult HandleManaShieldAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
SpellAuraProcResult HandleModResistanceAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
SpellAuraProcResult HandleNULLProc(Unit* /*pVictim*/, uint32 /*damage*/, Aura* /*triggeredByAura*/, SpellEntry const* /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 /*cooldown*/)

View file

@ -128,7 +128,7 @@ pAuraProcHandler AuraProcHandler[TOTAL_AURAS]=
&Unit::HandleNULLProc, // 93 SPELL_AURA_MOD_UNATTACKABLE
&Unit::HandleNULLProc, // 94 SPELL_AURA_INTERRUPT_REGEN
&Unit::HandleNULLProc, // 95 SPELL_AURA_GHOST
&Unit::HandleNULLProc, // 96 SPELL_AURA_SPELL_MAGNET
&Unit::HandleSpellMagnetAuraProc, // 96 SPELL_AURA_SPELL_MAGNET
&Unit::HandleManaShieldAuraProc, // 97 SPELL_AURA_MANA_SHIELD
&Unit::HandleNULLProc, // 98 SPELL_AURA_MOD_SKILL_TALENT
&Unit::HandleNULLProc, // 99 SPELL_AURA_MOD_ATTACK_POWER
@ -3974,6 +3974,20 @@ SpellAuraProcResult Unit::HandleModRating(Unit* /*pVictim*/, uint32 /*damage*/,
return SPELL_AURA_PROC_OK;
}
SpellAuraProcResult Unit::HandleSpellMagnetAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
{
if (triggeredByAura->GetId() == 8178) // Grounding Totem Effect
{
// for spells that doesn't do damage but need to destroy totem anyway
if ((!damage || damage < GetHealth()) && GetTypeId() == TYPEID_UNIT && ((Creature*)this)->IsTotem())
{
DealDamage(this, GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
return SPELL_AURA_PROC_OK;
}
}
return SPELL_AURA_PROC_OK;
}
SpellAuraProcResult Unit::HandleManaShieldAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
{
SpellEntry const *dummySpell = triggeredByAura->GetSpellProto ();