diff options
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 33 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 45 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.h | 2 |
4 files changed, 69 insertions, 19 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 0001af2fc13..e2f509721ed 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -4130,7 +4130,7 @@ void Unit::RemoveAllAuras() { // this may be a dead loop if some events on aura remove will continiously apply aura on remove // we want to have all auras removed, so use your brain when linking events - while (!m_appliedAuras.empty() || !m_ownedAuras.empty()) + for (int counter = 0; !m_appliedAuras.empty() || !m_ownedAuras.empty(); counter++) { AuraApplicationMap::iterator aurAppIter; for (aurAppIter = m_appliedAuras.begin(); aurAppIter != m_appliedAuras.end();) @@ -4139,6 +4139,37 @@ void Unit::RemoveAllAuras() AuraMap::iterator aurIter; for (aurIter = m_ownedAuras.begin(); aurIter != m_ownedAuras.end();) RemoveOwnedAura(aurIter); + + const int maxIteration = 50; + // give this loop a few tries, if there are still auras then log as much information as possible + if (counter >= maxIteration) + { + std::stringstream sstr; + sstr << "Unit::RemoveAllAuras() iterated " << maxIteration << " times already but there are still " + << m_appliedAuras.size() << " m_appliedAuras and " << m_ownedAuras.size() << " m_ownedAuras. Details:" << "\n"; + sstr << GetDebugInfo() << "\n"; + + if (!m_appliedAuras.empty()) + { + sstr << "m_appliedAuras:" << "\n"; + + for (std::pair<uint32 const, AuraApplication*>& auraAppPair : m_appliedAuras) + sstr << auraAppPair.second->GetDebugInfo() << "\n"; + } + + if (!m_ownedAuras.empty()) + { + sstr << "m_ownedAuras:" << "\n"; + + for (std::pair<uint32 const, Aura*>& auraPair : m_ownedAuras) + sstr << auraPair.second->GetDebugInfo() << "\n"; + } + + TC_LOG_ERROR("entities.unit", "%s", sstr.str().c_str()); + ABORT_MSG("%s", sstr.str().c_str()); + + break; + } } } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 02975f501dc..d331de21634 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1349,8 +1349,9 @@ void AuraEffect::HandleModInvisibilityDetect(AuraApplication const* aurApp, uint target->m_invisibilityDetect.AddValue(type, -GetAmount()); } - // call functions which may have additional effects after chainging state of unit - target->UpdateObjectVisibility(); + // call functions which may have additional effects after changing state of unit + if (target->IsInWorld()) + target->UpdateObjectVisibility(); } void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -1400,13 +1401,15 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode target->m_invisibility.AddValue(type, -GetAmount()); } - // call functions which may have additional effects after chainging state of unit + // call functions which may have additional effects after changing state of unit if (apply && (mode & AURA_EFFECT_HANDLE_REAL)) { // drop flag at invisibiliy in bg target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); } - target->UpdateObjectVisibility(); + + if (target->IsInWorld()) + target->UpdateObjectVisibility(); } void AuraEffect::HandleModStealthDetect(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -1430,8 +1433,9 @@ void AuraEffect::HandleModStealthDetect(AuraApplication const* aurApp, uint8 mod target->m_stealthDetect.AddValue(type, -GetAmount()); } - // call functions which may have additional effects after chainging state of unit - target->UpdateObjectVisibility(); + // call functions which may have additional effects after changing state of unit + if (target->IsInWorld()) + target->UpdateObjectVisibility(); } void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -1465,13 +1469,15 @@ void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, boo } } - // call functions which may have additional effects after chainging state of unit + // call functions which may have additional effects after changing state of unit if (apply && (mode & AURA_EFFECT_HANDLE_REAL)) { // drop flag at stealth in bg target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); } - target->UpdateObjectVisibility(); + + if (target->IsInWorld()) + target->UpdateObjectVisibility(); } void AuraEffect::HandleModStealthLevel(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -1487,8 +1493,9 @@ void AuraEffect::HandleModStealthLevel(AuraApplication const* aurApp, uint8 mode else target->m_stealth.AddValue(type, -GetAmount()); - // call functions which may have additional effects after chainging state of unit - target->UpdateObjectVisibility(); + // call functions which may have additional effects after changing state of unit + if (target->IsInWorld()) + target->UpdateObjectVisibility(); } void AuraEffect::HandleDetectAmore(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -1543,7 +1550,7 @@ void AuraEffect::HandleSpiritOfRedemption(AuraApplication const* aurApp, uint8 m } // die at aura end else if (target->IsAlive()) - // call functions which may have additional effects after chainging state of unit + // call functions which may have additional effects after changing state of unit target->setDeathState(JUST_DIED); } @@ -1612,7 +1619,7 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app target->SetPhaseMask(newPhase, false); } - // call functions which may have additional effects after chainging state of unit + // call functions which may have additional effects after changing state of unit // phase auras normally not expected at BG but anyway better check if (apply) { @@ -2253,7 +2260,7 @@ void AuraEffect::HandleModUnattackable(AuraApplication const* aurApp, uint8 mode target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE_2, apply); - // call functions which may have additional effects after chainging state of unit + // call functions which may have additional effects after changing state of unit if (apply && (mode & AURA_EFFECT_HANDLE_REAL)) { if (target->GetMap()->IsDungeon()) @@ -2345,7 +2352,7 @@ void AuraEffect::HandleAuraModSilence(AuraApplication const* aurApp, uint8 mode, { target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); - // call functions which may have additional effects after chainging state of unit + // call functions which may have additional effects after changing state of unit // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) if (Spell* spell = target->GetCurrentSpell(CurrentSpellTypes(i))) @@ -2500,8 +2507,9 @@ void AuraEffect::HandleAuraModStalked(AuraApplication const* aurApp, uint8 mode, target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT); } - // call functions which may have additional effects after chainging state of unit - target->UpdateObjectVisibility(); + // call functions which may have additional effects after changing state of unit + if (target->IsInWorld()) + target->UpdateObjectVisibility(); } void AuraEffect::HandleAuraUntrackable(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4943,8 +4951,9 @@ void AuraEffect::HandleAuraModFakeInebriation(AuraApplication const* aurApp, uin target->m_invisibilityDetect.DelFlag(INVISIBILITY_DRUNK); } - // call functions which may have additional effects after chainging state of unit - target->UpdateObjectVisibility(); + // call functions which may have additional effects after changing state of unit + if (target->IsInWorld()) + target->UpdateObjectVisibility(); } void AuraEffect::HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 mode, bool apply) const diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 94dc12f0b23..6c61ade3373 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -262,6 +262,14 @@ void AuraApplication::ClientUpdate(bool remove) _target->SendMessageToSet(&data, true); } +std::string AuraApplication::GetDebugInfo() const +{ + std::stringstream sstr; + sstr << "Base: " << (GetBase() ? GetBase()->GetDebugInfo() : "NULL") + << "\nTarget: " << (GetTarget() ? GetTarget()->GetDebugInfo() : "NULL"); + return sstr.str(); +} + uint8 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 availableEffectMask, WorldObject* owner) { ASSERT_NODEBUGINFO(spellProto); diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index e57813b0e1e..86da73a2263 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -82,6 +82,8 @@ class TC_GAME_API AuraApplication bool IsNeedClientUpdate() const { return _needClientUpdate;} void BuildUpdatePacket(ByteBuffer& data, bool remove) const; void ClientUpdate(bool remove = false); + + std::string GetDebugInfo() const; }; // Caches some information about caster (because it may no longer exist) |