aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatan Shukry <matanshukry@gmail.com>2021-04-17 23:42:34 +0300
committerGitHub <noreply@github.com>2021-04-17 22:42:34 +0200
commit530631e0a73c0bcd540f063cef975ecd827307b2 (patch)
tree6c80c5495198ed256a10d9a3ee9ce2acbea8637c
parent5b4f61d915475e44369430994cb636d14c2976b8 (diff)
Core/Auras: Implemented SPELL_AURA_SCHOOL_ABSORB_OVERKILL (#26269)
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp64
-rw-r--r--src/server/game/Entities/Unit/Unit.h5
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h1
-rw-r--r--src/server/game/Spells/SpellScript.cpp4
-rw-r--r--src/server/game/Spells/SpellScript.h5
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp14
7 files changed, 75 insertions, 20 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index a1143318983..20b4957e604 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -866,15 +866,68 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
victim->ToCreature()->LowerPlayerDamageReq(health < damage ? health : damage);
}
+ bool killed = false;
+ bool skipSettingDeathState = false;
+
if (health <= damage)
{
+ killed = true;
+
TC_LOG_DEBUG("entities.unit", "DealDamage: victim just died");
if (victim->GetTypeId() == TYPEID_PLAYER && victim != this)
victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, health);
- Kill(victim, durabilityLoss);
+ if (damagetype != NODAMAGE && damagetype != SELF_DAMAGE && victim->HasAuraType(SPELL_AURA_SCHOOL_ABSORB_OVERKILL))
+ {
+ AuraEffectList vAbsorbOverkill = victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB_OVERKILL);
+ DamageInfo damageInfo = DamageInfo(this, victim, damage, spellProto, damageSchoolMask, damagetype,
+ cleanDamage ? cleanDamage->attackType : BASE_ATTACK);
+ for (AuraEffect* absorbAurEff : vAbsorbOverkill)
+ {
+ Aura* base = absorbAurEff->GetBase();
+ AuraApplication const* aurApp = base->GetApplicationOfTarget(victim->GetGUID());
+ if (!aurApp)
+ continue;
+
+ if (!(absorbAurEff->GetMiscValue() & damageInfo.GetSchoolMask()))
+ continue;
+
+ // cannot absorb over limit
+ if (damage >= victim->CountPctFromMaxHealth(100 + absorbAurEff->GetMiscValueB()))
+ continue;
+
+ // 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);
+
+ // This aura type is used both by Spirit of Redemption (death not really prevented, must grant all credit immediately) and Cheat Death (death prevented)
+ // repurpose PreventDefaultAction for this
+ bool deathFullyPrevented = false;
+
+ absorbAurEff->GetBase()->CallScriptEffectAbsorbHandlers(absorbAurEff, aurApp, damageInfo, tempAbsorb, deathFullyPrevented);
+ currentAbsorb = tempAbsorb;
+
+ // absorb must be smaller than the damage itself
+ currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(damageInfo.GetDamage()));
+ damageInfo.AbsorbDamage(currentAbsorb);
+
+ if (deathFullyPrevented)
+ killed = false;
+
+ skipSettingDeathState = true;
+ }
+
+ damage = damageInfo.GetDamage();
+ }
}
+
+ if (killed)
+ Kill(victim, durabilityLoss, skipSettingDeathState);
else
{
TC_LOG_DEBUG("entities.unit", "DealDamageAlive");
@@ -11471,7 +11524,7 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId)
SendMessageToSet(data.Write(), true);
}
-void Unit::Kill(Unit* victim, bool durabilityLoss)
+void Unit::Kill(Unit* victim, bool durabilityLoss /*= true*/, bool skipSettingDeathState /*= false*/)
{
// Prevent killing unit twice (and giving reward from kill twice)
if (!victim->GetHealth())
@@ -11586,8 +11639,11 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
if (Player* killerPlayer = GetCharmerOrOwnerPlayerOrPlayerItself())
killerPlayer->UpdateCriteria(CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, 0, victim);
- TC_LOG_DEBUG("entities.unit", "SET JUST_DIED");
- victim->setDeathState(JUST_DIED);
+ if (!skipSettingDeathState)
+ {
+ TC_LOG_DEBUG("entities.unit", "SET JUST_DIED");
+ victim->setDeathState(JUST_DIED);
+ }
// Inform pets (if any) when player kills target)
// MUST come after victim->setDeathState(JUST_DIED); or pet next target
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 92da6ccbb20..6af545a36a3 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1043,8 +1043,8 @@ class TC_GAME_API Unit : public WorldObject
uint16 GetMaxSkillValueForLevel(Unit const* target = nullptr) const { return (target ? GetLevelForTarget(target) : getLevel()) * 5; }
void DealDamageMods(Unit const* victim, uint32 &damage, uint32* absorb) const;
uint32 DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage = nullptr, DamageEffectType damagetype = DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* spellProto = nullptr, bool durabilityLoss = true);
- void Kill(Unit* victim, bool durabilityLoss = true);
- void KillSelf(bool durabilityLoss = true) { Kill(this, durabilityLoss); }
+ void Kill(Unit* victim, bool durabilityLoss = true, bool skipSettingDeathState = false);
+ void KillSelf(bool durabilityLoss = true, bool skipSettingDeathState = false) { Kill(this, durabilityLoss, skipSettingDeathState); }
void DealHeal(HealInfo& healInfo);
void ProcSkillsAndAuras(Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget,
@@ -1414,6 +1414,7 @@ class TC_GAME_API Unit : public WorldObject
void _ApplyAllAuraStatMods();
AuraEffectList const& GetAuraEffectsByType(AuraType type) const { return m_modAuras[type]; }
+ AuraEffectList& GetAuraEffectsByType(AuraType type) { return m_modAuras[type]; }
AuraList & GetSingleCastAuras() { return m_scAuras; }
AuraList const& GetSingleCastAuras() const { return m_scAuras; }
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index cf5ed8a765d..786af2bf428 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -383,7 +383,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNULL, //313 SPELL_AURA_MOUNT_ANIM_REPLACEMENT_SET implemented clientside
&AuraEffect::HandlePreventResurrection, //314 SPELL_AURA_PREVENT_RESURRECTION todo
&AuraEffect::HandleNoImmediateEffect, //315 SPELL_AURA_UNDERWATER_WALKING todo
- &AuraEffect::HandleNULL, //316 SPELL_AURA_SCHOOL_ABSORB_OVERKILL
+ &AuraEffect::HandleNoImmediateEffect, //316 SPELL_AURA_SCHOOL_ABSORB_OVERKILL implemented in Unit::DealDamage()
&AuraEffect::HandleNULL, //317 SPELL_AURA_MOD_SPELL_POWER_PCT
&AuraEffect::HandleMastery, //318 SPELL_AURA_MASTERY
&AuraEffect::HandleModMeleeSpeedPct, //319 SPELL_AURA_MOD_MELEE_HASTE_3
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index 12e9547b4d6..8f5f1eb2efb 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -309,6 +309,7 @@ class TC_GAME_API AuraEffect
void HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraSetVehicle(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandlePreventResurrection(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleAbsorbOverkill(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleMastery(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraForceWeather(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleEnableAltPower(AuraApplication const* aurApp, uint8 mode, bool apply) const;
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 62b57b3a36a..12337bd0c67 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -928,8 +928,8 @@ void AuraScript::EffectApplyHandler::Call(AuraScript* auraScript, AuraEffect con
(auraScript->*pEffectHandlerScript)(_aurEff, _mode);
}
-AuraScript::EffectAbsorbHandler::EffectAbsorbHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex)
- : AuraScript::EffectBase(_effIndex, SPELL_AURA_SCHOOL_ABSORB)
+AuraScript::EffectAbsorbHandler::EffectAbsorbHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex, bool overKill)
+ : AuraScript::EffectBase(_effIndex, overKill ? SPELL_AURA_SCHOOL_ABSORB_OVERKILL : SPELL_AURA_SCHOOL_ABSORB)
{
pEffectHandlerScript = _pEffectHandlerScript;
}
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index efda8bc4d3d..7325f75b3f6 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -654,7 +654,7 @@ class TC_GAME_API AuraScript : public _SpellScript
class TC_GAME_API EffectAbsorbHandler : public EffectBase
{
public:
- EffectAbsorbHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex);
+ EffectAbsorbHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex, bool overKill);
void Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount);
private:
AuraEffectAbsorbFnType pEffectHandlerScript;
@@ -726,7 +726,7 @@ class TC_GAME_API AuraScript : public _SpellScript
class EffectCalcSpellModHandlerFunction : public AuraScript::EffectCalcSpellModHandler { public: EffectCalcSpellModHandlerFunction(AuraEffectCalcSpellModFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectCalcSpellModHandler((AuraScript::AuraEffectCalcSpellModFnType)_pEffectHandlerScript, _effIndex, _effName) { } }; \
class EffectCalcCritChanceHandlerFunction : public AuraScript::EffectCalcCritChanceHandler { public: EffectCalcCritChanceHandlerFunction(AuraEffectCalcCritChanceFnType effectHandlerScript, uint8 effIndex, uint16 effName) : AuraScript::EffectCalcCritChanceHandler((AuraScript::AuraEffectCalcCritChanceFnType)effectHandlerScript, effIndex, effName) { } }; \
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 EffectAbsorbFunction : public AuraScript::EffectAbsorbHandler { public: EffectAbsorbFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex, bool overkill = false) : AuraScript::EffectAbsorbHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex, overkill) { } }; \
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) { } }; \
@@ -847,6 +847,7 @@ class TC_GAME_API AuraScript : public _SpellScript
// where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount);
HookList<EffectAbsorbHandler> OnEffectAbsorb;
#define AuraEffectAbsorbFn(F, I) EffectAbsorbFunction(&F, I)
+ #define AuraEffectAbsorbOverkillFn(F, I) EffectAbsorbFunction(&F, I, true)
// executed after absorb aura effect reduced damage to target - absorbAmount is real amount absorbed by aura
// example: AfterEffectAbsorb += AuraEffectAbsorbFn(class::function, EffectIndexSpecifier);
diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp
index 7e377f496a8..8a0995098af 100644
--- a/src/server/scripts/Spells/spell_priest.cpp
+++ b/src/server/scripts/Spells/spell_priest.cpp
@@ -759,22 +759,18 @@ class spell_priest_spirit_of_redemption : public AuraScript
return ValidateSpellInfo({ SPELL_PRIEST_SPIRIT_OF_REDEMPTION });
}
- void HandleAbsorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& /*absorbAmount*/)
+ void HandleAbsorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount)
{
Unit* target = GetTarget();
- if (dmgInfo.GetDamage() >= target->GetHealth())
- {
- target->CastSpell(target, SPELL_PRIEST_SPIRIT_OF_REDEMPTION, aurEff);
- target->SetFullHealth();
- return;
- }
+ target->CastSpell(target, SPELL_PRIEST_SPIRIT_OF_REDEMPTION, aurEff);
+ target->SetFullHealth();
- PreventDefaultAction();
+ absorbAmount = dmgInfo.GetDamage();
}
void Register() override
{
- OnEffectAbsorb += AuraEffectAbsorbFn(spell_priest_spirit_of_redemption::HandleAbsorb, EFFECT_0);
+ OnEffectAbsorb += AuraEffectAbsorbOverkillFn(spell_priest_spirit_of_redemption::HandleAbsorb, EFFECT_0);
}
};