mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 16:37:01 +00:00
[9388] Implement max cast chain length for triggered spells.
* New config option MaxSpellCastsInChain ( 0 is disabled old way work ) * Check added for prevent stack overflow crashes in case infinity triggered casts sequences with more useful error output instead crash. * Default config steeing in 10 casts expected to allow all possible in game proper cast chains.
This commit is contained in:
parent
574f396b0d
commit
58d188f21a
7 changed files with 45 additions and 1 deletions
|
|
@ -2522,6 +2522,19 @@ void Spell::cast(bool skipCheck)
|
||||||
{
|
{
|
||||||
SetExecutedCurrently(true);
|
SetExecutedCurrently(true);
|
||||||
|
|
||||||
|
if (!m_caster->CheckAndIncreaseCastCounter())
|
||||||
|
{
|
||||||
|
if (m_triggeredByAuraSpell)
|
||||||
|
sLog.outError("Spell %u triggered by aura spell %u too deep in cast chain for cast. Cast not allowed for prevent overflow stack crash.");
|
||||||
|
else
|
||||||
|
sLog.outError("Spell %u too deep in cast chain for cast. Cast not allowed for prevent overflow stack crash.");
|
||||||
|
|
||||||
|
SendCastResult(SPELL_FAILED_ERROR);
|
||||||
|
finish(false);
|
||||||
|
SetExecutedCurrently(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// update pointers base at GUIDs to prevent access to non-existed already object
|
// update pointers base at GUIDs to prevent access to non-existed already object
|
||||||
UpdatePointers();
|
UpdatePointers();
|
||||||
|
|
||||||
|
|
@ -2529,6 +2542,7 @@ void Spell::cast(bool skipCheck)
|
||||||
if(!m_targets.getUnitTarget() && m_targets.getUnitTargetGUID() && m_targets.getUnitTargetGUID() != m_caster->GetGUID())
|
if(!m_targets.getUnitTarget() && m_targets.getUnitTargetGUID() && m_targets.getUnitTargetGUID() != m_caster->GetGUID())
|
||||||
{
|
{
|
||||||
cancel();
|
cancel();
|
||||||
|
m_caster->DecreaseCastCounter();
|
||||||
SetExecutedCurrently(false);
|
SetExecutedCurrently(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2541,6 +2555,7 @@ void Spell::cast(bool skipCheck)
|
||||||
{
|
{
|
||||||
SendCastResult(castResult);
|
SendCastResult(castResult);
|
||||||
finish(false);
|
finish(false);
|
||||||
|
m_caster->DecreaseCastCounter();
|
||||||
SetExecutedCurrently(false);
|
SetExecutedCurrently(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2553,6 +2568,7 @@ void Spell::cast(bool skipCheck)
|
||||||
{
|
{
|
||||||
SendCastResult(castResult);
|
SendCastResult(castResult);
|
||||||
finish(false);
|
finish(false);
|
||||||
|
m_caster->DecreaseCastCounter();
|
||||||
SetExecutedCurrently(false);
|
SetExecutedCurrently(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2667,6 +2683,7 @@ void Spell::cast(bool skipCheck)
|
||||||
|
|
||||||
if(m_spellState == SPELL_STATE_FINISHED) // stop cast if spell marked as finish somewhere in FillTargetMap
|
if(m_spellState == SPELL_STATE_FINISHED) // stop cast if spell marked as finish somewhere in FillTargetMap
|
||||||
{
|
{
|
||||||
|
m_caster->DecreaseCastCounter();
|
||||||
SetExecutedCurrently(false);
|
SetExecutedCurrently(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2699,6 +2716,7 @@ void Spell::cast(bool skipCheck)
|
||||||
handle_immediate();
|
handle_immediate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_caster->DecreaseCastCounter();
|
||||||
SetExecutedCurrently(false);
|
SetExecutedCurrently(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,8 @@ Unit::Unit()
|
||||||
for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i)
|
for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i)
|
||||||
m_currentSpells[i] = NULL;
|
m_currentSpells[i] = NULL;
|
||||||
|
|
||||||
|
m_castCounter = 0;
|
||||||
|
|
||||||
m_addDmgOnce = 0;
|
m_addDmgOnce = 0;
|
||||||
|
|
||||||
for(int i = 0; i < MAX_TOTEM; ++i)
|
for(int i = 0; i < MAX_TOTEM; ++i)
|
||||||
|
|
@ -13435,3 +13437,14 @@ void Unit::CleanupDeletedAuras()
|
||||||
delete *itr;
|
delete *itr;
|
||||||
m_deletedAuras.clear();
|
m_deletedAuras.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Unit::CheckAndIncreaseCastCounter()
|
||||||
|
{
|
||||||
|
uint32 maxCasts = sWorld.getConfig(CONFIG_MAX_SPELL_CASTS_IN_CHAIN);
|
||||||
|
|
||||||
|
if (maxCasts && m_castCounter >= maxCasts)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
++m_castCounter;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -1520,6 +1520,9 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
Spell* GetCurrentSpell(CurrentSpellTypes spellType) const { return m_currentSpells[spellType]; }
|
Spell* GetCurrentSpell(CurrentSpellTypes spellType) const { return m_currentSpells[spellType]; }
|
||||||
Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
||||||
|
|
||||||
|
bool CheckAndIncreaseCastCounter();
|
||||||
|
void DecreaseCastCounter() { if (m_castCounter) --m_castCounter; }
|
||||||
|
|
||||||
uint32 m_addDmgOnce;
|
uint32 m_addDmgOnce;
|
||||||
uint64 m_TotemSlot[MAX_TOTEM];
|
uint64 m_TotemSlot[MAX_TOTEM];
|
||||||
uint64 m_ObjectSlot[4];
|
uint64 m_ObjectSlot[4];
|
||||||
|
|
@ -1848,6 +1851,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
||||||
uint32 m_CombatTimer;
|
uint32 m_CombatTimer;
|
||||||
|
|
||||||
Spell* m_currentSpells[CURRENT_MAX_SPELL];
|
Spell* m_currentSpells[CURRENT_MAX_SPELL];
|
||||||
|
uint32 m_castCounter; // count casts chain of triggered spells for prevent infinity cast crashes
|
||||||
|
|
||||||
UnitVisibility m_Visibility;
|
UnitVisibility m_Visibility;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -795,6 +795,8 @@ void World::LoadConfigSettings(bool reload)
|
||||||
m_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfig.GetBoolDefault("Instance.IgnoreRaid", false);
|
m_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfig.GetBoolDefault("Instance.IgnoreRaid", false);
|
||||||
|
|
||||||
m_configs[CONFIG_CAST_UNSTUCK] = sConfig.GetBoolDefault("CastUnstuck", true);
|
m_configs[CONFIG_CAST_UNSTUCK] = sConfig.GetBoolDefault("CastUnstuck", true);
|
||||||
|
m_configs[CONFIG_MAX_SPELL_CASTS_IN_CHAIN] = sConfig.GetIntDefault("MaxSpellCastsInChain", 10);
|
||||||
|
|
||||||
m_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfig.GetIntDefault("Instance.ResetTimeHour", 4);
|
m_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfig.GetIntDefault("Instance.ResetTimeHour", 4);
|
||||||
m_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfig.GetIntDefault("Instance.UnloadDelay", 30 * MINUTE * IN_MILISECONDS);
|
m_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfig.GetIntDefault("Instance.UnloadDelay", 30 * MINUTE * IN_MILISECONDS);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ enum WorldConfigs
|
||||||
CONFIG_INSTANCE_RESET_TIME_HOUR,
|
CONFIG_INSTANCE_RESET_TIME_HOUR,
|
||||||
CONFIG_INSTANCE_UNLOAD_DELAY,
|
CONFIG_INSTANCE_UNLOAD_DELAY,
|
||||||
CONFIG_CAST_UNSTUCK,
|
CONFIG_CAST_UNSTUCK,
|
||||||
|
CONFIG_MAX_SPELL_CASTS_IN_CHAIN,
|
||||||
CONFIG_MAX_PRIMARY_TRADE_SKILL,
|
CONFIG_MAX_PRIMARY_TRADE_SKILL,
|
||||||
CONFIG_MIN_PETITION_SIGNS,
|
CONFIG_MIN_PETITION_SIGNS,
|
||||||
CONFIG_GM_LOGIN_STATE,
|
CONFIG_GM_LOGIN_STATE,
|
||||||
|
|
|
||||||
|
|
@ -508,6 +508,12 @@ LogColors = ""
|
||||||
# Default: 1 (true)
|
# Default: 1 (true)
|
||||||
# 0 (false)
|
# 0 (false)
|
||||||
#
|
#
|
||||||
|
# MaxSpellCastsInChain
|
||||||
|
# Max amount triggered spell casts in chain by one caster, prevent stack overflow crash
|
||||||
|
# Too Low value will make some correct triggered casts fail
|
||||||
|
# 0 (no limit)
|
||||||
|
# Default: 10
|
||||||
|
#
|
||||||
# Instance.IgnoreLevel
|
# Instance.IgnoreLevel
|
||||||
# Ignore level requirement to enter instance
|
# Ignore level requirement to enter instance
|
||||||
# Default: 0 (false)
|
# Default: 0 (false)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "9387"
|
#define REVISION_NR "9388"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue