Fixes aura infinite loop
Port From (https://github.com/TrinityCore/TrinityCore/commit/9cb01a79046fce3f76835bb68bf66e4f3079e4bc)
This commit is contained in:
@@ -24,6 +24,7 @@ using Game.Spells;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Game.Entities
|
namespace Game.Entities
|
||||||
{
|
{
|
||||||
@@ -3345,12 +3346,44 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
// this may be a dead loop if some events on aura remove will continiously apply aura on remove
|
// 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
|
// we want to have all auras removed, so use your brain when linking events
|
||||||
while (!m_appliedAuras.Empty())
|
for (int counter = 0; !m_appliedAuras.Empty() || !m_ownedAuras.Empty(); counter++)
|
||||||
_UnapplyAura(m_appliedAuras.FirstOrDefault(), AuraRemoveMode.Default);
|
{
|
||||||
|
foreach (var aurAppIter in GetAppliedAuras())
|
||||||
|
_UnapplyAura(aurAppIter, AuraRemoveMode.Default);
|
||||||
|
|
||||||
while (!m_ownedAuras.Empty())
|
foreach (var aurIter in GetOwnedAuras())
|
||||||
RemoveOwnedAura(m_ownedAuras.FirstOrDefault());
|
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)
|
||||||
|
{
|
||||||
|
StringBuilder sstr = new();
|
||||||
|
sstr.AppendLine($"Unit::RemoveAllAuras() iterated {maxIteration} times already but there are still {m_appliedAuras.Count} m_appliedAuras and {m_ownedAuras.Count} m_ownedAuras. Details:");
|
||||||
|
sstr.AppendLine(GetDebugInfo());
|
||||||
|
|
||||||
|
if (!m_appliedAuras.Empty())
|
||||||
|
{
|
||||||
|
sstr.AppendLine("m_appliedAuras:");
|
||||||
|
|
||||||
|
foreach (var auraAppPair in GetAppliedAuras())
|
||||||
|
sstr.AppendLine(auraAppPair.Value.GetDebugInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_ownedAuras.Empty())
|
||||||
|
{
|
||||||
|
sstr.AppendLine("m_ownedAuras:");
|
||||||
|
|
||||||
|
foreach (var auraPair in GetOwnedAuras())
|
||||||
|
sstr.AppendLine(auraPair.Value.GetDebugInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.outError(LogFilter.Unit, sstr.ToString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveArenaAuras()
|
public void RemoveArenaAuras()
|
||||||
{
|
{
|
||||||
// in join, remove positive buffs, on end, remove negative
|
// in join, remove positive buffs, on end, remove negative
|
||||||
@@ -3364,6 +3397,7 @@ namespace Game.Entities
|
|||||||
aura.GetSpellInfo().HasAttribute(SpellAttr5.RemoveEnteringArena); // special marker, always remove
|
aura.GetSpellInfo().HasAttribute(SpellAttr5.RemoveEnteringArena); // special marker, always remove
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveAllAurasExceptType(AuraType type)
|
public void RemoveAllAurasExceptType(AuraType type)
|
||||||
{
|
{
|
||||||
foreach (var pair in GetAppliedAuras())
|
foreach (var pair in GetAppliedAuras())
|
||||||
@@ -3385,6 +3419,7 @@ namespace Game.Entities
|
|||||||
RemoveOwnedAura(pair, AuraRemoveMode.Default);
|
RemoveOwnedAura(pair, AuraRemoveMode.Default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveAllAurasExceptType(AuraType type1, AuraType type2)
|
public void RemoveAllAurasExceptType(AuraType type1, AuraType type2)
|
||||||
{
|
{
|
||||||
foreach (var pair in GetAppliedAuras())
|
foreach (var pair in GetAppliedAuras())
|
||||||
|
|||||||
@@ -299,6 +299,11 @@ namespace Game.Spells
|
|||||||
_target.SendMessageToSet(update, true);
|
_target.SendMessageToSet(update, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetDebugInfo()
|
||||||
|
{
|
||||||
|
return $"Base: {(GetBase() != null ? GetBase().GetDebugInfo() : "NULL")}\nTarget: {(GetTarget() != null ? GetTarget().GetDebugInfo() : "NULL")}";
|
||||||
|
}
|
||||||
|
|
||||||
public Unit GetTarget() { return _target; }
|
public Unit GetTarget() { return _target; }
|
||||||
public Aura GetBase() { return _base; }
|
public Aura GetBase() { return _base; }
|
||||||
|
|
||||||
|
|||||||
@@ -924,8 +924,9 @@ namespace Game.Spells
|
|||||||
target.m_invisibilityDetect.AddValue(type, -GetAmount());
|
target.m_invisibilityDetect.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
|
||||||
target.UpdateObjectVisibility();
|
if (target.IsInWorld)
|
||||||
|
target.UpdateObjectVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
[AuraEffectHandler(AuraType.ModInvisibility)]
|
[AuraEffectHandler(AuraType.ModInvisibility)]
|
||||||
@@ -978,13 +979,15 @@ namespace Game.Spells
|
|||||||
target.m_invisibility.AddValue(type, -GetAmount());
|
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.HasAnyFlag(AuraEffectHandleModes.Real))
|
if (apply && mode.HasAnyFlag(AuraEffectHandleModes.Real))
|
||||||
{
|
{
|
||||||
// drop flag at invisibiliy in bg
|
// drop flag at invisibiliy in bg
|
||||||
target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.StealthOrInvis);
|
target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.StealthOrInvis);
|
||||||
}
|
}
|
||||||
target.UpdateObjectVisibility();
|
|
||||||
|
if (target.IsInWorld)
|
||||||
|
target.UpdateObjectVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
[AuraEffectHandler(AuraType.ModStealthDetect)]
|
[AuraEffectHandler(AuraType.ModStealthDetect)]
|
||||||
@@ -1009,8 +1012,9 @@ namespace Game.Spells
|
|||||||
target.m_stealthDetect.AddValue(type, -GetAmount());
|
target.m_stealthDetect.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
|
||||||
target.UpdateObjectVisibility();
|
if (target.IsInWorld)
|
||||||
|
target.UpdateObjectVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
[AuraEffectHandler(AuraType.ModStealth)]
|
[AuraEffectHandler(AuraType.ModStealth)]
|
||||||
@@ -1046,13 +1050,15 @@ namespace Game.Spells
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.HasAnyFlag(AuraEffectHandleModes.Real))
|
if (apply && mode.HasAnyFlag(AuraEffectHandleModes.Real))
|
||||||
{
|
{
|
||||||
// drop flag at stealth in bg
|
// drop flag at stealth in bg
|
||||||
target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.StealthOrInvis);
|
target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.StealthOrInvis);
|
||||||
}
|
}
|
||||||
target.UpdateObjectVisibility();
|
|
||||||
|
if (target.IsInWorld)
|
||||||
|
target.UpdateObjectVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
[AuraEffectHandler(AuraType.ModStealthLevel)]
|
[AuraEffectHandler(AuraType.ModStealthLevel)]
|
||||||
@@ -1069,8 +1075,9 @@ namespace Game.Spells
|
|||||||
else
|
else
|
||||||
target.m_stealth.AddValue(type, -GetAmount());
|
target.m_stealth.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
|
||||||
target.UpdateObjectVisibility();
|
if (target.IsInWorld)
|
||||||
|
target.UpdateObjectVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
[AuraEffectHandler(AuraType.DetectAmore)]
|
[AuraEffectHandler(AuraType.DetectAmore)]
|
||||||
@@ -1133,7 +1140,7 @@ namespace Game.Spells
|
|||||||
}
|
}
|
||||||
// die at aura end
|
// die at aura end
|
||||||
else if (target.IsAlive())
|
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(DeathState.JustDied);
|
target.SetDeathState(DeathState.JustDied);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1709,7 +1716,7 @@ namespace Game.Spells
|
|||||||
else
|
else
|
||||||
target.RemoveUnitFlag(UnitFlags.NonAttackable2);
|
target.RemoveUnitFlag(UnitFlags.NonAttackable2);
|
||||||
|
|
||||||
// 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.HasAnyFlag(AuraEffectHandleModes.Real))
|
if (apply && mode.HasAnyFlag(AuraEffectHandleModes.Real))
|
||||||
{
|
{
|
||||||
if (target.GetMap().IsDungeon())
|
if (target.GetMap().IsDungeon())
|
||||||
@@ -1810,7 +1817,7 @@ namespace Game.Spells
|
|||||||
{
|
{
|
||||||
target.AddUnitFlag(UnitFlags.Silenced);
|
target.AddUnitFlag(UnitFlags.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
|
// Stop cast only spells vs PreventionType & SPELL_PREVENTION_TYPE_SILENCE
|
||||||
for (var i = CurrentSpellTypes.Melee; i < CurrentSpellTypes.Max; ++i)
|
for (var i = CurrentSpellTypes.Melee; i < CurrentSpellTypes.Max; ++i)
|
||||||
{
|
{
|
||||||
@@ -1889,7 +1896,7 @@ namespace Game.Spells
|
|||||||
{
|
{
|
||||||
target.AddUnitFlag2(UnitFlags2.NoActions);
|
target.AddUnitFlag2(UnitFlags2.NoActions);
|
||||||
|
|
||||||
// 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
|
// Stop cast only spells vs PreventionType & SPELL_PREVENTION_TYPE_SILENCE
|
||||||
for (var i = CurrentSpellTypes.Melee; i < CurrentSpellTypes.Max; ++i)
|
for (var i = CurrentSpellTypes.Melee; i < CurrentSpellTypes.Max; ++i)
|
||||||
{
|
{
|
||||||
@@ -1969,8 +1976,9 @@ namespace Game.Spells
|
|||||||
target.RemoveDynamicFlag(UnitDynFlags.TrackUnit);
|
target.RemoveDynamicFlag(UnitDynFlags.TrackUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.UpdateObjectVisibility();
|
if (target.IsInWorld)
|
||||||
|
target.UpdateObjectVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
[AuraEffectHandler(AuraType.Untrackable)]
|
[AuraEffectHandler(AuraType.Untrackable)]
|
||||||
@@ -4769,8 +4777,9 @@ namespace Game.Spells
|
|||||||
target.m_invisibilityDetect.DelFlag(InvisibilityType.Drunk);
|
target.m_invisibilityDetect.DelFlag(InvisibilityType.Drunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.UpdateObjectVisibility();
|
if (target.IsInWorld)
|
||||||
|
target.UpdateObjectVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
[AuraEffectHandler(AuraType.OverrideSpells)]
|
[AuraEffectHandler(AuraType.OverrideSpells)]
|
||||||
|
|||||||
Reference in New Issue
Block a user