Core/SpellScripts: implement Spell Proc Hooks and use it in old and new proc system

Hooks:
- DoCheckProc: executed when aura checks if it can proc
- DoPrepareProc: executed before aura procs (possibility to prevent charge drop/cooldown)
- OnProc: executed when aura procs
- OnEffectProc: executed when aura effect procs
- AfterEffectProc: executed after aura effect proced
- AfterProc: executed after aura proced and charges removed

using PreventDefaultAction() in DoPrepareProc will prevent charge drop and cooldown

default execution of a proc can prevented in OnEffectProc with PreventDefaultAction()

Now we should be able to convert almost all procs from Unit::ProcDamageAndSpellFor to SpellScripts

Notes to old proc system:
- if a proc has a cooldown we must check it in spellscript and add it when we handle the proc
- behavior with charge drops is possible undefined (use PreventDefaultAction() in OnEffectProc to notify that the script is executed)
This commit is contained in:
joschiwald
2013-01-11 01:21:44 +01:00
parent 5f28502c0a
commit 89490e4d7f
6 changed files with 281 additions and 19 deletions
+26 -5
View File
@@ -14452,7 +14452,8 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
Unit* actionTarget = !isVictim ? target : this;
DamageInfo damageInfo = DamageInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL, SPELL_DIRECT_DAMAGE);
ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, NULL, &damageInfo, NULL /*HealInfo*/);
HealInfo healInfo = HealInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL);
ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, NULL, &damageInfo, &healInfo);
ProcTriggeredList procTriggered;
// Fill procTriggered list
@@ -14483,6 +14484,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
if (!sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
continue;
// AuraScript Hook
if (!triggerData.aura->CallScriptCheckProcHandlers(itr->second, eventInfo))
continue;
// Triggered spells not triggering additional spells
bool triggered = !(spellProto->AttributesEx3 & SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED) ?
(procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION)) : false;
@@ -14531,15 +14536,21 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
SpellInfo const* spellInfo = i->aura->GetSpellInfo();
uint32 Id = i->aura->GetId();
AuraApplication const* aurApp = i->aura->GetApplicationOfTarget(GetGUID());
bool prepare = i->aura->CallScriptPrepareProcHandlers(aurApp, eventInfo);
// For players set spell cooldown if need
uint32 cooldown = 0;
if (GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown)
if (prepare && GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown)
cooldown = i->spellProcEvent->cooldown;
// Note: must SetCantProc(false) before return
if (spellInfo->AttributesEx3 & SPELL_ATTR3_DISABLE_PROC)
SetCantProc(true);
i->aura->CallScriptProcHandlers(aurApp, eventInfo);
// This bool is needed till separate aura effect procs are still here
bool handled = false;
if (HandleAuraProc(target, damage, i->aura, procSpell, procFlag, procExtra, cooldown, &handled))
@@ -14558,6 +14569,13 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
AuraEffect* triggeredByAura = i->aura->GetEffect(effIndex);
ASSERT(triggeredByAura);
bool prevented = i->aura->CallScriptEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
if (prevented)
{
takeCharges = true;
continue;
}
switch (triggeredByAura->GetAuraType())
{
case SPELL_AURA_PROC_TRIGGER_SPELL:
@@ -14725,13 +14743,16 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
takeCharges = true;
break;
} // switch (triggeredByAura->GetAuraType())
i->aura->CallScriptAfterEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
} // for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
} // if (!handled)
// Remove charge (aura can be removed by triggers)
if (useCharges && takeCharges)
if (prepare && useCharges && takeCharges)
i->aura->DropCharge();
i->aura->CallScriptAfterProcHandlers(aurApp, eventInfo);
if (spellInfo->AttributesEx3 & SPELL_ATTR3_DISABLE_PROC)
SetCantProc(false);
}
@@ -14752,7 +14773,7 @@ void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTrigge
if (!(*itr)->GetRemoveMode())
if ((*itr)->GetBase()->IsProcTriggeredOnEvent(*itr, eventInfo))
{
(*itr)->GetBase()->PrepareProcToTrigger();
(*itr)->GetBase()->PrepareProcToTrigger(*itr, eventInfo);
aurasTriggeringProc.push_back(*itr);
}
}
@@ -14764,7 +14785,7 @@ void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTrigge
{
if (itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo))
{
itr->second->GetBase()->PrepareProcToTrigger();
itr->second->GetBase()->PrepareProcToTrigger(itr->second, eventInfo);
aurasTriggeringProc.push_back(itr->second);
}
}
@@ -1274,7 +1274,10 @@ void AuraEffect::PeriodicTick(AuraApplication * aurApp, Unit* caster) const
void AuraEffect::HandleProc(AuraApplication* aurApp, ProcEventInfo& eventInfo)
{
// TODO: effect script handlers here
bool prevented = GetBase()->CallScriptEffectProcHandlers(const_cast<AuraEffect const*>(this), const_cast<AuraApplication const*>(aurApp), eventInfo);
if (prevented)
return;
switch (GetAuraType())
{
case SPELL_AURA_PROC_TRIGGER_SPELL:
@@ -1295,6 +1298,8 @@ void AuraEffect::HandleProc(AuraApplication* aurApp, ProcEventInfo& eventInfo)
default:
break;
}
GetBase()->CallScriptAfterEffectProcHandlers(const_cast<AuraEffect const*>(this), const_cast<AuraApplication const*>(aurApp), eventInfo);
}
void AuraEffect::CleanupTriggeredSpells(Unit* target)
+105 -9
View File
@@ -1940,9 +1940,12 @@ void Aura::AddProcCooldown(uint32 /*msec*/)
//m_procCooldown = time(NULL) + msec;
}
void Aura::PrepareProcToTrigger()
void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo)
{
// TODO: allow scripts to prevent charge drop/cooldown
bool prepare = CallScriptPrepareProcHandlers(aurApp, eventInfo);
if (!prepare)
return;
// take one charge, aura expiration will be handled in Aura::TriggerProcOnEvent (if needed)
if (IsUsingCharges())
{
@@ -1981,14 +1984,18 @@ bool Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventI
return false;
// do checks using conditions table
ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_PROC, GetSpellInfo()->Id);
ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_PROC, GetId());
ConditionSourceInfo condInfo = ConditionSourceInfo(eventInfo.GetActor(), eventInfo.GetActionTarget());
if (!sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
return false;
// AuraScript Hook
bool check = const_cast<Aura*>(this)->CallScriptCheckProcHandlers(aurApp, eventInfo);
if (!check)
return false;
// TODO:
// - add DoCheckProc() AuraScript hook
// to allow additional requirements for procs
// do allow additional requirements for procs
// this is needed because this is the last moment in which you can prevent aura charge drop on proc
// and possibly a way to prevent default checks (if there're going to be any)
@@ -2052,14 +2059,14 @@ float Aura::CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& event
void Aura::TriggerProcOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo)
{
// TODO: OnProc hook here
CallScriptProcHandlers(const_cast<AuraApplication const*>(aurApp), eventInfo);
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (aurApp->HasEffect(i))
// TODO: OnEffectProc hook here (allowing prevention of selected effects)
// OnEffectProc / AfterEffectProc hooks handled in AuraEffect::HandleProc()
GetEffect(i)->HandleProc(aurApp, eventInfo);
// TODO: AfterEffectProc hook here
// TODO: AfterProc hook here
CallScriptAfterProcHandlers(const_cast<AuraApplication const*>(aurApp), eventInfo);
// Remove aura if we've used last charge to proc
if (IsUsingCharges() && !GetCharges())
@@ -2355,6 +2362,95 @@ void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication con
}
}
bool Aura::CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_PROC, aurApp);
std::list<AuraScript::CheckProcHandler>::iterator hookItrEnd = (*scritr)->DoCheckProc.end(), hookItr = (*scritr)->DoCheckProc.begin();
for (; hookItr != hookItrEnd; ++hookItr)
if (!(*hookItr).Call(*scritr, eventInfo))
return false;
(*scritr)->_FinishScriptCall();
}
return true;
}
bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
bool prepare = true;
for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PREPARE_PROC, aurApp);
std::list<AuraScript::AuraProcHandler>::iterator effEndItr = (*scritr)->DoPrepareProc.end(), effItr = (*scritr)->DoPrepareProc.begin();
for (; effItr != effEndItr; ++effItr)
(*effItr).Call(*scritr, eventInfo);
if (prepare && (*scritr)->_IsDefaultActionPrevented())
prepare = false;
(*scritr)->_FinishScriptCall();
}
return prepare;
}
void Aura::CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PROC, aurApp);
std::list<AuraScript::AuraProcHandler>::iterator hookItrEnd = (*scritr)->OnProc.end(), hookItr = (*scritr)->OnProc.begin();
for (; hookItr != hookItrEnd; ++hookItr)
(*hookItr).Call(*scritr, eventInfo);
(*scritr)->_FinishScriptCall();
}
}
void Aura::CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_PROC, aurApp);
std::list<AuraScript::AuraProcHandler>::iterator hookItrEnd = (*scritr)->AfterProc.end(), hookItr = (*scritr)->AfterProc.begin();
for (; hookItr != hookItrEnd; ++hookItr)
(*hookItr).Call(*scritr, eventInfo);
(*scritr)->_FinishScriptCall();
}
}
bool Aura::CallScriptEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
bool preventDefault = false;
for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC, aurApp);
std::list<AuraScript::EffectProcHandler>::iterator effEndItr = (*scritr)->OnEffectProc.end(), effItr = (*scritr)->OnEffectProc.begin();
for (; effItr != effEndItr; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
(*effItr).Call(*scritr, aurEff, eventInfo);
}
if (!preventDefault)
preventDefault = (*scritr)->_IsDefaultActionPrevented();
(*scritr)->_FinishScriptCall();
}
return preventDefault;
}
void Aura::CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo)
{
for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC, aurApp);
std::list<AuraScript::EffectProcHandler>::iterator effEndItr = (*scritr)->AfterEffectProc.end(), effItr = (*scritr)->AfterEffectProc.begin();
for (; effItr != effEndItr; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
(*effItr).Call(*scritr, aurEff, eventInfo);
}
(*scritr)->_FinishScriptCall();
}
}
UnitAura::UnitAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, uint64 casterGUID)
: Aura(spellproto, owner, caster, castItem, casterGUID)
{
+8 -1
View File
@@ -194,7 +194,7 @@ class Aura
void AddProcCooldown(uint32 msec);
bool IsUsingCharges() const { return m_isUsingCharges; }
void SetUsingCharges(bool val) { m_isUsingCharges = val; }
void PrepareProcToTrigger();
void PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo);
bool IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo) const;
float CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const;
void TriggerProcOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo);
@@ -218,6 +218,13 @@ class Aura
void CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & defaultPrevented);
void CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount);
void CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & splitAmount);
// Spell Proc Hooks
bool CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
bool CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
void CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
void CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo);
bool CallScriptEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo);
void CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo);
std::list<AuraScript*> m_loadedScripts;
private:
+66 -1
View File
@@ -470,7 +470,7 @@ WorldLocation* SpellScript::GetHitDest()
{
if (!IsInEffectHook())
{
sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u`: function SpellScript::GetHitGObj was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u`: function SpellScript::GetHitDest was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
return NULL;
}
return m_spell->destTarget;
@@ -679,6 +679,30 @@ bool AuraScript::_Validate(SpellInfo const* entry)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectSplit` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<CheckProcHandler>::iterator itr = DoCheckProc.begin(); itr != DoCheckProc.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoCheckProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
for (std::list<AuraProcHandler>::iterator itr = DoPrepareProc.begin(); itr != DoPrepareProc.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoPrepareProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
for (std::list<AuraProcHandler>::iterator itr = OnProc.begin(); itr != OnProc.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `OnProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
for (std::list<AuraProcHandler>::iterator itr = AfterProc.begin(); itr != AfterProc.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `AfterProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
for (std::list<EffectProcHandler>::iterator itr = OnEffectProc.begin(); itr != OnEffectProc.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectProc` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<EffectProcHandler>::iterator itr = AfterEffectProc.begin(); itr != AfterEffectProc.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `AfterEffectProc` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
return _SpellScript::_Validate(entry);
}
@@ -818,6 +842,37 @@ void AuraScript::EffectSplitHandler::Call(AuraScript* auraScript, AuraEffect* au
(auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, splitAmount);
}
AuraScript::CheckProcHandler::CheckProcHandler(AuraCheckProcFnType handlerScript)
{
_HandlerScript = handlerScript;
}
bool AuraScript::CheckProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo)
{
return (auraScript->*_HandlerScript)(eventInfo);
}
AuraScript::AuraProcHandler::AuraProcHandler(AuraProcFnType handlerScript)
{
_HandlerScript = handlerScript;
}
void AuraScript::AuraProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo)
{
(auraScript->*_HandlerScript)(eventInfo);
}
AuraScript::EffectProcHandler::EffectProcHandler(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName)
: AuraScript::EffectBase(effIndex, effName)
{
_EffectHandlerScript = effectHandlerScript;
}
void AuraScript::EffectProcHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
(auraScript->*_EffectHandlerScript)(aurEff, eventInfo);
}
bool AuraScript::_Load(Aura* aura)
{
m_aura = aura;
@@ -853,6 +908,8 @@ bool AuraScript::_IsDefaultActionPrevented()
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
case AURA_SCRIPT_HOOK_EFFECT_ABSORB:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
case AURA_SCRIPT_HOOK_PREPARE_PROC:
case AURA_SCRIPT_HOOK_EFFECT_PROC:
return m_defaultActionPrevented;
default:
ASSERT(false && "AuraScript::_IsDefaultActionPrevented is called in a wrong place");
@@ -869,6 +926,8 @@ void AuraScript::PreventDefaultAction()
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
case AURA_SCRIPT_HOOK_EFFECT_ABSORB:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
case AURA_SCRIPT_HOOK_PREPARE_PROC:
case AURA_SCRIPT_HOOK_EFFECT_PROC:
m_defaultActionPrevented = true;
break;
default:
@@ -1051,6 +1110,12 @@ Unit* AuraScript::GetTarget() const
case AURA_SCRIPT_HOOK_EFFECT_MANASHIELD:
case AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
case AURA_SCRIPT_HOOK_CHECK_PROC:
case AURA_SCRIPT_HOOK_PREPARE_PROC:
case AURA_SCRIPT_HOOK_PROC:
case AURA_SCRIPT_HOOK_AFTER_PROC:
case AURA_SCRIPT_HOOK_EFFECT_PROC:
case AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC:
return m_auraApplication->GetTarget();
default:
sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u` AuraScript::GetTarget called in a hook in which the call won't have effect!", m_scriptName->c_str(), m_scriptSpellId);
+70 -2
View File
@@ -428,14 +428,22 @@ enum AuraScriptHookType
AURA_SCRIPT_HOOK_EFFECT_SPLIT,
AURA_SCRIPT_HOOK_CHECK_AREA_TARGET,
AURA_SCRIPT_HOOK_DISPEL,
AURA_SCRIPT_HOOK_AFTER_DISPEL
AURA_SCRIPT_HOOK_AFTER_DISPEL,
// Spell Proc Hooks
AURA_SCRIPT_HOOK_CHECK_PROC,
AURA_SCRIPT_HOOK_PREPARE_PROC,
AURA_SCRIPT_HOOK_PROC,
AURA_SCRIPT_HOOK_EFFECT_PROC,
AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC,
AURA_SCRIPT_HOOK_AFTER_PROC,
/*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
@@ -453,6 +461,9 @@ class AuraScript : public _SpellScript
typedef void(CLASSNAME::*AuraEffectCalcSpellModFnType)(AuraEffect const*, SpellModifier* &); \
typedef void(CLASSNAME::*AuraEffectAbsorbFnType)(AuraEffect*, DamageInfo &, uint32 &); \
typedef void(CLASSNAME::*AuraEffectSplitFnType)(AuraEffect*, DamageInfo &, uint32 &); \
typedef bool(CLASSNAME::*AuraCheckProcFnType)(ProcEventInfo&); \
typedef void(CLASSNAME::*AuraProcFnType)(ProcEventInfo&); \
typedef void(CLASSNAME::*AuraEffectProcFnType)(AuraEffect const*, ProcEventInfo&); \
AURASCRIPT_FUNCTION_TYPE_DEFINES(AuraScript)
@@ -552,6 +563,30 @@ class AuraScript : public _SpellScript
private:
AuraEffectSplitFnType pEffectHandlerScript;
};
class CheckProcHandler
{
public:
CheckProcHandler(AuraCheckProcFnType handlerScript);
bool Call(AuraScript* auraScript, ProcEventInfo& eventInfo);
private:
AuraCheckProcFnType _HandlerScript;
};
class AuraProcHandler
{
public:
AuraProcHandler(AuraProcFnType handlerScript);
void Call(AuraScript* auraScript, ProcEventInfo& eventInfo);
private:
AuraProcFnType _HandlerScript;
};
class EffectProcHandler : public EffectBase
{
public:
EffectProcHandler(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName);
void Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo);
private:
AuraEffectProcFnType _EffectHandlerScript;
};
#define AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \
class CheckAreaTargetFunction : public AuraScript::CheckAreaTargetHandler { public: CheckAreaTargetFunction(AuraCheckAreaTargetFnType _pHandlerScript) : AuraScript::CheckAreaTargetHandler((AuraScript::AuraCheckAreaTargetFnType)_pHandlerScript) {} }; \
@@ -565,6 +600,9 @@ class AuraScript : public _SpellScript
class EffectAbsorbFunction : public AuraScript::EffectAbsorbHandler { public: EffectAbsorbFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectAbsorbHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex) {} }; \
class EffectManaShieldFunction : public AuraScript::EffectManaShieldHandler { public: EffectManaShieldFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectManaShieldHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex) {} }; \
class EffectSplitFunction : public AuraScript::EffectSplitHandler { public: EffectSplitFunction(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectSplitHandler((AuraScript::AuraEffectSplitFnType)_pEffectHandlerScript, _effIndex) {} }; \
class CheckProcHandlerFunction : public AuraScript::CheckProcHandler { public: CheckProcHandlerFunction(AuraCheckProcFnType handlerScript) : AuraScript::CheckProcHandler((AuraScript::AuraCheckProcFnType)handlerScript) {} }; \
class AuraProcHandlerFunction : public AuraScript::AuraProcHandler { public: AuraProcHandlerFunction(AuraProcFnType handlerScript) : AuraScript::AuraProcHandler((AuraScript::AuraProcFnType)handlerScript) {} }; \
class EffectProcHandlerFunction : public AuraScript::EffectProcHandler { public: EffectProcHandlerFunction(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName) : AuraScript::EffectProcHandler((AuraScript::AuraEffectProcFnType)effectHandlerScript, effIndex, effName) {} }; \
#define PrepareAuraScript(CLASSNAME) AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME)
@@ -695,6 +733,36 @@ class AuraScript : public _SpellScript
HookList<EffectSplitHandler> OnEffectSplit;
#define AuraEffectSplitFn(F, I) EffectSplitFunction(&F, I)
// executed when aura checks if it can proc
// example: DoCheckProc += AuraCheckProcFn(class::function);
// where function is: bool function (ProcEventInfo& eventInfo);
HookList<CheckProcHandler> DoCheckProc;
#define AuraCheckProcFn(F) CheckProcHandlerFunction(&F)
// executed before aura procs (possibility to prevent charge drop/cooldown)
// example: DoPrepareProc += AuraProcFn(class::function);
// where function is: void function (ProcEventInfo& eventInfo);
HookList<AuraProcHandler> DoPrepareProc;
// executed when aura procs
// example: OnProc += AuraProcFn(class::function);
// where function is: void function (ProcEventInfo& eventInfo);
HookList<AuraProcHandler> OnProc;
// executed after aura proced
// example: AfterProc += AuraProcFn(class::function);
// where function is: void function (ProcEventInfo& eventInfo);
HookList<AuraProcHandler> AfterProc;
#define AuraProcFn(F) AuraProcHandlerFunction(&F)
// executed when aura effect procs
// example: OnEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
// where function is: void function (AuraEffect const* aurEff, ProcEventInfo& procInfo);
HookList<EffectProcHandler> OnEffectProc;
// executed after aura effect proced
// example: AfterEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
// where function is: void function (AuraEffect const* aurEff, ProcEventInfo& procInfo);
HookList<EffectProcHandler> AfterEffectProc;
#define AuraEffectProcFn(F, I, N) EffectProcHandlerFunction(&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)