mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Auras: Implemented SPELL_AURA_SCHOOL_ABSORB_OVERKILL (#26269)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user