diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/SpellAuras.cpp | 62 | ||||
-rw-r--r-- | src/game/SpellAuras.h | 7 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 4 | ||||
-rw-r--r-- | src/game/Unit.cpp | 116 | ||||
-rw-r--r-- | src/game/Unit.h | 3 |
5 files changed, 91 insertions, 101 deletions
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 89d5a5578d5..1df03bd6b73 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -344,8 +344,8 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= Aura::Aura(SpellEntry const* spellproto, uint32 effMask, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) : m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target), -m_timeCla(1000), m_removeMode(AURA_NO_REMOVE_MODE), m_AuraDRGroup(DIMINISHING_NONE), -m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),m_auraStateMask(0), m_updated(false), m_in_use(false) +m_timeCla(1000), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE), +m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),m_auraStateMask(0), m_updated(false), m_isRemoved(false) { assert(target); @@ -462,19 +462,6 @@ m_target(parentAura->GetTarget()) m_effIndex = effIndex; m_auraName = AuraType(m_spellProto->EffectApplyAuraName[m_effIndex]); - /*if(currentBasePoints) - { - m_amount = *currentBasePoints; - m_currentBasePoints = m_amount - 1; - } - else - { - m_currentBasePoints = m_spellProto->EffectBasePoints[m_effIndex]; - if(caster) - m_amount = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target); - else - m_amount = m_currentBasePoints + 1; - }*/ if(currentBasePoints) m_currentBasePoints = *currentBasePoints; else @@ -637,12 +624,12 @@ void Aura::Update(uint32 diff) if (caster->GetHealth()>manaPerSecond) caster->ModifyHealth(-manaPerSecond); else - RemoveAura(); + m_target->RemoveAura(this); } else if (caster->GetPower(powertype)>=manaPerSecond) caster->ModifyPower(powertype,-manaPerSecond); else - RemoveAura(); + m_target->RemoveAura(this); } } } @@ -654,7 +641,7 @@ void Aura::Update(uint32 diff) Unit* caster = GetCaster(); if(!caster) { - RemoveAura(); + m_target->RemoveAura(this); return; } // Get spell range @@ -680,7 +667,7 @@ void Aura::Update(uint32 diff) if(!caster->IsWithinDistInMap(m_target,radius)) { - RemoveAura(); + m_target->RemoveAura(this); return; } } @@ -796,7 +783,7 @@ void AreaAuraEffect::Update(uint32 diff) caster->IsFriendlyTo(tmp_target) != needFriendly ) { - GetParentAura()->RemoveAura(); + m_target->RemoveAura(GetParentAura()); } else if (!caster->IsWithinDistInMap(tmp_target, m_radius)) { @@ -804,10 +791,10 @@ void AreaAuraEffect::Update(uint32 diff) { m_removeTime -= diff; if (m_removeTime < 0) - GetParentAura()->RemoveAura(); + m_target->RemoveAura(GetParentAura()); } else - GetParentAura()->RemoveAura(); + m_target->RemoveAura(GetParentAura()); } else { @@ -816,17 +803,17 @@ void AreaAuraEffect::Update(uint32 diff) if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group { if(!tmp_target->IsInPartyWith(caster)) - GetParentAura()->RemoveAura(); + m_target->RemoveAura(GetParentAura()); } else if( m_areaAuraType == AREA_AURA_RAID) { if(!tmp_target->IsInRaidWith(caster)) - GetParentAura()->RemoveAura(); + m_target->RemoveAura(GetParentAura()); } else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER ) { if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() ) - GetParentAura()->RemoveAura(); + m_target->RemoveAura(GetParentAura()); } } } @@ -854,22 +841,18 @@ void PersistentAreaAuraEffect::Update(uint32 diff) remove = true; if(remove) - GetParentAura()->RemoveAura(); + m_target->RemoveAura(GetParentAura()); AuraEffect::Update(diff); } void AuraEffect::ApplyModifier(bool apply, bool Real) { - AuraType aura = m_auraName; + if (GetParentAura()->IsRemoved()) + return; - bool inuse = GetParentAura()->IsInUse(); - if (!inuse) - GetParentAura()->SetInUse(true); - if(aura<TOTAL_AURAS) - (*this.*AuraHandler [aura])(apply,Real); - if (!inuse) - GetParentAura()->SetInUse(false); + if(m_auraName<TOTAL_AURAS) + (*this.*AuraHandler [m_auraName])(apply,Real); } void AuraEffect::CleanupTriggeredSpells() @@ -1078,6 +1061,8 @@ void Aura::_AddAura() bool Aura::SetPartAura(AuraEffect* aurEff, uint8 effIndex) { + if (IsRemoved()) + return false; if (m_auraFlags & (1<<effIndex)) return false; m_auraFlags |= 1<<effIndex; @@ -1138,6 +1123,11 @@ void Aura::_RemoveAura() m_target->ApplyModFlag(UNIT_FIELD_AURASTATE, foundMask, false); } + // since now aura cannot apply/remove it's modifiers + m_isRemoved = true; + // disable client server communication for removed aura + SetAuraSlot(MAX_AURAS); + // reset cooldown state for spells if(caster && caster->GetTypeId() == TYPEID_PLAYER) { @@ -4270,7 +4260,7 @@ void AuraEffect::HandlePeriodicTriggerSpell(bool apply, bool Real) m_isPeriodic = apply; if (m_spellProto->Id == 66 && !apply) { - if (GetParentAura()->GetRemoveMode() && GetParentAura()->GetAuraDuration()<=0) + if (GetParentAura()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) m_target->CastSpell(m_target, 32612, true, NULL, this); } } @@ -5650,7 +5640,7 @@ void AuraEffect::PeriodicTick() 100; if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent ) { - GetParentAura()->RemoveAura(); + m_target->RemoveAurasDueToSpell(GetId()); return; } break; diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 3632c7b2121..64a8d14079a 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -92,17 +92,14 @@ class TRINITY_DLL_SPEC Aura void SetNegative() { m_positive = false; } void SetPositive() { m_positive = true; } bool IsPermanent() const { return m_permanent; } - void RemoveAura(AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT) { m_permanent = false; m_duration=0; m_removeMode = mode; } bool IsPassive() const { return m_isPassive; } bool IsDeathPersistent() const { return m_isDeathPersist; } bool IsRemovedOnShapeLost() const { return m_isRemovedOnShapeLost; } bool IsUpdated() const { return m_updated; } + bool IsRemoved() const { return m_isRemoved; } void SetUpdated(bool val) { m_updated = val; } - bool IsInUse() const { return m_in_use; } - void SetInUse(bool val) { m_in_use = val; } - bool IsPersistent() const; bool IsAreaAura() const; bool IsAuraType(AuraType type) const; @@ -158,8 +155,8 @@ class TRINITY_DLL_SPEC Aura bool m_isPassive:1; bool m_positive:1; bool m_permanent:1; + bool m_isRemoved:1; bool m_updated:1; // Prevent remove aura by stack if set - bool m_in_use:1; bool m_isSingleTargetAura:1; // true if it's a single target spell and registered at caster - can change at spell steal for example }; class TRINITY_DLL_SPEC AuraEffect diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 5dac4ca1a7e..c25f4a372a2 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4922,10 +4922,10 @@ void Spell::EffectScriptEffect(uint32 effIndex) // search seal (all seals have judgement's aura dummy spell id in 2 effect if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo)) continue; - spellId2 = (*itr)->GetAmount(); - SpellEntry const *judge = sSpellStore.LookupEntry(spellId2); + SpellEntry const *judge = sSpellStore.LookupEntry((*itr)->GetAmount()); if (!judge) continue; + spellId2 = (*itr)->GetAmount(); break; } if (spellId1) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index e08d4c2d43e..21a6ec75e7e 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -159,7 +159,6 @@ Unit::Unit() for (int i = 0; i < MAX_MOVE_TYPE; ++i) m_speed_rate[i] = 1.0f; - m_removedAuras = 0; m_charmInfo = NULL; m_unit_movement_flags = 0; m_reducedThreatPercent = 0; @@ -182,6 +181,14 @@ Unit::~Unit() } } + for (AuraList::iterator i = m_removedAuras.begin(); i != m_removedAuras.end();i = m_removedAuras.begin()) + { + Aura * aur = *i; + sLog.outDebug("Aura %d is deleted from unit %d", aur->GetId(), GetGUIDLow()); + m_removedAuras.pop_front(); + delete (aur); + } + RemoveAllGameObjects(); RemoveAllDynObjects(); @@ -472,7 +479,10 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except) ++iter; if ((aur->GetSpellProto()->AuraInterruptFlags & flag) && (!except || aur->GetId() != except)) { + uint32 removedAuras = m_removedAuras.size(); RemoveAura(aur); + if (removedAuras+1<m_removedAuras.size()) + iter=m_interruptableAuras.begin(); } } @@ -513,7 +523,10 @@ void Unit::RemoveSpellbyDamageTaken(uint32 damage, uint32 spell) ++iter; if ((!spell || aur->GetId() != spell) && roll_chance_f(chance)) { + uint32 removedAuras = m_removedAuras.size(); RemoveAura(aur); + if (removedAuras+1<m_ccAuras.size()) + iter=m_interruptableAuras.begin(); } } } @@ -1659,7 +1672,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) // victim's damage shield std::set<AuraEffect*> alreadyDone; - uint32 removedAuras = pVictim->m_removedAuras; + uint32 removedAuras = pVictim->m_removedAuras.size(); AuraEffectList const& vDamageShields = pVictim->GetAurasByType(SPELL_AURA_DAMAGE_SHIELD); for(AuraEffectList::const_iterator i = vDamageShields.begin(), next = vDamageShields.begin(); i != vDamageShields.end(); i = next) { @@ -1688,9 +1701,9 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) pVictim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellProto), spellProto, true); - if (pVictim->m_removedAuras > removedAuras) + if (pVictim->m_removedAuras.size() > removedAuras) { - removedAuras = pVictim->m_removedAuras; + removedAuras = pVictim->m_removedAuras.size(); next = vDamageShields.begin(); } } @@ -2083,7 +2096,10 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe ++i; if (auraeff->GetAmount()<=0) { + uint32 removedAuras = pVictim->m_removedAuras.size(); pVictim->RemoveAura(aura); + if (removedAuras+1<pVictim->m_removedAuras.size()) + i=vSchoolAbsorb.begin(); } } } @@ -3199,7 +3215,6 @@ void Unit::_UpdateSpells( uint32 time ) } // TODO: Find a better way to prevent crash when multiple auras are removed. - m_removedAuras = 0; for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i) i->second->SetUpdated(false); @@ -3212,18 +3227,16 @@ void Unit::_UpdateSpells( uint32 time ) continue; aur->SetUpdated(true); - aur->SetInUse(true); + uint32 removedAuras = m_removedAuras.size(); aur->Update( time ); - aur->SetInUse(false); // several auras can be deleted due to update - if(m_removedAuras) + if(removedAuras < m_removedAuras.size()) { - m_removedAuras = 0; i = m_Auras.begin(); } else - ++i; + ++i; } for(AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end();) @@ -3234,6 +3247,14 @@ void Unit::_UpdateSpells( uint32 time ) ++i; } + for (AuraList::iterator i = m_removedAuras.begin(); i != m_removedAuras.end();i = m_removedAuras.begin()) + { + Aura * aur = *i; + sLog.outDebug("Aura %d is deleted from unit %d", aur->GetId(), GetGUIDLow()); + m_removedAuras.pop_front(); + delete (aur); + } + if(!m_gameObj.empty()) { std::list<GameObject*>::iterator ite1, dnext1; @@ -3787,7 +3808,6 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur) { next = i; ++next; - if ((*i).second->IsInUse()) continue; SpellEntry const* i_spellProto = (*i).second->GetSpellProto(); @@ -3863,12 +3883,9 @@ void Unit::RemoveAura(uint32 spellId, uint64 caster ,AuraRemoveMode removeMode) void Unit::RemoveAura(Aura * aur ,AuraRemoveMode mode) { - if (aur->IsInUse()) - { - if (!aur->GetRemoveMode()) - aur->RemoveAura(mode); + // no need to remove + if (aur->IsRemoved()) return; - } for(AuraMap::iterator iter = m_Auras.lower_bound(aur->GetId()); iter != m_Auras.upper_bound(aur->GetId());) { if (aur == iter->second) @@ -3885,7 +3902,7 @@ void Unit::RemoveAurasDueToSpell(uint32 spellId, uint64 caster ,AuraRemoveMode r { for(AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);) { - if ((!caster || iter->second->GetCasterGUID()==caster) && (!iter->second->IsInUse() || !iter->second->GetRemoveMode())) + if (!caster || iter->second->GetCasterGUID()==caster) { RemoveAura(iter, removeMode); iter = m_Auras.lower_bound(spellId); @@ -3964,9 +3981,9 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit // 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); + stealer->AddAura(new_aur); RemoveAuraFromStack(iter, AURA_REMOVE_BY_ENEMY_SPELL); return; } @@ -3979,7 +3996,7 @@ void Unit::RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId) { for (AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);) { - if ((!castItem || iter->second->GetCastItemGUID()==castItem->GetGUID()) && (!iter->second->IsInUse() || !iter->second->GetRemoveMode())) + if (!castItem || iter->second->GetCastItemGUID()==castItem->GetGUID()) { RemoveAura(iter); iter = m_Auras.upper_bound(spellId); // overwrite by more appropriate @@ -3998,7 +4015,10 @@ void Unit::RemoveAurasByType(AuraType auraType, uint64 casterGUID, Aura * except ++iter; if (aur != except && (!casterGUID || aur->GetCasterGUID()==casterGUID)) { + uint32 removedAuras = m_removedAuras.size(); RemoveAura(aur); + if (removedAuras+1<m_removedAuras.size()) + iter=m_modAuras[auraType].begin(); } } } @@ -4012,7 +4032,10 @@ void Unit::RemoveAurasByTypeWithDispel(AuraType auraType, Spell * spell) ++iter; if (GetDispelChance(spell, aur->GetCaster(), aur->GetId())) { + uint32 removedAuras = m_removedAuras.size(); RemoveAura(aur, AURA_REMOVE_BY_ENEMY_SPELL); + if (removedAuras+1<m_removedAuras.size()) + iter=m_modAuras[auraType].begin(); } } } @@ -4032,35 +4055,26 @@ void Unit::RemoveNotOwnSingleTargetAuras() AuraList& scAuras = GetSingleCastAuras(); for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();) { - if ((*iter)->GetTarget()!=this) + Aura * aur=*iter; + ++iter; + if (aur->GetTarget()!=this) { - Aura * aur=*iter; - ++iter; + uint32 removedAuras = m_removedAuras.size(); aur->GetTarget()->RemoveAura(aur->GetId(),aur->GetCasterGUID()); + if (removedAuras+1<m_removedAuras.size()) + iter=scAuras.begin(); } - else - ++iter; } } void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) { Aura* Aur = i->second; - //aura can be during update when removing, set it to remove at next update - if (Aur->IsInUse()) - { - if (!Aur->GetRemoveMode()) - Aur->RemoveAura(mode); - i++; - return; - } - SpellEntry const* AurSpellInfo = Aur->GetSpellProto(); // some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura // remove aura from list before to prevent deleting it before m_Auras.erase(i); - ++m_removedAuras; // internal count used by unit update Aur->UnregisterSingleCastAura(); @@ -4077,10 +4091,6 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) m_ccAuras.remove(Aur); } - // Set remove mode if mode already not set - if (!Aur->GetRemoveMode()) - Aur->SetRemoveMode(mode); - // Statue unsummoned at aura remove Totem* statue = NULL; bool channeled = false; @@ -4129,11 +4139,15 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) } } + Aur->SetRemoveMode(mode); + sLog.outDebug("Aura %u now is remove mode %d", Aur->GetId(), mode); Aur->HandleEffects(false); - Aur->_RemoveAura(); - delete Aur; + // set aura to be removed during unit::_updatespells + m_removedAuras.push_back(Aur); + + Aur->_RemoveAura(); if(statue) statue->UnSummon(); @@ -11475,10 +11489,6 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag if (!parentAura) continue; - bool inuse = parentAura->IsInUse(); - if (!inuse) - parentAura->SetInUse(true); - bool useCharges= parentAura->GetAuraCharges()>0; bool takeCharges = false; @@ -11611,19 +11621,11 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag } takeCharges=true; } - if (!inuse) - parentAura->SetInUse(false); - - if ( !parentAura->GetAuraDuration() && !(parentAura->IsPermanent() || (parentAura->IsPassive())) ) - RemoveAura(parentAura); - else + // Remove charge (aura can be removed by triggers) + if(useCharges && takeCharges) { - // Remove charge (aura can be removed by triggers) - if(useCharges && takeCharges) - { - if (parentAura->DropAuraCharge()) - RemoveAura(parentAura->GetId(),parentAura->GetCasterGUID()); - } + if (parentAura->DropAuraCharge()) + RemoveAura(parentAura->GetId(),parentAura->GetCasterGUID()); } } } @@ -13107,6 +13109,8 @@ void Unit::GetPartyMember(std::list<Unit*> &TagUnitMap, float radius) void Unit::HandleAuraEffect(AuraEffect * aureff, bool apply) { + if (aureff->GetParentAura()->IsRemoved()) + return; if (apply) { m_modAuras[aureff->GetAuraName()].push_back(aureff); diff --git a/src/game/Unit.h b/src/game/Unit.h index 2ab00f23407..0d1c01e5bd1 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -328,7 +328,6 @@ enum DamageTypeToSchool enum AuraRemoveMode { - AURA_NO_REMOVE_MODE = 0, AURA_REMOVE_BY_DEFAULT, AURA_REMOVE_BY_STACK, // change stack, single aura remove, AURA_REMOVE_BY_CANCEL, @@ -1576,12 +1575,12 @@ class TRINITY_DLL_SPEC Unit : public WorldObject std::list<GameObject*> m_gameObj; bool m_isSorted; uint32 m_transform; - uint32 m_removedAuras; AuraEffectList m_modAuras[TOTAL_AURAS]; AuraList m_scAuras; // casted singlecast auras AuraList m_interruptableAuras; AuraList m_ccAuras; + AuraList m_removedAuras; uint32 m_interruptMask; float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; |