aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp64
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp32
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h2
-rw-r--r--src/server/game/Spells/SpellScript.cpp11
-rw-r--r--src/server/game/Spells/SpellScript.h21
5 files changed, 98 insertions, 32 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index d42751dcbf0..2339aca1d2d 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -1976,53 +1976,53 @@ void Unit::HandleEmoteCommand(Emote emoteId, Player* target /*=nullptr*/, Trinit
if (!healInfo.GetHeal())
return;
- // Need remove expired auras after
- bool existExpired = false;
-
// absorb without mana cost
AuraEffectList const& vHealAbsorb = healInfo.GetTarget()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_HEAL_ABSORB);
for (AuraEffectList::const_iterator i = vHealAbsorb.begin(); i != vHealAbsorb.end() && healInfo.GetHeal() > 0; ++i)
{
- if (!((*i)->GetMiscValue() & healInfo.GetSpellInfo()->SchoolMask))
+ AuraEffect * absorbAurEff = *i;
+ // Check if aura was removed during iteration - we don't need to work on such auras
+ AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(healInfo.GetTarget()->GetGUID());
+ if (!aurApp)
continue;
- // Max Amount can be absorbed by this aura
- int32 currentAbsorb = (*i)->GetAmount();
+ if (!(absorbAurEff->GetMiscValue() & healInfo.GetSchoolMask()))
+ continue;
- // Found empty aura (impossible but..)
- if (currentAbsorb <= 0)
- {
- existExpired = true;
+ // get amount which can be still absorbed by the aura
+ int32 currentAbsorb = absorbAurEff->GetAmount();
+ // aura with infinite absorb amount - let the scripts handle absorbtion amount, set here to 0 for safety
+ if (currentAbsorb < 0)
+ currentAbsorb = 0;
+
+ uint32 tempAbsorb = uint32(currentAbsorb);
+
+ bool defaultPrevented = false;
+
+ absorbAurEff->GetBase()->CallScriptEffectAbsorbHandlers(absorbAurEff, aurApp, healInfo, tempAbsorb, defaultPrevented);
+ currentAbsorb = tempAbsorb;
+
+ if (defaultPrevented)
continue;
- }
// currentAbsorb - damage can be absorbed by shield
- // If need absorb less damage
currentAbsorb = std::min<int32>(healInfo.GetHeal(), currentAbsorb);
healInfo.AbsorbHeal(currentAbsorb);
- // Reduce shield amount
- (*i)->ChangeAmount((*i)->GetAmount() - currentAbsorb);
- // Need remove it later
- if ((*i)->GetAmount() <= 0)
- existExpired = true;
- }
+ tempAbsorb = currentAbsorb;
+ absorbAurEff->GetBase()->CallScriptEffectAfterAbsorbHandlers(absorbAurEff, aurApp, healInfo, tempAbsorb);
- // Remove all expired absorb auras
- if (existExpired)
- {
- for (AuraEffectList::const_iterator i = vHealAbsorb.begin(); i != vHealAbsorb.end();)
- {
- AuraEffect* auraEff = *i;
- ++i;
- if (auraEff->GetAmount() <= 0)
- {
- uint32 removedAuras = healInfo.GetTarget()->m_removedAurasCount;
- auraEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
- if (removedAuras + 1 < healInfo.GetTarget()->m_removedAurasCount)
- i = vHealAbsorb.begin();
- }
+ // Reduce shield amount
+ absorbAurEff->ChangeAmount((*i)->GetAmount() - currentAbsorb);
+ // Check if our aura is using amount to count damage
+ if (absorbAurEff->GetAmount() >= 0)
+ {
+ // Reduce shield amount
+ absorbAurEff->ChangeAmount(absorbAurEff->GetAmount() - currentAbsorb);
+ // Aura cannot absorb anything more - remove it
+ if (absorbAurEff->GetAmount() <= 0)
+ absorbAurEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
}
}
}
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index da2c0c2b6c9..3ad6cf25935 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -2200,6 +2200,23 @@ void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication co
}
}
+void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount, bool& defaultPrevented)
+{
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp);
+ auto effEndItr = (*scritr)->OnEffectAbsorbHeal.end(), effItr = (*scritr)->OnEffectAbsorbHeal.begin();
+ for (; effItr != effEndItr; ++effItr)
+
+ if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
+ effItr->Call(*scritr, aurEff, healInfo, absorbAmount);
+
+ if (!defaultPrevented)
+ defaultPrevented = (*scritr)->_IsDefaultActionPrevented();
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount)
{
for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
@@ -2214,6 +2231,21 @@ void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplicati
}
}
+void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount)
+{
+ for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp);
+ auto effEndItr = (*scritr)->AfterEffectAbsorbHeal.end(), effItr = (*scritr)->AfterEffectAbsorbHeal.begin();
+ for (; effItr != effEndItr; ++effItr)
+
+ if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
+ effItr->Call(*scritr, aurEff, healInfo, absorbAmount);
+
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& /*defaultPrevented*/)
{
for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index 3aa899513ba..0ae0110b5d0 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -277,7 +277,9 @@ class TC_GAME_API Aura
void CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellModifier*& spellMod);
void CallScriptEffectCalcCritChanceHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit const* victim, float& critChance);
void CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool & defaultPrevented);
+ void CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount, bool& defaultPrevented);
void CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount);
+ void CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, 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);
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 100ea02fbe5..772426ae5ed 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -1164,11 +1164,22 @@ AuraScript::EffectAbsorbHandler::EffectAbsorbHandler(EffectAbsorbHandler&& right
AuraScript::EffectAbsorbHandler& AuraScript::EffectAbsorbHandler::operator=(EffectAbsorbHandler&& right) noexcept = default;
AuraScript::EffectAbsorbHandler::~EffectAbsorbHandler() = default;
+AuraScript::EffectAbsorbHealHandler::EffectAbsorbHealHandler(AuraEffectAbsorbHealFnType _pEffectHandlerScript, uint8 _effIndex)
+ : AuraScript::EffectBase(_effIndex, SPELL_AURA_SCHOOL_HEAL_ABSORB)
+{
+ pEffectHandlerScript = _pEffectHandlerScript;
+}
+
void AuraScript::EffectAbsorbHandler::Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount)
{
(auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, absorbAmount);
}
+void AuraScript::EffectAbsorbHealHandler::Call(AuraScript * auraScript, AuraEffect * aurEff, HealInfo & healInfo, uint32 & absorbAmount)
+{
+ (auraScript->*pEffectHandlerScript)(aurEff, healInfo, absorbAmount);
+}
+
AuraScript::EffectManaShieldHandler::EffectManaShieldHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex)
: AuraScript::EffectBase(_effIndex, SPELL_AURA_MANA_SHIELD), pEffectHandlerScript(_pEffectHandlerScript)
{
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 7cbb3a5121b..7deec060f01 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -690,6 +690,7 @@ class TC_GAME_API AuraScript : public _SpellScript
typedef void(CLASSNAME::*AuraEffectCalcSpellModFnType)(AuraEffect const*, SpellModifier* &); \
typedef void(CLASSNAME::*AuraEffectCalcCritChanceFnType)(AuraEffect const*, Unit const*, float&); \
typedef void(CLASSNAME::*AuraEffectAbsorbFnType)(AuraEffect*, DamageInfo &, uint32 &); \
+ typedef void(CLASSNAME::*AuraEffectAbsorbHealFnType)(AuraEffect*, HealInfo &, uint32 &); \
typedef void(CLASSNAME::*AuraEffectSplitFnType)(AuraEffect*, DamageInfo &, uint32 &); \
typedef bool(CLASSNAME::*AuraCheckProcFnType)(ProcEventInfo&); \
typedef bool(CLASSNAME::*AuraCheckEffectProcFnType)(AuraEffect const*, ProcEventInfo&); \
@@ -842,6 +843,14 @@ class TC_GAME_API AuraScript : public _SpellScript
private:
AuraEffectAbsorbFnType pEffectHandlerScript;
};
+ class TC_GAME_API EffectAbsorbHealHandler : public EffectBase
+ {
+ public:
+ EffectAbsorbHealHandler(AuraEffectAbsorbHealFnType _pEffectHandlerScript, uint8 _effIndex);
+ void Call(AuraScript* auraScript, AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount);
+ private:
+ AuraEffectAbsorbHealFnType pEffectHandlerScript;
+ };
class TC_GAME_API EffectManaShieldHandler : public EffectBase
{
public:
@@ -945,6 +954,7 @@ class TC_GAME_API AuraScript : public _SpellScript
class EffectCalcCritChanceHandlerFunction : public AuraScript::EffectCalcCritChanceHandler { public: explicit EffectCalcCritChanceHandlerFunction(AuraEffectCalcCritChanceFnType effectHandlerScript, uint8 effIndex, uint16 effName) : AuraScript::EffectCalcCritChanceHandler((AuraScript::AuraEffectCalcCritChanceFnType)effectHandlerScript, effIndex, effName) { } }; \
class EffectApplyHandlerFunction : public AuraScript::EffectApplyHandler { public: explicit EffectApplyHandlerFunction(AuraEffectApplicationModeFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName, AuraEffectHandleModes _mode) : AuraScript::EffectApplyHandler((AuraScript::AuraEffectApplicationModeFnType)_pEffectHandlerScript, _effIndex, _effName, _mode) { } }; \
class EffectAbsorbFunction : public AuraScript::EffectAbsorbHandler { public: explicit EffectAbsorbFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex, bool overkill = false) : AuraScript::EffectAbsorbHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex, overkill) { } }; \
+ class EffectAbsorbHealFunction : public AuraScript::EffectAbsorbHealHandler { public: EffectAbsorbHealFunction(AuraEffectAbsorbHealFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectAbsorbHealHandler((AuraScript::AuraEffectAbsorbHealFnType)_pEffectHandlerScript, _effIndex) { } }; \
class EffectManaShieldFunction : public AuraScript::EffectManaShieldHandler { public: explicit EffectManaShieldFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectManaShieldHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex) { } }; \
class EffectSplitFunction : public AuraScript::EffectSplitHandler { public: explicit EffectSplitFunction(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectSplitHandler((AuraScript::AuraEffectSplitFnType)_pEffectHandlerScript, _effIndex) { } }; \
class CheckProcHandlerFunction : public AuraScript::CheckProcHandler { public: explicit CheckProcHandlerFunction(AuraCheckProcFnType handlerScript) : AuraScript::CheckProcHandler((AuraScript::AuraCheckProcFnType)handlerScript) { } }; \
@@ -1067,11 +1077,22 @@ class TC_GAME_API AuraScript : public _SpellScript
#define AuraEffectAbsorbFn(F, I) EffectAbsorbFunction(&F, I)
#define AuraEffectAbsorbOverkillFn(F, I) EffectAbsorbFunction(&F, I, true)
+ // executed when absorb aura effect is going to reduce damage
+ // example: OnEffectAbsorbHeal += AuraEffectAbsorbHealFn(class::function, EffectIndexSpecifier);
+ // where function is: void function (AuraEffect const* aurEff, HealInfo& healInfo, uint32& absorbAmount);
+ HookList<EffectAbsorbHealHandler> OnEffectAbsorbHeal;
+ #define AuraEffectAbsorbHealFn(F, I) EffectAbsorbHealFunction(&F, I)
+
// executed after absorb aura effect reduced damage to target - absorbAmount is real amount absorbed by aura
// example: AfterEffectAbsorb += AuraEffectAbsorbFn(class::function, EffectIndexSpecifier);
// where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount);
HookList<EffectAbsorbHandler> AfterEffectAbsorb;
+ // executed after absorb aura effect reduced heal to target - absorbAmount is real amount absorbed by aura
+ // example: AfterEffectAbsorbHeal += AuraEffectAbsorbHealFn(class::function, EffectIndexSpecifier);
+ // where function is: void function (AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount);
+ HookList<EffectAbsorbHealHandler> AfterEffectAbsorbHeal;
+
// executed when mana shield aura effect is going to reduce damage
// example: OnEffectManaShield += AuraEffectManaShieldFn(class::function, EffectIndexSpecifier);
// where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount);