Core/Spells: Protect against stack overflows in spell override handling
Port From (https://github.com/TrinityCore/TrinityCore/commit/723e638a84d2aebe8a41fc39ba94f1a04138797e)
This commit is contained in:
@@ -274,20 +274,23 @@ namespace Game.Entities
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override SpellInfo GetCastSpellInfo(SpellInfo spellInfo, TriggerCastFlags triggerFlag)
|
public override SpellInfo GetCastSpellInfo(SpellInfo spellInfo, TriggerCastFlags triggerFlag, GetCastSpellInfoContext context)
|
||||||
{
|
{
|
||||||
var overrides = m_overrideSpells.LookupByKey(spellInfo.Id);
|
var overrides = m_overrideSpells.LookupByKey(spellInfo.Id);
|
||||||
if (!overrides.Empty())
|
if (!overrides.Empty())
|
||||||
{
|
{
|
||||||
foreach (uint spellId in overrides)
|
foreach (uint spellId in overrides)
|
||||||
{
|
{
|
||||||
SpellInfo newInfo = Global.SpellMgr.GetSpellInfo(spellId, GetMap().GetDifficultyID());
|
if (context.AddSpell(spellId))
|
||||||
if (newInfo != null)
|
{
|
||||||
return GetCastSpellInfo(newInfo, triggerFlag);
|
SpellInfo newInfo = Global.SpellMgr.GetSpellInfo(spellId, GetMap().GetDifficultyID());
|
||||||
|
if (newInfo != null)
|
||||||
|
return GetCastSpellInfo(newInfo, triggerFlag, context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.GetCastSpellInfo(spellInfo, triggerFlag);
|
return base.GetCastSpellInfo(spellInfo, triggerFlag, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetOverrideSpellsId(uint overrideSpellsId) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.OverrideSpellsID), overrideSpellsId); }
|
public void SetOverrideSpellsId(uint overrideSpellsId) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.OverrideSpellsID), overrideSpellsId); }
|
||||||
@@ -3879,7 +3882,8 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check possible spell cast overrides
|
// Check possible spell cast overrides
|
||||||
spellInfo = castingUnit.GetCastSpellInfo(spellInfo, triggerFlag);
|
GetCastSpellInfoContext overrideContext = new();
|
||||||
|
spellInfo = castingUnit.GetCastSpellInfo(spellInfo, triggerFlag, overrideContext);
|
||||||
if (spellInfo.IsPassive())
|
if (spellInfo.IsPassive())
|
||||||
{
|
{
|
||||||
CancelPendingCastRequest();
|
CancelPendingCastRequest();
|
||||||
|
|||||||
@@ -944,14 +944,14 @@ namespace Game.Entities
|
|||||||
spell.Finish(result);
|
spell.Finish(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual SpellInfo GetCastSpellInfo(SpellInfo spellInfo, TriggerCastFlags triggerFlag)
|
public virtual SpellInfo GetCastSpellInfo(SpellInfo spellInfo, TriggerCastFlags triggerFlag, GetCastSpellInfoContext context)
|
||||||
{
|
{
|
||||||
SpellInfo findMatchingAuraEffectIn(AuraType type)
|
SpellInfo findMatchingAuraEffectIn(AuraType type)
|
||||||
{
|
{
|
||||||
foreach (AuraEffect auraEffect in GetAuraEffectsByType(type))
|
foreach (AuraEffect auraEffect in GetAuraEffectsByType(type))
|
||||||
{
|
{
|
||||||
bool matches = auraEffect.GetMiscValue() != 0 ? auraEffect.GetMiscValue() == spellInfo.Id : auraEffect.IsAffectingSpell(spellInfo);
|
bool matches = auraEffect.GetMiscValue() != 0 ? auraEffect.GetMiscValue() == spellInfo.Id : auraEffect.IsAffectingSpell(spellInfo);
|
||||||
if (matches)
|
if (matches && context.AddSpell((uint)auraEffect.GetAmount()))
|
||||||
{
|
{
|
||||||
SpellInfo info = Global.SpellMgr.GetSpellInfo((uint)auraEffect.GetAmount(), GetMap().GetDifficultyID());
|
SpellInfo info = Global.SpellMgr.GetSpellInfo((uint)auraEffect.GetAmount(), GetMap().GetDifficultyID());
|
||||||
if (info != null)
|
if (info != null)
|
||||||
@@ -979,14 +979,14 @@ namespace Game.Entities
|
|||||||
if (newInfo != null)
|
if (newInfo != null)
|
||||||
{
|
{
|
||||||
triggerFlag &= ~TriggerCastFlags.IgnoreCastTime;
|
triggerFlag &= ~TriggerCastFlags.IgnoreCastTime;
|
||||||
return GetCastSpellInfo(newInfo, triggerFlag);
|
return GetCastSpellInfo(newInfo, triggerFlag, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
newInfo = findMatchingAuraEffectIn(AuraType.OverrideActionbarSpellsTriggered);
|
newInfo = findMatchingAuraEffectIn(AuraType.OverrideActionbarSpellsTriggered);
|
||||||
if (newInfo != null)
|
if (newInfo != null)
|
||||||
{
|
{
|
||||||
triggerFlag |= TriggerCastFlags.IgnoreCastTime;
|
triggerFlag |= TriggerCastFlags.IgnoreCastTime;
|
||||||
return GetCastSpellInfo(newInfo, triggerFlag);
|
return GetCastSpellInfo(newInfo, triggerFlag, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return spellInfo;
|
return spellInfo;
|
||||||
@@ -4602,4 +4602,26 @@ namespace Game.Entities
|
|||||||
public void SetVisibleAuraUpdate(AuraApplication aurApp) { m_visibleAurasToUpdate.Add(aurApp); }
|
public void SetVisibleAuraUpdate(AuraApplication aurApp) { m_visibleAurasToUpdate.Add(aurApp); }
|
||||||
public void RemoveVisibleAuraUpdate(AuraApplication aurApp) { m_visibleAurasToUpdate.Remove(aurApp); }
|
public void RemoveVisibleAuraUpdate(AuraApplication aurApp) { m_visibleAurasToUpdate.Remove(aurApp); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class GetCastSpellInfoContext
|
||||||
|
{
|
||||||
|
uint[] VisitedSpells = new uint[5];
|
||||||
|
|
||||||
|
public bool AddSpell(uint spellId)
|
||||||
|
{
|
||||||
|
if (VisitedSpells.Contains(spellId))
|
||||||
|
return false; // already exists
|
||||||
|
|
||||||
|
for (int i = 0; i < VisitedSpells.Length; ++i)
|
||||||
|
{
|
||||||
|
if (VisitedSpells[i] != 0u)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
VisitedSpells[i] = spellId;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user