diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 8c75d81c5..335f2973a 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -477,6 +477,9 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, m_areaAuraType = AREA_AURA_RAID; if (target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) m_modifier.m_auraname = SPELL_AURA_NONE; + // Light's Beacon not applied to caster itself (TODO: more generic check for another simialr spell if any?) + else if (target == caster_ptr && m_spellProto->Id == 53651) + m_modifier.m_auraname = SPELL_AURA_NONE; break; case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: m_areaAuraType = AREA_AURA_FRIEND; @@ -770,7 +773,40 @@ void AreaAura::Update(uint32 diff) for(std::list::iterator tIter = targets.begin(); tIter != targets.end(); tIter++) { - if((*tIter)->HasAura(GetId(), m_effIndex)) + // flag for seelction is need apply aura to current iteration target + bool apply = true; + + // we need ignore present caster self applied are auras sometime + // in cases if this only auras applied for spell effect + Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), m_effIndex); + for(Unit::AuraMap::const_iterator i = (*tIter)->GetAuras().lower_bound(spair); i != (*tIter)->GetAuras().upper_bound(spair); ++i) + { + if (i->second->IsDeleted()) + continue; + + switch(m_areaAuraType) + { + case AREA_AURA_ENEMY: + // non caster self-casted auras (non stacked) + if(i->second->GetModifier()->m_auraname != SPELL_AURA_NONE) + apply = false; + break; + case AREA_AURA_RAID: + // non caster self-casted auras (stacked from diff. casters) + if(i->second->GetModifier()->m_auraname != SPELL_AURA_NONE || i->second->GetCasterGUID() == GetCasterGUID()) + apply = false; + break; + default: + // in generic case not allow stacking area auras + apply = false; + break; + } + + if(!apply) + break; + } + + if(!apply) continue; if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel())) @@ -803,7 +839,7 @@ void AreaAura::Update(uint32 diff) caster->IsFriendlyTo(m_target) != needFriendly ) { - m_target->RemoveAura(GetId(), GetEffIndex()); + m_target->RemoveAurasByCasterSpell(GetId(), GetEffIndex(),GetCasterGUID()); } else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group { @@ -835,16 +871,16 @@ void AreaAura::Update(uint32 diff) { Player* checkTarget = m_target->GetCharmerOrOwnerPlayerOrPlayerItself(); if(!checkTarget) - m_target->RemoveAura(GetId(), GetEffIndex()); + m_target->RemoveAurasByCasterSpell(GetId(), GetEffIndex(), GetCasterGUID()); } else - m_target->RemoveAura(GetId(), GetEffIndex()); + m_target->RemoveAurasByCasterSpell(GetId(), GetEffIndex(), GetCasterGUID()); } } else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER ) { if( m_target->GetGUID() != caster->GetCharmerOrOwnerGUID() ) - m_target->RemoveAura(GetId(), GetEffIndex()); + m_target->RemoveAurasByCasterSpell(GetId(), GetEffIndex(), GetCasterGUID()); } } } @@ -885,6 +921,32 @@ void Aura::ApplyModifier(bool apply, bool Real) SetInUse(false); } +bool Aura::IsNeedVisibleSlot(Unit const* caster) const +{ + bool totemAura = caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem(); + + // passive auras (except totem auras) do not get placed in the slots + if (m_isPassive && !totemAura) + return false; + + // generic not caster case + if (m_target != caster) + return true; + + // special area auras case at caster + switch(m_spellProto->Effect[GetEffIndex()]) + { + case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: + return false; + case SPELL_EFFECT_APPLY_AREA_AURA_RAID: + // not sure is totemAura need, just preserve old code results + return totemAura || m_modifier.m_auraname != SPELL_AURA_NONE; + default: break; + } + + return true; +} + void Aura::_AddAura() { if (!GetId()) @@ -942,10 +1004,7 @@ void Aura::_AddAura() } } - // passive auras (except totem auras) do not get placed in the slots - // area auras with SPELL_AURA_NONE are not shown on target - if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && - (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster)) + if (IsNeedVisibleSlot(caster)) { SetAuraSlot( slot ); if(slot < MAX_AURAS) // slot found send data to client @@ -2415,7 +2474,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) // original caster must be target (beacon) m_target->CastSpell(m_target,53651,true,NULL,this,m_target->GetGUID()); else - m_target->RemoveAurasDueToSpell(53651); + m_target->RemoveAurasByCasterSpell(53651,m_target->GetGUID()); return; } break; diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index c6965ca53..98fe1111d 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -383,6 +383,7 @@ class MANGOS_DLL_SPEC Aura uint32 m_in_use; // > 0 while in Aura::ApplyModifier call/Aura::Update/etc private: void CleanupTriggeredSpells(); + bool IsNeedVisibleSlot(Unit const* caster) const; // helper for check req. visibility slot }; class MANGOS_DLL_SPEC AreaAura : public Aura diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index e9c591b25..f73262e2e 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3417,6 +3417,7 @@ bool Unit::AddAura(Aura *Aur) return false; } + // m_auraname can be modified to SPELL_AURA_NONE for area auras, this expected for this value AuraType aurName = Aur->GetModifier()->m_auraname; spellEffectPair spair = spellEffectPair(Aur->GetId(), Aur->GetEffIndex()); @@ -3445,10 +3446,15 @@ bool Unit::AddAura(Aura *Aur) } bool stop = false; - switch(aurName) + + // m_auraname can be modified to SPELL_AURA_NONE for area auras, use original + AuraType aurNameReal = AuraType(aurSpellInfo->EffectApplyAuraName[Aur->GetEffIndex()]); + + switch(aurNameReal) { // DoT/HoT/etc - case SPELL_AURA_PERIODIC_DAMAGE: // allow stack + case SPELL_AURA_DUMMY: // allow stack + case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: case SPELL_AURA_PERIODIC_LEECH: case SPELL_AURA_PERIODIC_HEAL: @@ -3752,6 +3758,22 @@ void Unit::RemoveAurasByCasterSpell(uint32 spellId, uint64 casterGUID) } } +void Unit::RemoveAurasByCasterSpell(uint32 spellId, uint32 effindex, uint64 casterGUID) +{ + spellEffectPair spair = spellEffectPair(spellId, effindex); + for(AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair);) + { + Aura *aur = iter->second; + if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID) + { + RemoveAura(iter); + iter = m_Auras.lower_bound(spair); + } + else + ++iter; + } +} + void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler) { for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ) @@ -5110,7 +5132,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } CastSpell(this, 28682, true, castItem, triggeredByAura); - return (procEx & PROC_EX_CRITICAL_HIT);// charge update only at crit hits, no hidden cooldowns + return (procEx & PROC_EX_CRITICAL_HIT); // charge update only at crit hits, no hidden cooldowns } } break; @@ -5807,22 +5829,33 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu if (GetGUID() == triggeredByAura->GetCasterGUID()) return false; + // beacon Unit* beacon = triggeredByAura->GetCaster(); if (!beacon) return false; - Aura* dummy = beacon->GetDummyAura(53563); + // find caster main aura at beacon + Aura* dummy = NULL; + Unit::AuraList const& baa = beacon->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = baa.begin(); i != baa.end(); ++i) + { + if ((*i)->GetId() == 53563 && (*i)->GetCasterGUID() == pVictim->GetGUID()) + { + dummy = (*i); + break; + } + } + + // original heal must be form beacon caster if (!dummy) return false; - // original heal must be form beacon caster - if (dummy->GetCasterGUID() != pVictim->GetGUID()) - return false; - - triggered_spell_id = 53652; // Beacon of Light + triggered_spell_id = 53652; // Beacon of Light basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/100; - target = beacon; - break; + + // cast with original caster set but beacon to beacon for apply caster mods and avoid LoS check + beacon->CastCustomSpell(beacon,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura,pVictim->GetGUID()); + return true; } // Seal of the Martyr do damage trigger case 53720: diff --git a/src/game/Unit.h b/src/game/Unit.h index 20c175471..b098d4dc9 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1211,6 +1211,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL); void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId); void RemoveAurasByCasterSpell(uint32 spellId, uint64 casterGUID); + void RemoveAurasByCasterSpell(uint32 spellId, uint32 effindex, uint64 casterGUID); void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler); void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer); void RemoveAurasDueToSpellByCancel(uint32 spellId); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 937bce2a4..515a463de 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8496" + #define REVISION_NR "8497" #endif // __REVISION_NR_H__