aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp11
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.cpp15
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.h2
-rwxr-xr-xsrc/server/game/Spells/SpellScript.cpp18
-rwxr-xr-xsrc/server/game/Spells/SpellScript.h17
-rw-r--r--src/server/scripts/Spells/spell_paladin.cpp49
6 files changed, 108 insertions, 4 deletions
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();
}