diff options
author | Faq <ainarsh@gmail.com> | 2012-09-18 23:19:31 +0300 |
---|---|---|
committer | Faq <ainarsh@gmail.com> | 2012-09-18 23:28:46 +0300 |
commit | 0e7ed5ec857706f27378b00773aa46b8825c3f27 (patch) | |
tree | cc1220c7797237fd247351381c17fe0d565aaa26 | |
parent | 378f83df4e363b1160291d411e7c31f78e604358 (diff) |
Core/Spells: Implementing some hooks for split damage taken, fixes the limitation of dmg such auras can split, for example at Hand of Sacrifice. Might have unexpected results, but they are called unexpected for a reason.. .Author Tibbi
closes #6025
Made new one as https://github.com/TrinityCore/TrinityCore/pull/7423/ was closed.
-rw-r--r-- | sql/updates/world/2012_09_18_02_world_spell_script_names.sql | 3 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 11 | ||||
-rwxr-xr-x | src/server/game/Spells/Auras/SpellAuras.cpp | 15 | ||||
-rwxr-xr-x | src/server/game/Spells/Auras/SpellAuras.h | 2 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellScript.cpp | 18 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellScript.h | 17 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_paladin.cpp | 49 |
7 files changed, 111 insertions, 4 deletions
diff --git a/sql/updates/world/2012_09_18_02_world_spell_script_names.sql b/sql/updates/world/2012_09_18_02_world_spell_script_names.sql new file mode 100644 index 00000000000..00734753691 --- /dev/null +++ b/sql/updates/world/2012_09_18_02_world_spell_script_names.sql @@ -0,0 +1,3 @@ +DELETE FROM spell_script_names WHERE spell_id = 6940; +INSERT INTO spell_script_names (spell_id, ScriptName) VALUES +(6940, 'spell_pal_hand_of_sacrifice'); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 6e9ebb38e48..a5ba72cb9b2 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1769,8 +1769,10 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(), next; (itr != vSplitDamagePctCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr) { // Check if aura was removed during iteration - we don't need to work on such auras - if (!((*itr)->GetBase()->IsAppliedOnTarget(victim->GetGUID()))) + AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(victim->GetGUID()); + if (!aurApp) continue; + // check damage school mask if (!((*itr)->GetMiscValue() & schoolMask)) continue; @@ -1780,13 +1782,14 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->isAlive()) continue; - int32 splitDamage = CalculatePctN(dmgInfo.GetDamage(), (*itr)->GetAmount()); + uint32 splitDamage = CalculatePctN(dmgInfo.GetDamage(), (*itr)->GetAmount()); + + (*itr)->GetBase()->CallScriptEffectSplitHandlers((*itr), aurApp, dmgInfo, splitDamage); // absorb must be smaller than the damage itself - splitDamage = RoundToInterval(splitDamage, 0, int32(dmgInfo.GetDamage())); + splitDamage = RoundToInterval(splitDamage, uint32(0), uint32(dmgInfo.GetDamage())); dmgInfo.AbsorbDamage(splitDamage); - uint32 splitted = splitDamage; uint32 split_absorb = 0; DealDamageMods(caster, splitted, &split_absorb); diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 3de11b98e30..abffc65245d 100755 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -2324,6 +2324,21 @@ void Aura::CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraAppli } } +void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & splitAmount) +{ + for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + { + (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_SPLIT, aurApp); + std::list<AuraScript::EffectSplitHandler>::iterator effEndItr = (*scritr)->OnEffectSplit.end(), effItr = (*scritr)->OnEffectSplit.begin(); + for (; effItr != effEndItr; ++effItr) + { + if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + (*effItr).Call(*scritr, aurEff, dmgInfo, splitAmount); + } + (*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 2f50d47a79b..85c8992c597 100755 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -217,6 +217,8 @@ 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); + void CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & splitAmount); + 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 1399934efeb..f7ab6e22f2e 100755 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -675,6 +675,10 @@ 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 `AfterEffectManaShield` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + for (std::list<EffectSplitHandler>::iterator itr = OnEffectSplit.begin(); itr != OnEffectSplit.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 `OnEffectSplit` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + return _SpellScript::_Validate(entry); } @@ -803,6 +807,17 @@ void AuraScript::EffectManaShieldHandler::Call(AuraScript* auraScript, AuraEffec (auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, absorbAmount); } +AuraScript::EffectSplitHandler::EffectSplitHandler(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex) + : AuraScript::EffectBase(_effIndex, SPELL_AURA_SPLIT_DAMAGE_PCT) +{ + pEffectHandlerScript = _pEffectHandlerScript; +} + +void AuraScript::EffectSplitHandler::Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& splitAmount) +{ + (auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, splitAmount); +} + bool AuraScript::_Load(Aura* aura) { m_aura = aura; @@ -837,6 +852,7 @@ bool AuraScript::_IsDefaultActionPrevented() case AURA_SCRIPT_HOOK_EFFECT_REMOVE: case AURA_SCRIPT_HOOK_EFFECT_PERIODIC: case AURA_SCRIPT_HOOK_EFFECT_ABSORB: + case AURA_SCRIPT_HOOK_EFFECT_SPLIT: return m_defaultActionPrevented; default: ASSERT(false && "AuraScript::_IsDefaultActionPrevented is called in a wrong place"); @@ -852,6 +868,7 @@ void AuraScript::PreventDefaultAction() case AURA_SCRIPT_HOOK_EFFECT_REMOVE: case AURA_SCRIPT_HOOK_EFFECT_PERIODIC: case AURA_SCRIPT_HOOK_EFFECT_ABSORB: + case AURA_SCRIPT_HOOK_EFFECT_SPLIT: m_defaultActionPrevented = true; break; default: @@ -1033,6 +1050,7 @@ Unit* AuraScript::GetTarget() const case AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB: case AURA_SCRIPT_HOOK_EFFECT_MANASHIELD: case AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD: + case AURA_SCRIPT_HOOK_EFFECT_SPLIT: 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 460a4e20d7f..a5d77806739 100755 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -423,6 +423,7 @@ enum AuraScriptHookType AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, AURA_SCRIPT_HOOK_EFFECT_MANASHIELD, AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD, + AURA_SCRIPT_HOOK_EFFECT_SPLIT, AURA_SCRIPT_HOOK_CHECK_AREA_TARGET, AURA_SCRIPT_HOOK_DISPEL, AURA_SCRIPT_HOOK_AFTER_DISPEL @@ -449,6 +450,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::*AuraEffectSplitFnType)(AuraEffect*, DamageInfo &, uint32 &); \ AURASCRIPT_FUNCTION_TYPE_DEFINES(AuraScript) @@ -540,6 +542,14 @@ class AuraScript : public _SpellScript private: AuraEffectAbsorbFnType pEffectHandlerScript; }; + class EffectSplitHandler : public EffectBase + { + public: + EffectSplitHandler(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex); + void Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & splitAmount); + private: + AuraEffectSplitFnType pEffectHandlerScript; + }; #define AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \ class CheckAreaTargetFunction : public AuraScript::CheckAreaTargetHandler { public: CheckAreaTargetFunction(AuraCheckAreaTargetFnType _pHandlerScript) : AuraScript::CheckAreaTargetHandler((AuraScript::AuraCheckAreaTargetFnType)_pHandlerScript) {} }; \ @@ -552,6 +562,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 EffectSplitFunction : public AuraScript::EffectSplitHandler { public: EffectSplitFunction(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectSplitHandler((AuraScript::AuraEffectSplitFnType)_pEffectHandlerScript, _effIndex) {} }; \ #define PrepareAuraScript(CLASSNAME) AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) @@ -676,6 +687,12 @@ class AuraScript : public _SpellScript // where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount); HookList<EffectManaShieldHandler> AfterEffectManaShield; + // executed when the caster of some spell with split dmg aura gets damaged through it + // example: OnEffectSplit += AuraEffectSplitFn(class::function, EffectIndexSpecifier); + // where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& splitAmount); + HookList<EffectSplitHandler> OnEffectSplit; + #define AuraEffectSplitFn(F, I) EffectSplitFunction(&F, I) + // 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_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index 0bf2e5664a0..43c4dc139a3 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -47,6 +47,8 @@ enum PaladinSpells SPELL_FORBEARANCE = 25771, SPELL_AVENGING_WRATH_MARKER = 61987, SPELL_IMMUNE_SHIELD_MARKER = 61988, + + SPELL_HAND_OF_SACRIFICE = 6940, }; // 31850 - Ardent Defender @@ -566,6 +568,52 @@ class spell_pal_exorcism_and_holy_wrath_damage : public SpellScriptLoader } }; +class spell_pal_hand_of_sacrifice : public SpellScriptLoader +{ + public: + spell_pal_hand_of_sacrifice() : SpellScriptLoader("spell_pal_hand_of_sacrifice") { } + + class spell_pal_hand_of_sacrifice_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pal_hand_of_sacrifice_AuraScript); + + uint32 splitPct; + int32 remainingAmount; + Unit* caster; + + bool Load() + { + caster = GetCaster(); + if (!caster) + return false; + remainingAmount = caster->GetMaxHealth(); + splitPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster()); + return true; + } + + void Split(AuraEffect* /*aurEff*/, DamageInfo & /*dmgInfo*/, uint32 & splitAmount) + { + remainingAmount -= splitAmount; + + if (remainingAmount <= 0) + { + Unit* target = GetTarget(); + target->RemoveAura(SPELL_HAND_OF_SACRIFICE); + } + } + + void Register() + { + OnEffectSplit += AuraEffectSplitFn(spell_pal_hand_of_sacrifice_AuraScript::Split, EFFECT_0); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pal_hand_of_sacrifice_AuraScript(); + } +}; + void AddSC_paladin_spell_scripts() { new spell_pal_ardent_defender(); @@ -579,4 +627,5 @@ void AddSC_paladin_spell_scripts() new spell_pal_lay_on_hands(); new spell_pal_righteous_defense(); new spell_pal_exorcism_and_holy_wrath_damage(); + new spell_pal_hand_of_sacrifice(); } |