mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 22:37:03 +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);
|
||||
|
||||
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
|
||||
UpdatePointers();
|
||||
|
||||
|
|
@ -2529,6 +2542,7 @@ void Spell::cast(bool skipCheck)
|
|||
if(!m_targets.getUnitTarget() && m_targets.getUnitTargetGUID() && m_targets.getUnitTargetGUID() != m_caster->GetGUID())
|
||||
{
|
||||
cancel();
|
||||
m_caster->DecreaseCastCounter();
|
||||
SetExecutedCurrently(false);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2541,6 +2555,7 @@ void Spell::cast(bool skipCheck)
|
|||
{
|
||||
SendCastResult(castResult);
|
||||
finish(false);
|
||||
m_caster->DecreaseCastCounter();
|
||||
SetExecutedCurrently(false);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2553,6 +2568,7 @@ void Spell::cast(bool skipCheck)
|
|||
{
|
||||
SendCastResult(castResult);
|
||||
finish(false);
|
||||
m_caster->DecreaseCastCounter();
|
||||
SetExecutedCurrently(false);
|
||||
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
|
||||
{
|
||||
m_caster->DecreaseCastCounter();
|
||||
SetExecutedCurrently(false);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2699,6 +2716,7 @@ void Spell::cast(bool skipCheck)
|
|||
handle_immediate();
|
||||
}
|
||||
|
||||
m_caster->DecreaseCastCounter();
|
||||
SetExecutedCurrently(false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -208,6 +208,8 @@ Unit::Unit()
|
|||
for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i)
|
||||
m_currentSpells[i] = NULL;
|
||||
|
||||
m_castCounter = 0;
|
||||
|
||||
m_addDmgOnce = 0;
|
||||
|
||||
for(int i = 0; i < MAX_TOTEM; ++i)
|
||||
|
|
@ -13435,3 +13437,14 @@ void Unit::CleanupDeletedAuras()
|
|||
delete *itr;
|
||||
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* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
||||
|
||||
bool CheckAndIncreaseCastCounter();
|
||||
void DecreaseCastCounter() { if (m_castCounter) --m_castCounter; }
|
||||
|
||||
uint32 m_addDmgOnce;
|
||||
uint64 m_TotemSlot[MAX_TOTEM];
|
||||
uint64 m_ObjectSlot[4];
|
||||
|
|
@ -1848,6 +1851,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
|||
uint32 m_CombatTimer;
|
||||
|
||||
Spell* m_currentSpells[CURRENT_MAX_SPELL];
|
||||
uint32 m_castCounter; // count casts chain of triggered spells for prevent infinity cast crashes
|
||||
|
||||
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_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_UNLOAD_DELAY] = sConfig.GetIntDefault("Instance.UnloadDelay", 30 * MINUTE * IN_MILISECONDS);
|
||||
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ enum WorldConfigs
|
|||
CONFIG_INSTANCE_RESET_TIME_HOUR,
|
||||
CONFIG_INSTANCE_UNLOAD_DELAY,
|
||||
CONFIG_CAST_UNSTUCK,
|
||||
CONFIG_MAX_SPELL_CASTS_IN_CHAIN,
|
||||
CONFIG_MAX_PRIMARY_TRADE_SKILL,
|
||||
CONFIG_MIN_PETITION_SIGNS,
|
||||
CONFIG_GM_LOGIN_STATE,
|
||||
|
|
|
|||
|
|
@ -508,6 +508,12 @@ LogColors = ""
|
|||
# Default: 1 (true)
|
||||
# 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
|
||||
# Ignore level requirement to enter instance
|
||||
# Default: 0 (false)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "9387"
|
||||
#define REVISION_NR "9388"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue