diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 31 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 114 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.h | 9 | ||||
-rw-r--r-- | src/server/game/Spells/SpellScript.cpp | 67 | ||||
-rw-r--r-- | src/server/game/Spells/SpellScript.h | 72 |
6 files changed, 281 insertions, 19 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index d383b92c5ff..e560363a186 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -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); } } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 12551c93346..a7a4a14dfb4 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -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) diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index b33546ee988..299c534ee8d 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -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) { diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 88ebee18981..bd351548255 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -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: diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index c29b08242a0..89ed223545f 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -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); diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 5791c701c07..6f1df2560dc 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -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) |