mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 23:50:44 +01:00
Core/SpellScripts: Add BeforeCast, OnCast and AfterCast hooks to SpellScripts.
This commit is contained in:
@@ -2035,7 +2035,6 @@ void Aura::_DeleteRemovedApplications()
|
||||
|
||||
void Aura::LoadScripts()
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Aura::LoadScripts");
|
||||
sScriptMgr->CreateAuraScripts(m_spellInfo->Id, m_loadedScripts);
|
||||
for (std::list<AuraScript*>::iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end() ;)
|
||||
{
|
||||
@@ -2046,6 +2045,7 @@ void Aura::LoadScripts()
|
||||
m_loadedScripts.erase(bitr);
|
||||
continue;
|
||||
}
|
||||
sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Aura::LoadScripts: Script `%s` for aura `%u` is loaded now", (*itr)->_GetScriptName()->c_str(), m_spellInfo->Id);
|
||||
(*itr)->Register();
|
||||
++itr;
|
||||
}
|
||||
|
||||
@@ -3091,6 +3091,8 @@ void Spell::cast(bool skipCheck)
|
||||
m_caster->ToPlayer()->SetSpellModTakingSpell(this, true);
|
||||
}
|
||||
|
||||
CallScriptBeforeCastHandlers();
|
||||
|
||||
// skip check if done already (for instant cast spells for example)
|
||||
if (!skipCheck)
|
||||
{
|
||||
@@ -3160,6 +3162,8 @@ void Spell::cast(bool skipCheck)
|
||||
|
||||
PrepareTriggersExecutedOnHit();
|
||||
|
||||
CallScriptOnCastHandlers();
|
||||
|
||||
// traded items have trade slot instead of guid in m_itemTargetGUID
|
||||
// set to real guid to be sent later to the client
|
||||
m_targets.UpdateTradeSlotItem();
|
||||
@@ -3219,6 +3223,8 @@ void Spell::cast(bool skipCheck)
|
||||
handle_immediate();
|
||||
}
|
||||
|
||||
CallScriptAfterCastHandlers();
|
||||
|
||||
if (const std::vector<int32> *spell_triggered = sSpellMgr->GetSpellLinked(m_spellInfo->Id))
|
||||
{
|
||||
for (std::vector<int32>::const_iterator i = spell_triggered->begin(); i != spell_triggered->end(); ++i)
|
||||
@@ -6969,7 +6975,6 @@ void Spell::CheckEffectExecuteData()
|
||||
|
||||
void Spell::LoadScripts()
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::LoadScripts");
|
||||
sScriptMgr->CreateSpellScripts(m_spellInfo->Id, m_loadedScripts);
|
||||
for (std::list<SpellScript*>::iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end() ;)
|
||||
{
|
||||
@@ -6980,15 +6985,49 @@ void Spell::LoadScripts()
|
||||
m_loadedScripts.erase(bitr);
|
||||
continue;
|
||||
}
|
||||
sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::LoadScripts: Script `%s` for spell `%u` is loaded now", (*itr)->_GetScriptName()->c_str(), m_spellInfo->Id);
|
||||
(*itr)->Register();
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::PrepareScriptHitHandlers()
|
||||
void Spell::CallScriptBeforeCastHandlers()
|
||||
{
|
||||
for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
|
||||
(*scritr)->_InitHit();
|
||||
{
|
||||
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_BEFORE_CAST);
|
||||
std::list<SpellScript::CastHandler>::iterator hookItrEnd = (*scritr)->BeforeCast.end(), hookItr = (*scritr)->BeforeCast.begin();
|
||||
for (; hookItr != hookItrEnd ; ++hookItr)
|
||||
(*hookItr).Call(*scritr);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::CallScriptOnCastHandlers()
|
||||
{
|
||||
for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
|
||||
{
|
||||
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_ON_CAST);
|
||||
std::list<SpellScript::CastHandler>::iterator hookItrEnd = (*scritr)->OnCast.end(), hookItr = (*scritr)->OnCast.begin();
|
||||
for (; hookItr != hookItrEnd ; ++hookItr)
|
||||
(*hookItr).Call(*scritr);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::CallScriptAfterCastHandlers()
|
||||
{
|
||||
for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
|
||||
{
|
||||
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_AFTER_CAST);
|
||||
std::list<SpellScript::CastHandler>::iterator hookItrEnd = (*scritr)->AfterCast.end(), hookItr = (*scritr)->AfterCast.begin();
|
||||
for (; hookItr != hookItrEnd ; ++hookItr)
|
||||
(*hookItr).Call(*scritr);
|
||||
|
||||
(*scritr)->_FinishScriptCall();
|
||||
}
|
||||
}
|
||||
|
||||
SpellCastResult Spell::CallScriptCheckCastHandlers()
|
||||
@@ -7010,6 +7049,12 @@ SpellCastResult Spell::CallScriptCheckCastHandlers()
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void Spell::PrepareScriptHitHandlers()
|
||||
{
|
||||
for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
|
||||
(*scritr)->_InitHit();
|
||||
}
|
||||
|
||||
bool Spell::CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMode mode)
|
||||
{
|
||||
// execute script effect handler hooks and check if effects was prevented
|
||||
|
||||
@@ -624,6 +624,9 @@ class Spell
|
||||
|
||||
// Scripting system
|
||||
void LoadScripts();
|
||||
void CallScriptBeforeCastHandlers();
|
||||
void CallScriptOnCastHandlers();
|
||||
void CallScriptAfterCastHandlers();
|
||||
SpellCastResult CallScriptCheckCastHandlers();
|
||||
void PrepareScriptHitHandlers();
|
||||
bool CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMode mode);
|
||||
|
||||
@@ -52,6 +52,11 @@ void _SpellScript::_Init(std::string const* scriptname, uint32 spellId)
|
||||
m_scriptSpellId = spellId;
|
||||
}
|
||||
|
||||
std::string const* _SpellScript::_GetScriptName() const
|
||||
{
|
||||
return m_scriptName;
|
||||
}
|
||||
|
||||
_SpellScript::EffectHook::EffectHook(uint8 _effIndex)
|
||||
{
|
||||
// effect index must be in range <0;2>, allow use of special effindexes
|
||||
@@ -147,6 +152,16 @@ std::string _SpellScript::EffectAuraNameCheck::ToString()
|
||||
}
|
||||
}
|
||||
|
||||
SpellScript::CastHandler::CastHandler(SpellCastFnType _pCastHandlerScript)
|
||||
{
|
||||
pCastHandlerScript = _pCastHandlerScript;
|
||||
}
|
||||
|
||||
void SpellScript::CastHandler::Call(SpellScript* spellScript)
|
||||
{
|
||||
(spellScript->*pCastHandlerScript)();
|
||||
}
|
||||
|
||||
SpellScript::CheckCastHandler::CheckCastHandler(SpellCheckCastFnType checkCastHandlerScript)
|
||||
{
|
||||
_checkCastHandlerScript = checkCastHandlerScript;
|
||||
|
||||
@@ -64,6 +64,7 @@ class _SpellScript
|
||||
virtual void _Register();
|
||||
virtual void _Unload();
|
||||
virtual void _Init(std::string const* scriptname, uint32 spellId);
|
||||
std::string const* _GetScriptName() const;
|
||||
|
||||
protected:
|
||||
class EffectHook
|
||||
@@ -131,6 +132,9 @@ enum SpellScriptHookType
|
||||
SPELL_SCRIPT_HOOK_AFTER_HIT,
|
||||
SPELL_SCRIPT_HOOK_UNIT_TARGET_SELECT,
|
||||
SPELL_SCRIPT_HOOK_CHECK_CAST,
|
||||
SPELL_SCRIPT_HOOK_BEFORE_CAST,
|
||||
SPELL_SCRIPT_HOOK_ON_CAST,
|
||||
SPELL_SCRIPT_HOOK_AFTER_CAST,
|
||||
};
|
||||
|
||||
#define HOOK_SPELL_HIT_START SPELL_SCRIPT_HOOK_EFFECT_HIT
|
||||
@@ -148,10 +152,20 @@ class SpellScript : public _SpellScript
|
||||
typedef SpellCastResult(CLASSNAME::*SpellCheckCastFnType)(); \
|
||||
typedef void(CLASSNAME::*SpellEffectFnType)(SpellEffIndex); \
|
||||
typedef void(CLASSNAME::*SpellHitFnType)(); \
|
||||
typedef void(CLASSNAME::*SpellCastFnType)(); \
|
||||
typedef void(CLASSNAME::*SpellUnitTargetFnType)(std::list<Unit*>&); \
|
||||
|
||||
SPELLSCRIPT_FUNCTION_TYPE_DEFINES(SpellScript)
|
||||
|
||||
class CastHandler
|
||||
{
|
||||
public:
|
||||
CastHandler(SpellCastFnType _pCastHandlerScript);
|
||||
void Call(SpellScript* spellScript);
|
||||
private:
|
||||
SpellCastFnType pCastHandlerScript;
|
||||
};
|
||||
|
||||
class CheckCastHandler
|
||||
{
|
||||
public:
|
||||
@@ -194,6 +208,7 @@ class SpellScript : public _SpellScript
|
||||
};
|
||||
|
||||
#define SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \
|
||||
class CastHandlerFunction : public SpellScript::CastHandler { public: CastHandlerFunction(SpellCastFnType _pCastHandlerScript) : SpellScript::CastHandler((SpellScript::SpellCastFnType)_pCastHandlerScript) {} }; \
|
||||
class CheckCastHandlerFunction : public SpellScript::CheckCastHandler { public: CheckCastHandlerFunction(SpellCheckCastFnType _checkCastHandlerScript) : SpellScript::CheckCastHandler((SpellScript::SpellCheckCastFnType)_checkCastHandlerScript) {} }; \
|
||||
class EffectHandlerFunction : public SpellScript::EffectHandler { public: EffectHandlerFunction(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : SpellScript::EffectHandler((SpellScript::SpellEffectFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \
|
||||
class HitHandlerFunction : public SpellScript::HitHandler { public: HitHandlerFunction(SpellHitFnType _pHitHandlerScript) : SpellScript::HitHandler((SpellScript::SpellHitFnType)_pHitHandlerScript) {} }; \
|
||||
@@ -221,6 +236,13 @@ class SpellScript : public _SpellScript
|
||||
// SpellScript interface
|
||||
// hooks to which you can attach your functions
|
||||
//
|
||||
// example: BeforeCast += SpellCastFn(class::function);
|
||||
HookList<CastHandler> BeforeCast;
|
||||
// example: OnCast += SpellCastFn(class::function);
|
||||
HookList<CastHandler> OnCast;
|
||||
// example: AfterCast += SpellCastFn(class::function);
|
||||
HookList<CastHandler> AfterCast;
|
||||
#define SpellCastFn(F) CastHandlerFunction(&F)
|
||||
|
||||
// example: OnCheckCast += SpellCheckCastFn();
|
||||
// where function is SpellCastResult function()
|
||||
@@ -250,14 +272,18 @@ class SpellScript : public _SpellScript
|
||||
#define SpellUnitTargetFn(F, I, N) UnitTargetHandlerFunction(&F, I, N)
|
||||
|
||||
// hooks are executed in following order, at specified event of spell:
|
||||
// 1. OnUnitTargetSelect - executed just before adding selected targets to final target list
|
||||
// 2. OnEffectLaunch - executed just before specified effect handler call - when spell missile is launched
|
||||
// 3. OnEffectLaunchTarget - executed just before specified effect handler call - when spell missile is launched - called for each target from spell target map
|
||||
// 4. OnEffectHit - executed just before specified effect handler call - when spell missile hits dest
|
||||
// 5. BeforeHit - executed just before spell hits a target - called for each target from spell target map
|
||||
// 6. OnEffectHitTarget - executed just before specified effect handler call - called for each target from spell target map
|
||||
// 7. OnHit - executed just before spell deals damage and procs auras - when spell hits target - called for each target from spell target map
|
||||
// 8. AfterHit - executed just after spell finishes all it's jobs for target - called for each target from spell target map
|
||||
// 1. BeforeCast - executed when spell preparation is finished (when cast bar becomes full) before cast is handled
|
||||
// 2. OnCheckCast - allows to override result of CheckCast function
|
||||
// 3. OnUnitTargetSelect - executed just before adding selected targets to final target list
|
||||
// 4. OnCast - executed just before spell is launched (creates missile) or executed
|
||||
// 5. AfterCast - executed after spell missile is launched and immediate spell actions are done
|
||||
// 6. OnEffectLaunch - executed just before specified effect handler call - when spell missile is launched
|
||||
// 7. OnEffectLaunchTarget - executed just before specified effect handler call - when spell missile is launched - called for each target from spell target map
|
||||
// 8. OnEffectHit - executed just before specified effect handler call - when spell missile hits dest
|
||||
// 9. BeforeHit - executed just before spell hits a target - called for each target from spell target map
|
||||
// 10. OnEffectHitTarget - executed just before specified effect handler call - called for each target from spell target map
|
||||
// 11. OnHit - executed just before spell deals damage and procs auras - when spell hits target - called for each target from spell target map
|
||||
// 12. AfterHit - executed just after spell finishes all it's jobs for target - called for each target from spell target map
|
||||
|
||||
//
|
||||
// methods allowing interaction with Spell object
|
||||
|
||||
@@ -76,6 +76,38 @@ class spell_ex_5581 : public SpellScriptLoader
|
||||
delete localVariable2;
|
||||
}
|
||||
|
||||
void HandleBeforeCast()
|
||||
{
|
||||
// this hook is executed before anything about casting the spell is done
|
||||
// after this hook is executed all the machinery starts
|
||||
sLog->outString("Caster just finished preparing the spell (cast bar has expired)");
|
||||
}
|
||||
|
||||
void HandleOnCast()
|
||||
{
|
||||
// cast is validated and spell targets are selected at this moment
|
||||
// this is a last place when the spell can be safely interrupted
|
||||
sLog->outString("Spell is about to do take reagents, power, launch missile, do visuals and instant spell effects");
|
||||
}
|
||||
|
||||
void HandleAfterCast()
|
||||
{
|
||||
sLog->outString("All immediate actions for the spell are finished now");
|
||||
// this is a safe for triggering additional effects for a spell without interfering
|
||||
// with visuals or with other effects of the spell
|
||||
//GetCaster()->CastSpell(target, SPELL_TRIGGERED, true);
|
||||
}
|
||||
|
||||
SpellCastResult CheckRequirement()
|
||||
{
|
||||
// in this hook you can add additional requirements for spell caster (and throw a client error if reqs're not passed)
|
||||
// in this case we're disallowing to select non-player as a target of the spell
|
||||
//if (!GetTargetUnit() || GetTargetUnit()->ToPlayer())
|
||||
//return SPELL_FAILED_BAD_TARGETS;
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
|
||||
void HandleDummyLaunch(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
sLog->outString("Spell %u with SPELL_EFFECT_DUMMY is just launched!", GetSpellInfo()->Id);
|
||||
@@ -127,7 +159,11 @@ class spell_ex_5581 : public SpellScriptLoader
|
||||
// register functions used in spell script - names of these functions do not matter
|
||||
void Register()
|
||||
{
|
||||
// we're registering our function here
|
||||
// we're registering our functions here
|
||||
BeforeCast += SpellCastFn(spell_ex_5581SpellScript::HandleBeforeCast);
|
||||
OnCast += SpellCastFn(spell_ex_5581SpellScript::HandleOnCast);
|
||||
AfterCast += SpellCastFn(spell_ex_5581SpellScript::HandleAfterCast);
|
||||
OnCheckCast += SpellCheckCastFn(spell_ex_5581SpellScript::CheckRequirement);
|
||||
// function HandleDummy will be called when spell is launched, independant from targets selected for spell, just before default effect 0 launch handler
|
||||
OnEffectLaunch += SpellEffectFn(spell_ex_5581SpellScript::HandleDummyLaunch, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
// function HandleDummy will be called when spell is launched at target, just before default effect 0 launch at target handler
|
||||
|
||||
Reference in New Issue
Block a user