mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
*Add script hooks for SpellScript class - now you can use BeforeHit, OnHit, AfterHit hook lists.
--HG-- branch : trunk
This commit is contained in:
@@ -1279,6 +1279,8 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
|
||||
break;
|
||||
}
|
||||
}
|
||||
CallScriptOnHitHandlers();
|
||||
|
||||
// All calculated do it!
|
||||
// Do healing and triggers
|
||||
if (m_healing > 0)
|
||||
@@ -1392,6 +1394,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
|
||||
m_caster->ToPlayer()->UpdatePvP(true);
|
||||
}
|
||||
|
||||
CallScriptAfterHitHandlers();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1404,7 +1407,8 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask, bool
|
||||
if (m_spellInfo->speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo)))
|
||||
return SPELL_MISS_IMMUNE;
|
||||
|
||||
PrepareTargetHitForScripts();
|
||||
PrepareScriptHitHandlers();
|
||||
CallScriptBeforeHitHandlers();
|
||||
|
||||
if (unit->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
@@ -1497,7 +1501,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask, bool
|
||||
if (scaleAura)
|
||||
{
|
||||
aurSpellInfo = sSpellMgr.SelectAuraRankForPlayerLevel(m_spellInfo,unitTarget->getLevel());
|
||||
ASSERT (aurSpellInfo);
|
||||
ASSERT(aurSpellInfo);
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
basePoints[i] = aurSpellInfo->EffectBasePoints[i];
|
||||
@@ -1641,12 +1645,15 @@ void Spell::DoAllEffectOnTarget(GOTargetInfo *target)
|
||||
if (!go)
|
||||
return;
|
||||
|
||||
PrepareTargetHitForScripts();
|
||||
PrepareScriptHitHandlers();
|
||||
CallScriptBeforeHitHandlers();
|
||||
|
||||
for (uint32 effectNumber = 0; effectNumber < 3; ++effectNumber)
|
||||
if (effectMask & (1 << effectNumber))
|
||||
HandleEffects(NULL, NULL, go, effectNumber);
|
||||
|
||||
CallScriptOnHitHandlers();
|
||||
|
||||
// cast at creature (or GO) quest objectives update at successful cast finished (+channel finished)
|
||||
// ignore autorepeat/melee casts for speed (not exist quest for spells (hm...)
|
||||
if (m_originalCaster && m_originalCaster->IsControlledByPlayer() && !IsAutoRepeat() && !IsNextMeleeSwingSpell() && !IsChannelActive())
|
||||
@@ -1654,6 +1661,7 @@ void Spell::DoAllEffectOnTarget(GOTargetInfo *target)
|
||||
if (Player* p = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
p->CastedCreatureOrGO(go->GetEntry(),go->GetGUID(),m_spellInfo->Id);
|
||||
}
|
||||
CallScriptAfterHitHandlers();
|
||||
}
|
||||
|
||||
void Spell::DoAllEffectOnTarget(ItemTargetInfo *target)
|
||||
@@ -1662,11 +1670,16 @@ void Spell::DoAllEffectOnTarget(ItemTargetInfo *target)
|
||||
if (!target->item || !effectMask)
|
||||
return;
|
||||
|
||||
PrepareTargetHitForScripts();
|
||||
PrepareScriptHitHandlers();
|
||||
CallScriptBeforeHitHandlers();
|
||||
|
||||
for (uint32 effectNumber = 0; effectNumber < 3; ++effectNumber)
|
||||
if (effectMask & (1 << effectNumber))
|
||||
HandleEffects(NULL, target->item, NULL, effectNumber);
|
||||
|
||||
CallScriptOnHitHandlers();
|
||||
|
||||
CallScriptAfterHitHandlers();
|
||||
}
|
||||
|
||||
bool Spell::UpdateChanneledTargetList()
|
||||
@@ -3261,7 +3274,7 @@ void Spell::cast(bool skipCheck)
|
||||
// CAST SPELL
|
||||
SendSpellCooldown();
|
||||
|
||||
PrepareTargetHitForScripts();
|
||||
PrepareScriptHitHandlers();
|
||||
|
||||
for (uint32 i = 0; i < 3; ++i)
|
||||
{
|
||||
@@ -3427,7 +3440,7 @@ void Spell::_handle_immediate_phase()
|
||||
// handle some immediate features of the spell here
|
||||
HandleThreatSpells(m_spellInfo->Id);
|
||||
|
||||
PrepareTargetHitForScripts();
|
||||
PrepareScriptHitHandlers();
|
||||
|
||||
m_needSpellLog = IsNeedSendToClient();
|
||||
for (uint32 j = 0; j < 3; ++j)
|
||||
@@ -4677,20 +4690,7 @@ void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTar
|
||||
//we do not need DamageMultiplier here.
|
||||
damage = CalculateDamage(i, NULL);
|
||||
|
||||
// execute script effect handler hooks and check if effects was prevented
|
||||
bool preventDefault = false;
|
||||
for(std::list<SpellScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
|
||||
{
|
||||
std::list<SpellScript::EffectHandler>::iterator effEndItr = (*scritr)->EffectHandlers.end(), effItr = (*scritr)->EffectHandlers.begin();
|
||||
for(; effItr != effEndItr ; ++effItr)
|
||||
{
|
||||
// effect execution can be prevented
|
||||
if (!(*scritr)->_IsEffectPrevented((SpellEffIndex)i) && (*effItr).IsEffectAffected(m_spellInfo, i))
|
||||
(*effItr).Call(*scritr, (SpellEffIndex)i);
|
||||
}
|
||||
if (!preventDefault)
|
||||
preventDefault = (*scritr)->_IsDefaultEffectPrevented((SpellEffIndex)i);
|
||||
}
|
||||
bool preventDefault = CallScriptEffectHandlers((SpellEffIndex)i);
|
||||
|
||||
if (!preventDefault && eff < TOTAL_SPELL_EFFECTS)
|
||||
{
|
||||
@@ -7306,10 +7306,65 @@ void Spell::LoadScripts()
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::PrepareTargetHitForScripts()
|
||||
void Spell::PrepareScriptHitHandlers()
|
||||
{
|
||||
for(std::list<SpellScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
|
||||
{
|
||||
(*scritr)->_InitHit();
|
||||
}
|
||||
}
|
||||
|
||||
bool Spell::CallScriptEffectHandlers(SpellEffIndex effIndex)
|
||||
{
|
||||
// execute script effect handler hooks and check if effects was prevented
|
||||
bool preventDefault = false;
|
||||
for(std::list<SpellScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
|
||||
{
|
||||
std::list<SpellScript::EffectHandler>::iterator effEndItr = (*scritr)->EffectHandlers.end(), effItr = (*scritr)->EffectHandlers.begin();
|
||||
for(; effItr != effEndItr ; ++effItr)
|
||||
{
|
||||
// effect execution can be prevented
|
||||
if (!(*scritr)->_IsEffectPrevented(effIndex) && (*effItr).IsEffectAffected(m_spellInfo, effIndex))
|
||||
(*effItr).Call(*scritr, effIndex);
|
||||
}
|
||||
if (!preventDefault)
|
||||
preventDefault = (*scritr)->_IsDefaultEffectPrevented(effIndex);
|
||||
}
|
||||
return preventDefault;
|
||||
}
|
||||
|
||||
void Spell::CallScriptBeforeHitHandlers()
|
||||
{
|
||||
for(std::list<SpellScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
|
||||
{
|
||||
std::list<SpellScript::HitHandler>::iterator hookItrEnd = (*scritr)->BeforeHit.end(), hookItr = (*scritr)->BeforeHit.begin();
|
||||
for(; hookItr != hookItrEnd ; ++hookItr)
|
||||
{
|
||||
((*scritr)->*(*hookItr))();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::CallScriptOnHitHandlers()
|
||||
{
|
||||
for(std::list<SpellScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
|
||||
{
|
||||
std::list<SpellScript::HitHandler>::iterator hookItrEnd = (*scritr)->OnHit.end(), hookItr = (*scritr)->OnHit.begin();
|
||||
for(; hookItr != hookItrEnd ; ++hookItr)
|
||||
{
|
||||
((*scritr)->*(*hookItr))();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::CallScriptAfterHitHandlers()
|
||||
{
|
||||
for(std::list<SpellScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
|
||||
{
|
||||
std::list<SpellScript::HitHandler>::iterator hookItrEnd = (*scritr)->AfterHit.end(), hookItr = (*scritr)->AfterHit.begin();
|
||||
for(; hookItr != hookItrEnd ; ++hookItr)
|
||||
{
|
||||
((*scritr)->*(*hookItr))();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -672,7 +672,11 @@ class Spell
|
||||
|
||||
// Scripting system
|
||||
void LoadScripts();
|
||||
void PrepareTargetHitForScripts();
|
||||
void PrepareScriptHitHandlers();
|
||||
bool CallScriptEffectHandlers(SpellEffIndex effIndex);
|
||||
void CallScriptBeforeHitHandlers();
|
||||
void CallScriptOnHitHandlers();
|
||||
void CallScriptAfterHitHandlers();
|
||||
std::list<SpellScript *> m_loadedScripts;
|
||||
|
||||
// effect helpers
|
||||
|
||||
@@ -34,6 +34,7 @@ class Item;
|
||||
class WorldLocation;
|
||||
|
||||
typedef void(SpellScript::*EffectHandlerFnType)(SpellEffIndex);
|
||||
typedef void(SpellScript::*HitHandlerFnType)();
|
||||
|
||||
#define SPELL_EFFECT_ANY (uint16)-1
|
||||
#define SPELL_AURA_ANY (uint16)-1
|
||||
@@ -108,6 +109,7 @@ class SpellScript : public _SpellScript
|
||||
private:
|
||||
EffectHandlerFnType pEffectHandlerScript;
|
||||
};
|
||||
typedef HitHandlerFnType HitHandler;
|
||||
public:
|
||||
bool _Validate(SpellEntry const * entry, const char * scriptname);
|
||||
bool _Load(Spell * spell);
|
||||
@@ -127,6 +129,20 @@ class SpellScript : public _SpellScript
|
||||
// allows more than one hook
|
||||
// example EffectHandlers += EffectHandlerFn(class::function, EffectIndexSpecifier, EffectNameSpecifier);
|
||||
HookList<EffectHandler> EffectHandlers;
|
||||
// List of functions registered by HitHandlerFn
|
||||
// allows more than one hook
|
||||
// example: BeforeHit += HitHandlerFn(class::function);
|
||||
HookList<HitHandler> BeforeHit;
|
||||
// example: OnHit += HitHandlerFn(class::function);
|
||||
HookList<HitHandler> OnHit;
|
||||
// example: AfterHit += HitHandlerFn(class::function);
|
||||
HookList<HitHandler> AfterHit;
|
||||
|
||||
// hooks are executed in following order, at specified event of spell:
|
||||
// 1. BeforeHit - executed just before spell hits a target
|
||||
// 2. EffectHandlers - executed just before specified effect handler call
|
||||
// 3. OnHit - executed just before spell deals damage and procs auras
|
||||
// 4. AfterHit - executed just after spell finishes all it's jobs for target
|
||||
|
||||
//
|
||||
// methods allowing interaction with Spell object
|
||||
@@ -196,6 +212,11 @@ class SpellScript : public _SpellScript
|
||||
// parameters: function to call, EffectIndexSpecifier, EffectNameSpecifier
|
||||
#define EffectHandlerFn(F, I, N) EffectHandler((EffectHandlerFnType)&F, I, N)
|
||||
|
||||
// HitHandlerFn
|
||||
// called at: Spell hit on unit, before or after effect handlers, depends if bound to OnHit or AfterHit
|
||||
// parameters: function to call
|
||||
#define HitHandlerFn(F) (HitHandlerFnType)&F
|
||||
|
||||
//
|
||||
// definitions:
|
||||
//
|
||||
|
||||
@@ -45,6 +45,21 @@ class spell_ex_49375 : public SpellHandlerScript
|
||||
GetCaster()->CastSpell(target, 70522, true);
|
||||
};
|
||||
|
||||
void HandleBeforeHit()
|
||||
{
|
||||
sLog.outError("Spell is about to hit target!");
|
||||
}
|
||||
|
||||
void HandleOnHit()
|
||||
{
|
||||
sLog.outError("Spell just hit target!");
|
||||
}
|
||||
|
||||
void HandleAfterHit()
|
||||
{
|
||||
sLog.outError("Spell just finished hitting target!");
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
// we're registering our function here
|
||||
@@ -56,6 +71,12 @@ class spell_ex_49375 : public SpellHandlerScript
|
||||
//EffectHandlers += EffectHandlerFn(spell_gen_49375SpellScript::HandleDummy, EFFECT_FIRST_FOUND, SPELL_EFFECT_ANY);
|
||||
// this will make HandleDummy function to be called on all != 0 effect of spell 49375
|
||||
//EffectHandlers += EffectHandlerFn(spell_gen_49375SpellScript::HandleDummy, EFFECT_ALL, SPELL_EFFECT_ANY);
|
||||
// bind handler to BeforeHit event of the spell
|
||||
BeforeHit += HitHandlerFn(spell_ex_49375SpellScript::HandleBeforeHit);
|
||||
// bind handler to OnHit event of the spell
|
||||
OnHit += HitHandlerFn(spell_ex_49375SpellScript::HandleOnHit);
|
||||
// bind handler to AfterHit event of the spell
|
||||
AfterHit += HitHandlerFn(spell_ex_49375SpellScript::HandleAfterHit);
|
||||
};
|
||||
|
||||
// function called on server startup
|
||||
|
||||
Reference in New Issue
Block a user