Skip to content

Instantly share code, notes, and snippets.

@Subv
Created April 2, 2012 23:12
Show Gist options
  • Save Subv/2287876 to your computer and use it in GitHub Desktop.
Save Subv/2287876 to your computer and use it in GitHub Desktop.
Proc Hook
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index d71f8e8..e0a589d 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -5689,29 +5689,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
}
break;
}
-
- // Hot Streak
- if (dummySpell->SpellIconID == 2999)
- {
- if (effIndex != 0)
- return false;
- AuraEffect* counter = triggeredByAura->GetBase()->GetEffect(EFFECT_1);
- if (!counter)
- return true;
-
- // Count spell criticals in a row in second aura
- if (procEx & PROC_EX_CRITICAL_HIT)
- {
- counter->SetAmount(counter->GetAmount() * 2);
- if (counter->GetAmount() < 100) // not enough
- return true;
- // Crititcal counted -> roll chance
- if (roll_chance_i(triggerAmount))
- CastSpell(this, 48108, true, castItem, triggeredByAura);
- }
- counter->SetAmount(25);
- return true;
- }
// Burnout
if (dummySpell->SpellIconID == 2998)
{
@@ -14376,13 +14353,18 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
SetCantProc(true);
// 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))
+ // Prevent default effect by script, remember to set takeCharges according to the needs of the script
+ bool handled = i->aura->CallScriptEffectProc(this, target, damage, procSpell, procFlag, procExtra, attType, cooldown, takeCharges);
+ if (!handled)
{
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), Id);
- takeCharges = true;
+ if (HandleAuraProc(target, damage, i->aura, procSpell, procFlag, procExtra, cooldown, &handled))
+ {
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), Id);
+ takeCharges = true;
+ }
}
+ // Check again since HandleAuraProc can change the handled boolean
if (!handled)
{
for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index b6cdc00..4c09e8c 100755
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -2303,6 +2303,24 @@ void Aura::CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraAppli
}
}
+bool Aura::CallScriptEffectProc(Unit* unit, Unit* victim, uint32 damage, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, uint32& cooldown, bool& takeCharges)
+{
+ bool preventDefault = false;
+ for(std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC);
+ std::list<AuraScript::EffectProcHandler>::iterator effEndItr = (*scritr)->OnEffectProc.end(), effItr = (*scritr)->OnEffectProc.begin();
+
+ for(; effItr != effEndItr ; ++effItr)
+ (*effItr).Call(*scritr, unit, victim, damage, procSpell, procFlag, procExtra, attType, cooldown, takeCharges);
+
+ if (!preventDefault)
+ preventDefault = (*scritr)->_IsDefaultActionPrevented();
+ (*scritr)->_FinishScriptCall();
+ }
+ return preventDefault;
+}
+
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 2f50d47..86235fa 100755
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -217,6 +217,7 @@ class Aura
void CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount);
void CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & defaultPrevented);
void CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount);
+ bool CallScriptEffectProc(Unit* unit, Unit* victim, uint32 damage, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, uint32& cooldown, bool& takeCharges);
std::list<AuraScript*> m_loadedScripts;
private:
void _DeleteRemovedApplications();
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 81f8bbd..4d56a41 100755
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -740,6 +740,16 @@ void AuraScript::EffectManaShieldHandler::Call(AuraScript* auraScript, AuraEffec
(auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, absorbAmount);
}
+AuraScript::EffectProcHandler::EffectProcHandler(AuraEffectProcFnType effectProcScript)
+{
+ pEffectProcScript = effectProcScript;
+}
+
+void AuraScript::EffectProcHandler::Call(AuraScript* auraScript, Unit* unit, Unit* victim, uint32 damage, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, uint32& cooldown, bool& takeCharges)
+{
+ (auraScript->*pEffectProcScript)(unit, victim, damage, procSpell, procFlag, procExtra, attType, cooldown, takeCharges);
+}
+
bool AuraScript::_Load(Aura* aura)
{
m_aura = aura;
@@ -773,6 +783,7 @@ bool AuraScript::_IsDefaultActionPrevented()
case AURA_SCRIPT_HOOK_EFFECT_APPLY:
case AURA_SCRIPT_HOOK_EFFECT_REMOVE:
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
+ case AURA_SCRIPT_HOOK_EFFECT_PROC:
return m_defaultActionPrevented;
default:
ASSERT(false && "AuraScript::_IsDefaultActionPrevented is called in a wrong place");
@@ -787,6 +798,7 @@ void AuraScript::PreventDefaultAction()
case AURA_SCRIPT_HOOK_EFFECT_APPLY:
case AURA_SCRIPT_HOOK_EFFECT_REMOVE:
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
+ case AURA_SCRIPT_HOOK_EFFECT_PROC:
m_defaultActionPrevented = true;
break;
default:
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index e84a56c..6b015fb 100755
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -390,6 +390,7 @@ enum AuraScriptHookType
AURA_SCRIPT_HOOK_CHECK_AREA_TARGET,
AURA_SCRIPT_HOOK_DISPEL,
AURA_SCRIPT_HOOK_AFTER_DISPEL,
+ AURA_SCRIPT_HOOK_EFFECT_PROC
/*AURA_SCRIPT_HOOK_APPLY,
AURA_SCRIPT_HOOK_REMOVE, */
};
@@ -413,6 +414,7 @@ class AuraScript : public _SpellScript
typedef void(CLASSNAME::*AuraEffectCalcPeriodicFnType)(AuraEffect const*, bool &, int32 &); \
typedef void(CLASSNAME::*AuraEffectCalcSpellModFnType)(AuraEffect const*, SpellModifier* &); \
typedef void(CLASSNAME::*AuraEffectAbsorbFnType)(AuraEffect*, DamageInfo &, uint32 &); \
+ typedef void(CLASSNAME::*AuraEffectProcFnType)(Unit*, Unit*, uint32, SpellInfo const*, uint32, uint32, WeaponAttackType, uint32 &, bool &); \
AURASCRIPT_FUNCTION_TYPE_DEFINES(AuraScript)
@@ -504,6 +506,14 @@ class AuraScript : public _SpellScript
private:
AuraEffectAbsorbFnType pEffectHandlerScript;
};
+ class EffectProcHandler
+ {
+ public:
+ EffectProcHandler(AuraEffectProcFnType effectProcScript);
+ void Call(AuraScript* auraScript, Unit* unit, Unit* victim, uint32 damage, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, uint32& cooldown, bool& takeCharges);
+ private:
+ AuraEffectProcFnType pEffectProcScript;
+ };
#define AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \
class CheckAreaTargetFunction : public AuraScript::CheckAreaTargetHandler { public: CheckAreaTargetFunction(AuraCheckAreaTargetFnType _pHandlerScript) : AuraScript::CheckAreaTargetHandler((AuraScript::AuraCheckAreaTargetFnType)_pHandlerScript) {} }; \
@@ -516,6 +526,7 @@ class AuraScript : public _SpellScript
class EffectApplyHandlerFunction : public AuraScript::EffectApplyHandler { public: EffectApplyHandlerFunction(AuraEffectApplicationModeFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName, AuraEffectHandleModes _mode) : AuraScript::EffectApplyHandler((AuraScript::AuraEffectApplicationModeFnType)_pEffectHandlerScript, _effIndex, _effName, _mode) {} }; \
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 EffectProcHandlerFunction : public AuraScript::EffectProcHandler { public: EffectProcHandlerFunction(AuraEffectProcFnType _pEffectProcScript) : AuraScript::EffectProcHandler((AuraScript::AuraEffectProcFnType)_pEffectProcScript) {} }; \
#define PrepareAuraScript(CLASSNAME) AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME)
@@ -640,6 +651,12 @@ class AuraScript : public _SpellScript
// where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount);
HookList<EffectManaShieldHandler> AfterEffectManaShield;
+ // executed when aura effect proc event occurs
+ // example: OnEffectProc += AuraEffectProcFn(class::function);
+ // where function is: void function (Unit* unit, Unit* victim, uint32 damage, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, uint32& cooldown, bool& takeCharges);
+ HookList<EffectProcHandler> OnEffectProc;
+ #define AuraEffectProcFn(F) EffectProcHandlerFunction(&F)
+
// 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)
diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp
index b746c37..ac0171a 100644
--- a/src/server/scripts/Spells/spell_mage.cpp
+++ b/src/server/scripts/Spells/spell_mage.cpp
@@ -340,13 +340,56 @@ public:
}
};
+// Hot Streak
+class spell_mage_hot_streak : public SpellScriptLoader
+{
+ public:
+ spell_mage_hot_streak() : SpellScriptLoader("spell_mage_hot_streak") { }
+
+ class spell_mage_hot_streak_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_mage_hot_streak_AuraScript);
+
+ void HandleProc(Unit* unit, Unit* victim, uint32 damage, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, uint32& cooldown, bool& takeCharges)
+ {
+ AuraEffect* counter = GetEffect(EFFECT_1);
+ if (!counter)
+ return;
+
+ // Count spell criticals in a row in second aura
+ if (procExtra & PROC_EX_CRITICAL_HIT)
+ {
+ counter->SetAmount(counter->GetAmount() * 2);
+ if (counter->GetAmount() < 100) // not enough
+ return;
+ // Crititcal counted -> roll chance
+ if (roll_chance_i(GetEffect(EFFECT_0)->GetAmount()))
+ unit->CastSpell(unit, 48108, true, NULL, GetEffect(EFFECT_0));
+ }
+ counter->SetAmount(25);
+ }
+
+ void Register()
+ {
+ OnEffectProc += AuraEffectProcFn(spell_mage_hot_streak_AuraScript::HandleProc);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_mage_hot_streak_AuraScript();
+ }
+};
+
+
void AddSC_mage_spell_scripts()
{
- new spell_mage_blast_wave;
- new spell_mage_cold_snap;
+ new spell_mage_blast_wave();
+ new spell_mage_cold_snap();
new spell_mage_frost_warding_trigger();
new spell_mage_incanters_absorbtion_absorb();
new spell_mage_incanters_absorbtion_manashield();
- new spell_mage_polymorph_cast_visual;
- new spell_mage_summon_water_elemental;
+ new spell_mage_polymorph_cast_visual();
+ new spell_mage_summon_water_elemental();
+ new spell_mage_hot_streak();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment