diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/Player.cpp | 10 | ||||
-rw-r--r-- | src/game/SpellAuras.cpp | 20 | ||||
-rw-r--r-- | src/game/SpellAuras.h | 7 | ||||
-rw-r--r-- | src/game/Unit.cpp | 34 |
4 files changed, 45 insertions, 26 deletions
diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 027b3bd8080..34e9ff8de8a 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -14749,15 +14749,17 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) else remaincharges = 0; - //do not load single target auras (unless they were cast by the player) - if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto)) - continue; for(uint32 i=0; i<stackcount; i++) { Aura* aura = CreateAura(spellproto, effindex, NULL, this, NULL); if(!damage) damage = aura->GetModifier()->m_amount; + + // reset stolen single target auras + if (caster_guid != GetGUID() && aura->IsSingleTarget()) + aura->SetIsSingleTarget(false); + aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges); AddAura(aura); sLog.outDetail("Added aura spellid %u, effect %u", spellproto->Id, effindex); @@ -15874,7 +15876,7 @@ void Player::_SaveAuras() if (!(itr2->second->IsPassive() || itr2->second->IsRemovedOnShapeLost())) { //do not save single target auras (unless they were cast by the player) - if (!(itr2->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(spellInfo))) + if (!(itr2->second->GetCasterGUID() != GetGUID() && itr2->second->IsSingleTarget())) { uint8 i; // or apply at cast SPELL_AURA_MOD_SHAPESHIFT or SPELL_AURA_MOD_STEALTH auras diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 8976aea2cb5..10028c9095a 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -376,6 +376,8 @@ m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false) m_positive = IsPositiveEffect(GetId(), m_effIndex); m_auraStateMask = 0; + m_isSingleTargetAura = IsSingleTargetSpell(m_spellProto); + m_applyTime = time(NULL); if(!caster) @@ -6726,3 +6728,21 @@ void Aura::HandlePhase(bool apply, bool Real) m_target->SetVisibility(m_target->GetVisibility()); } +void Aura::UnregisterSingleCastAura() +{ + if (IsSingleTarget()) + { + Unit* caster = NULL; + caster = GetCaster(); + if(caster) + { + caster->GetSingleCastAuras().remove(this); + } + else + { + sLog.outError("Couldn't find the caster of the single target aura, may crash later!"); + assert(false); + } + m_isSingleTargetAura = false; + } +} diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 48611018f94..d566c0a6cc4 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -279,6 +279,8 @@ class TRINITY_DLL_SPEC Aura return m_procCharges == 0; } + void UnregisterSingleCastAura(); + int8 GetStackAmount() {return m_stackAmount;} //int32 GetModifierValuePerStack() {return m_modifier.m_amount / m_stackAmount;} void SetStackAmount(uint8 num); @@ -310,6 +312,10 @@ class TRINITY_DLL_SPEC Aura bool IsUpdated() { return m_updated; } void SetUpdated(bool val) { m_updated = val; } + + bool IsSingleTarget() {return m_isSingleTargetAura;} + void SetIsSingleTarget(bool val) { m_isSingleTargetAura = val;} + void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; } Unit* GetTriggerTarget() const; @@ -367,6 +373,7 @@ class TRINITY_DLL_SPEC Aura bool m_isRemovedOnShapeLost:1; bool m_updated:1; // Prevent remove aura by stack if set bool m_in_use:1; // true while in Aura::ApplyModifier call + bool m_isSingleTargetAura:1; // true if it's a single target spell and registered at caster - can change at spell steal for example private: }; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 2a958411f58..7e64c9617d9 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3864,7 +3864,7 @@ bool Unit::AddAura(Aura *Aur) } // update single target auras list (before aura add to aura list, to prevent unexpected remove recently added aura) - if (IsSingleTargetSpell(aurSpellInfo) && Aur->GetTarget()) + if (Aur->IsSingleTarget() && Aur->GetTarget()) { // caster pointer can be deleted in time aura remove, find it by guid at each iteration for(;;) @@ -4231,10 +4231,9 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID) { int32 basePoints = aur->GetBasePoints(); - // construct the new aura for the attacker - Aura * new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), NULL/*&basePoints*/, stealer); - if(!new_aur) - continue; + // construct the new aura for the attacker - will never return NULL, it's just a wrapper for + // some different constructors + Aura * new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), NULL, stealer, this); // set its duration and maximum duration // max duration 2 minutes (in msecs) @@ -4243,6 +4242,12 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit new_aur->SetAuraMaxDuration( max_dur > dur ? dur : max_dur ); new_aur->SetAuraDuration( max_dur > dur ? dur : max_dur ); + // Unregister _before_ adding to stealer + aur->UnregisterSingleCastAura(); + + // strange but intended behaviour: Stolen single target auras won't be treated as single targeted + new_aur->SetIsSingleTarget(false); + // add the new aura to stealer stealer->AddAura(new_aur); @@ -4352,21 +4357,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) m_Auras.erase(i); ++m_removedAuras; // internal count used by unit update - Unit* caster = NULL; - if (IsSingleTargetSpell(AurSpellInfo)) - { - caster = Aur->GetCaster(); - if(caster) - { - AuraList& scAuras = caster->GetSingleCastAuras(); - scAuras.remove(Aur); - } - else - { - sLog.outError("Couldn't find the caster of the single target aura, may crash later!"); - assert(false); - } - } + Aur->UnregisterSingleCastAura(); // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order) if (Aur->GetModifier()->m_auraname < TOTAL_AURAS) @@ -4395,8 +4386,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) bool channeled = false; if(Aur->GetAuraDuration() && !Aur->IsPersistent() && IsChanneledSpell(AurSpellInfo)) { - if(!caster) // can be already located for IsSingleTargetSpell case - caster = Aur->GetCaster(); + Unit* caster = Aur->GetCaster(); if(caster && caster->isAlive()) { |