aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.cpp2
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp51
-rwxr-xr-xsrc/server/game/Spells/Spell.h3
-rwxr-xr-xsrc/server/game/Spells/SpellScript.cpp15
-rwxr-xr-xsrc/server/game/Spells/SpellScript.h42
-rw-r--r--src/server/scripts/Examples/example_spell.cpp38
6 files changed, 138 insertions, 13 deletions
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 91ecc328fd8..b3898c92450 100755
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -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;
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index de49b2cf579..113842fb967 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -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
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index f57b3114a70..a79384e12eb 100755
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -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);
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 53ec7822623..fc537ce4fb1 100755
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -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;
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index dab77f6533d..67886becb74 100755
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -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
diff --git a/src/server/scripts/Examples/example_spell.cpp b/src/server/scripts/Examples/example_spell.cpp
index 372abc45268..4d2064bf630 100644
--- a/src/server/scripts/Examples/example_spell.cpp
+++ b/src/server/scripts/Examples/example_spell.cpp
@@ -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