Core/ScriptSystem:

Add basic code for runtime checks of function calls in AuraScripts
 Make AuraScript::PreventDefaultAction() do not take parameters and add description for the function
 Remove PreventDefaultEffect() from aura script, use PreventDefaultAction() instead
 Unload aura scripts memory on aura delete

--HG--
branch : trunk
This commit is contained in:
QAston
2010-10-04 17:44:49 +02:00
parent 5adaf5887e
commit caaa77deb2
8 changed files with 178 additions and 42 deletions

View File

@@ -5234,15 +5234,17 @@ void ObjectMgr::ValidateSpellScripts()
}
if (spellScript)
{
spellScript->Register();
if (!spellScript->_Validate(spellEntry, sObjectMgr.GetScriptName(sitr->second->second)))
spellScript->_Init(&sitr->first->GetName(), spellEntry->Id);
spellScript->_Register();
if (!spellScript->_Validate(spellEntry))
valid = false;
delete spellScript;
}
if (auraScript)
{
auraScript->Register();
if (!auraScript->_Validate(spellEntry, sObjectMgr.GetScriptName(sitr->second->second)))
auraScript->_Init(&sitr->first->GetName(), spellEntry->Id);
auraScript->_Register();
if (!auraScript->_Validate(spellEntry))
valid = false;
delete auraScript;
}

View File

@@ -307,6 +307,8 @@ void ScriptMgr::CreateSpellScripts(uint32 spell_id, std::list<SpellScript *> & s
if (!script)
continue;
script->_Init(&tmpscript->GetName(), spell_id);
script_vector.push_back(script);
}
}
@@ -326,6 +328,8 @@ void ScriptMgr::CreateAuraScripts(uint32 spell_id, std::list<AuraScript *> & scr
if (!script)
continue;
script->_Init(&tmpscript->GetName(), spell_id);
script_vector.push_back(script);
}
}

View File

@@ -366,6 +366,15 @@ m_isRemoved(false), m_isSingleTarget(false)
Aura::~Aura()
{
// unload scripts
while(!m_loadedScripts.empty())
{
std::list<AuraScript *>::iterator itr = m_loadedScripts.begin();
(*itr)->_Unload();
delete (*itr);
m_loadedScripts.erase(itr);
}
// free effects memory
for (uint8 i = 0 ; i < MAX_SPELL_EFFECTS; ++i)
delete m_effects[i];
@@ -1640,7 +1649,7 @@ bool Aura::CallScriptEffectApplyHandlers(AuraEffect const * aurEff, AuraApplicat
bool preventDefault = false;
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
(*scritr)->_ResetDefault();
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY);
std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->OnEffectApply.end(), effItr = (*scritr)->OnEffectApply.begin();
for(; effItr != effEndItr ; ++effItr)
{
@@ -1648,7 +1657,8 @@ bool Aura::CallScriptEffectApplyHandlers(AuraEffect const * aurEff, AuraApplicat
(*effItr).Call(*scritr, aurEff, aurApp, mode);
}
if (!preventDefault)
preventDefault = (*scritr)->_IsDefaultActionPrevented((SpellEffIndex)aurEff->GetEffIndex());
preventDefault = (*scritr)->_IsDefaultActionPrevented();
(*scritr)->_FinishScriptCall();
}
return preventDefault;
}
@@ -1658,7 +1668,7 @@ bool Aura::CallScriptEffectRemoveHandlers(AuraEffect const * aurEff, AuraApplica
bool preventDefault = false;
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
(*scritr)->_ResetDefault();
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE);
std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->OnEffectRemove.end(), effItr = (*scritr)->OnEffectRemove.begin();
for(; effItr != effEndItr ; ++effItr)
{
@@ -1666,7 +1676,8 @@ bool Aura::CallScriptEffectRemoveHandlers(AuraEffect const * aurEff, AuraApplica
(*effItr).Call(*scritr, aurEff, aurApp, mode);
}
if (!preventDefault)
preventDefault = (*scritr)->_IsDefaultActionPrevented((SpellEffIndex)aurEff->GetEffIndex());
preventDefault = (*scritr)->_IsDefaultActionPrevented();
(*scritr)->_FinishScriptCall();
}
return preventDefault;
}
@@ -1676,7 +1687,7 @@ bool Aura::CallScriptEffectPeriodicHandlers(AuraEffect const * aurEff, AuraAppli
bool preventDefault = false;
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
(*scritr)->_ResetDefault();
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PERIODIC);
std::list<AuraScript::EffectPeriodicHandler>::iterator effEndItr = (*scritr)->OnEffectPeriodic.end(), effItr = (*scritr)->OnEffectPeriodic.begin();
for(; effItr != effEndItr ; ++effItr)
{
@@ -1684,7 +1695,8 @@ bool Aura::CallScriptEffectPeriodicHandlers(AuraEffect const * aurEff, AuraAppli
(*effItr).Call(*scritr, aurEff, aurApp);
}
if (!preventDefault)
preventDefault = (*scritr)->_IsDefaultActionPrevented((SpellEffIndex)aurEff->GetEffIndex());
preventDefault = (*scritr)->_IsDefaultActionPrevented();
(*scritr)->_FinishScriptCall();
}
return preventDefault;
}
@@ -1693,12 +1705,14 @@ void Aura::CallScriptEffectUpdatePeriodicHandlers(AuraEffect * aurEff)
{
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC);
std::list<AuraScript::EffectUpdatePeriodicHandler>::iterator effEndItr = (*scritr)->OnEffectUpdatePeriodic.end(), effItr = (*scritr)->OnEffectUpdatePeriodic.begin();
for(; effItr != effEndItr ; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
(*effItr).Call(*scritr, aurEff);
}
(*scritr)->_FinishScriptCall();
}
}
@@ -1706,12 +1720,14 @@ void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const * aurEff, int32 &
{
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT);
std::list<AuraScript::EffectCalcAmountHandler>::iterator effEndItr = (*scritr)->OnEffectCalcAmount.end(), effItr = (*scritr)->OnEffectCalcAmount.begin();
for(; effItr != effEndItr ; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
(*effItr).Call(*scritr, aurEff, amount, canBeRecalculated);
}
(*scritr)->_FinishScriptCall();
}
}
@@ -1719,12 +1735,14 @@ void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const * aurEff, bool
{
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC);
std::list<AuraScript::EffectCalcPeriodicHandler>::iterator effEndItr = (*scritr)->OnEffectCalcPeriodic.end(), effItr = (*scritr)->OnEffectCalcPeriodic.begin();
for(; effItr != effEndItr ; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
(*effItr).Call(*scritr, aurEff, isPeriodic, amplitude);
}
(*scritr)->_FinishScriptCall();
}
}
@@ -1732,12 +1750,14 @@ void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const * aurEff, Spell
{
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD);
std::list<AuraScript::EffectCalcSpellModHandler>::iterator effEndItr = (*scritr)->OnEffectCalcSpellMod.end(), effItr = (*scritr)->OnEffectCalcSpellMod.begin();
for(; effItr != effEndItr ; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
(*effItr).Call(*scritr, aurEff, spellMod);
}
(*scritr)->_FinishScriptCall();
}
}

View File

@@ -541,10 +541,11 @@ Spell::~Spell()
while(!m_loadedScripts.empty())
{
std::list<SpellScript *>::iterator itr = m_loadedScripts.begin();
(*itr)->Unload();
(*itr)->_Unload();
delete (*itr);
m_loadedScripts.erase(itr);
}
if (m_referencedFromCurrentSpell && m_selfContainer && *m_selfContainer == this)
{
// Clean the reference to avoid later crash.

View File

@@ -21,16 +21,37 @@
#include "SpellAuras.h"
#include "SpellScript.h"
bool _SpellScript::_Validate(SpellEntry const * entry, const char * scriptname)
bool _SpellScript::_Validate(SpellEntry const * entry)
{
if (!Validate(entry))
{
sLog.outError("TSCR: Spell `%u` did not pass Validate() function of script `%s` - script will be not added to the spell", entry->Id, scriptname);
sLog.outError("TSCR: Spell `%u` did not pass Validate() function of script `%s` - script will be not added to the spell", entry->Id, m_scriptName->c_str());
return false;
}
return true;
}
void _SpellScript::_Register()
{
m_currentScriptState = SPELL_SCRIPT_STATE_REGISTRATION;
Register();
m_currentScriptState = SPELL_SCRIPT_STATE_NONE;
}
void _SpellScript::_Unload()
{
m_currentScriptState = SPELL_SCRIPT_STATE_UNLOADING;
Unload();
m_currentScriptState = SPELL_SCRIPT_STATE_NONE;
}
void _SpellScript::_Init(const std::string * scriptname, uint32 spellId)
{
m_currentScriptState = SPELL_SCRIPT_STATE_NONE;
m_scriptName = scriptname;
m_scriptSpellId = spellId;
}
_SpellScript::EffectHook::EffectHook(uint8 _effIndex)
{
// effect index must be in range <0;2>, allow use of special effindexes
@@ -147,22 +168,25 @@ void SpellScript::EffectHandler::Call(SpellScript * spellScript, SpellEffIndex e
(spellScript->*pEffectHandlerScript)(effIndex);
}
bool SpellScript::_Validate(SpellEntry const * entry, const char * scriptname)
bool SpellScript::_Validate(SpellEntry const * entry)
{
for (std::list<EffectHandler>::iterator itr = OnEffect.begin(); itr != OnEffect.end(); ++itr)
{
if (!(*itr).GetAffectedEffectsMask(entry))
{
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), scriptname);
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
}
}
return _SpellScript::_Validate(entry, scriptname);
return _SpellScript::_Validate(entry);
}
bool SpellScript::_Load(Spell * spell)
{
m_currentScriptState = SPELL_SCRIPT_STATE_LOADING;
m_spell = spell;
return Load();
bool load = Load();
m_currentScriptState = SPELL_SCRIPT_STATE_NONE;
return load;
}
void SpellScript::_InitHit()
@@ -285,37 +309,37 @@ void SpellScript::CreateItem(uint32 effIndex, uint32 itemId)
m_spell->DoCreateItem(effIndex, itemId);
}
bool AuraScript::_Validate(SpellEntry const * entry, const char * scriptname)
bool AuraScript::_Validate(SpellEntry const * entry)
{
for (std::list<EffectApplyHandler>::iterator itr = OnEffectApply.begin(); itr != OnEffectApply.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), scriptname);
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<EffectApplyHandler>::iterator itr = OnEffectRemove.begin(); itr != OnEffectRemove.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), scriptname);
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<EffectPeriodicHandler>::iterator itr = OnEffectPeriodic.begin(); itr != OnEffectPeriodic.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), scriptname);
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<EffectUpdatePeriodicHandler>::iterator itr = OnEffectUpdatePeriodic.begin(); itr != OnEffectUpdatePeriodic.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), scriptname);
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<EffectCalcAmountHandler>::iterator itr = OnEffectCalcAmount.begin(); itr != OnEffectCalcAmount.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), scriptname);
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<EffectCalcPeriodicHandler>::iterator itr = OnEffectCalcPeriodic.begin(); itr != OnEffectCalcPeriodic.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), scriptname);
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<EffectCalcSpellModHandler>::iterator itr = OnEffectCalcSpellMod.begin(); itr != OnEffectCalcSpellMod.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), scriptname);
sLog.outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
return _SpellScript::_Validate(entry, scriptname);
return _SpellScript::_Validate(entry);
}
AuraScript::EffectBase::EffectBase(uint8 _effIndex, uint16 _effName)
@@ -403,8 +427,59 @@ void AuraScript::EffectApplyHandler::Call(AuraScript * auraScript, AuraEffect co
bool AuraScript::_Load(Aura * aura)
{
m_currentScriptState = SPELL_SCRIPT_STATE_LOADING;
m_aura = aura;
return Load();
bool load = Load();
m_currentScriptState = SPELL_SCRIPT_STATE_NONE;
return load;
}
void AuraScript::_PrepareScriptCall(AuraScriptHookType hookType)
{
m_currentScriptState = hookType;
switch (m_currentScriptState)
{
case AURA_SCRIPT_HOOK_EFFECT_APPLY:
case AURA_SCRIPT_HOOK_EFFECT_REMOVE:
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
m_defaultActionPrevented = false;
break;
default:
break;
}
}
void AuraScript::_FinishScriptCall()
{
m_currentScriptState = SPELL_SCRIPT_STATE_NONE;
}
bool AuraScript::_IsDefaultActionPrevented()
{
switch (m_currentScriptState)
{
case AURA_SCRIPT_HOOK_EFFECT_APPLY:
case AURA_SCRIPT_HOOK_EFFECT_REMOVE:
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
return m_defaultActionPrevented;
default:
return false;
}
}
void AuraScript::PreventDefaultAction()
{
switch (m_currentScriptState)
{
case AURA_SCRIPT_HOOK_EFFECT_APPLY:
case AURA_SCRIPT_HOOK_EFFECT_REMOVE:
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
m_defaultActionPrevented = true;
break;
default:
sLog.outError("TSCR: Script: `%s` Spell: `%u` AuraScript::PreventDefaultAction called in a hook in which the call won't have effect!", m_scriptName->c_str(), m_scriptSpellId);
break;
}
}
SpellEntry const* AuraScript::GetSpellProto() const

View File

@@ -41,13 +41,26 @@ class WorldObject;
#define SPELL_EFFECT_ANY (uint16)-1
#define SPELL_AURA_ANY (uint16)-1
enum SpellScriptState
{
SPELL_SCRIPT_STATE_NONE = 0,
SPELL_SCRIPT_STATE_REGISTRATION,
SPELL_SCRIPT_STATE_LOADING,
SPELL_SCRIPT_STATE_UNLOADING,
};
#define SPELL_SCRIPT_STATE_END SPELL_SCRIPT_STATE_UNLOADING + 1
// helper class from which SpellScript and SpellAura derive, use these classes instead
class _SpellScript
{
// internal use classes & functions
// DO NOT OVERRIDE THESE IN SCRIPTS
protected:
virtual bool _Validate(SpellEntry const * entry, const char * scriptname);
virtual bool _Validate(SpellEntry const * entry);
public:
virtual void _Register();
virtual void _Unload();
virtual void _Init(const std::string * scriptname, uint32 spellId);
protected:
class EffectHook
{
@@ -78,6 +91,10 @@ class _SpellScript
private:
uint16 effAurName;
};
uint8 m_currentScriptState;
const std::string * m_scriptName;
uint32 m_scriptSpellId;
public:
//
// SpellScript/AuraScript interface base
@@ -116,7 +133,7 @@ class SpellScript : public _SpellScript
};
typedef SpellHitFnType HitHandler;
public:
bool _Validate(SpellEntry const * entry, const char * scriptname);
bool _Validate(SpellEntry const * entry);
bool _Load(Spell * spell);
void _InitHit();
bool _IsEffectPrevented(SpellEffIndex effIndex) {return m_hitPreventEffectMask & (1<<effIndex);};
@@ -209,6 +226,23 @@ class SpellScript : public _SpellScript
void CreateItem(uint32 effIndex, uint32 itemId);
};
// AuraScript interface - enum used for manipulations on hooks by their type
enum AuraScriptHookType
{
AURA_SCRIPT_HOOK_EFFECT_APPLY = SPELL_SCRIPT_STATE_END,
AURA_SCRIPT_HOOK_EFFECT_REMOVE,
AURA_SCRIPT_HOOK_EFFECT_PERIODIC,
AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC,
AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT,
AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC,
AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD,
/*AURA_SCRIPT_HOOK_APPLY,
AURA_SCRIPT_HOOK_REMOVE,*/
};
#define HOOK_AURA_EFFECT_START HOOK_AURA_EFFECT_APPLY
#define HOOK_AURA_EFFECT_END HOOK_AURA_EFFECT_CALC_SPELLMOD + 1
#define HOOK_AURA_EFFECT_COUNT HOOK_AURA_EFFECT_END - HOOK_AURA_EFFECT_START
class AuraScript : public _SpellScript
{
// internal use classes & functions
@@ -278,20 +312,14 @@ class AuraScript : public _SpellScript
AuraEffectHandleModes mode;
};
public:
bool _Validate(SpellEntry const * entry, const char * scriptname);
bool _Validate(SpellEntry const * entry);
bool _Load(Aura * aura);
void _ResetDefault() { m_defaultPreventedActionsMask = 0; }
bool _IsDefaultActionPrevented(SpellEffIndex effIndex)
{
uint8 effIndexMask = 1 << effIndex;
return (m_defaultPreventedActionsMask & effIndexMask) || (m_defaultPreventedEffectsMask & effIndexMask);
}
void PreventDefaultAction(SpellEffIndex effIndex) { m_defaultPreventedActionsMask |= 1 << effIndex; }
void PreventDefaultEffect(SpellEffIndex effIndex) { m_defaultPreventedEffectsMask |= 1 << effIndex; }
void _PrepareScriptCall(AuraScriptHookType hookType);
void _FinishScriptCall();
bool _IsDefaultActionPrevented();
private:
Aura * m_aura;
uint8 m_defaultPreventedActionsMask;
uint8 m_defaultPreventedEffectsMask;
bool m_defaultActionPrevented;
public:
//
// AuraScript interface
@@ -338,6 +366,11 @@ class AuraScript : public _SpellScript
HookList<EffectCalcSpellModHandler> OnEffectCalcSpellMod;
#define AuraEffectCalcSpellModFn(F, I, N) EffectCalcSpellModHandler((AuraEffectCalcSpellModFnType)&F, I, N)
// AuraScript interface - hook/effect execution manipulators
// prevents default action of a hook from being executed (works only while called in a hook which default action can be prevented)
void PreventDefaultAction();
// AuraScript interface - functions which are redirecting to Aura class
// returns proto of the spell

View File

@@ -961,11 +961,12 @@ class spell_deathbringer_blood_link_aura : public SpellScriptLoader
if (GetUnitOwner()->getPowerType() == POWER_ENERGY && GetUnitOwner()->GetPower(POWER_ENERGY) == GetUnitOwner()->GetMaxPower(POWER_ENERGY))
if (Creature* saurfang = GetUnitOwner()->ToCreature())
saurfang->AI()->DoAction(ACTION_MARK_OF_THE_FALLEN_CHAMPION);
PreventDefaultAction();
}
void Register()
{
PreventDefaultEffect(EFFECT_1);
OnEffectPeriodic += AuraEffectPeriodicFn(spell_deathbringer_blood_link_AuraScript::HandlePeriodicTick, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
}

View File

@@ -754,11 +754,11 @@ class spell_deathwhisper_mana_barrier : public SpellScriptLoader
int32 missingHealth = caster->GetMaxHealth() - caster->GetHealth();
caster->ModifyHealth(missingHealth);
caster->ModifyPower(POWER_MANA, -missingHealth);
PreventDefaultAction();
}
void Register()
{
PreventDefaultEffect(EFFECT_0);
OnEffectPeriodic += AuraEffectPeriodicFn(spell_deathwhisper_mana_barrier_AuraScript::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};