Core/Auras: Implemented SPELL_AURA_SCHOOL_ABSORB_OVERKILL

Port From (https://github.com/TrinityCore/TrinityCore/commit/530631e0a73c0bcd540f063cef975ecd827307b2)
This commit is contained in:
hondacrx
2021-04-19 10:36:03 -04:00
parent c925d7af40
commit 3ac625e8ff
3 changed files with 67 additions and 15 deletions
+61 -5
View File
@@ -1125,15 +1125,68 @@ namespace Game.Entities
victim.ToCreature().LowerPlayerDamageReq(health < damage ? health : damage);
}
bool killed = false;
bool skipSettingDeathState = false;
if (health <= damage)
{
killed = true;
Log.outDebug(LogFilter.Unit, "DealDamage: victim just died");
if (victim.IsTypeId(TypeId.Player) && victim != this)
victim.ToPlayer().UpdateCriteria(CriteriaTypes.TotalDamageReceived, health);
Kill(victim, durabilityLoss);
if (damagetype != DamageEffectType.NoDamage && damagetype != DamageEffectType.Self && victim.HasAuraType(AuraType.SchoolAbsorbOverkill))
{
var vAbsorbOverkill = victim.GetAuraEffectsByType(AuraType.SchoolAbsorbOverkill);
DamageInfo damageInfo = new(this, victim, damage, spellProto, damageSchoolMask, damagetype, cleanDamage != null ? cleanDamage.attackType : WeaponAttackType.BaseAttack);
foreach (var absorbAurEff in vAbsorbOverkill)
{
Aura baseAura = absorbAurEff.GetBase();
AuraApplication aurApp = baseAura.GetApplicationOfTarget(victim.GetGUID());
if (aurApp == null)
continue;
if ((absorbAurEff.GetMiscValue() & (int)damageInfo.GetSchoolMask()) == 0)
continue;
// cannot absorb over limit
if (damage >= victim.CountPctFromMaxHealth(100 + absorbAurEff.GetMiscValueB()))
continue;
// get amount which can be still absorbed by the aura
int 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;
uint tempAbsorb = (uint)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, ref tempAbsorb, ref deathFullyPrevented);
currentAbsorb = (int)tempAbsorb;
// absorb must be smaller than the damage itself
currentAbsorb = MathFunctions.RoundToInterval(ref currentAbsorb, 0, (int)damageInfo.GetDamage());
damageInfo.AbsorbDamage((uint)currentAbsorb);
if (deathFullyPrevented)
killed = false;
skipSettingDeathState = true;
}
damage = damageInfo.GetDamage();
}
}
if (killed)
Kill(victim, durabilityLoss, skipSettingDeathState);
else
{
Log.outDebug(LogFilter.Unit, "DealDamageAlive");
@@ -1484,7 +1537,7 @@ namespace Game.Entities
Cell.VisitWorldObjects(this, notifier, GetVisibilityRange());
}
public void Kill(Unit victim, bool durabilityLoss = true)
public void Kill(Unit victim, bool durabilityLoss = true, bool skipSettingDeathState = false)
{
// Prevent killing unit twice (and giving reward from kill twice)
if (victim.GetHealth() == 0)
@@ -1599,8 +1652,11 @@ namespace Game.Entities
if (player != null)
player.UpdateCriteria(CriteriaTypes.GetKillingBlows, 1, 0, 0, victim);
Log.outDebug(LogFilter.Unit, "SET JUST_DIED");
victim.SetDeathState(DeathState.JustDied);
if (!skipSettingDeathState)
{
Log.outDebug(LogFilter.Unit, "SET JUST_DIED");
victim.SetDeathState(DeathState.JustDied);
}
// Inform pets (if any) when player kills target)
// MUST come after victim.setDeathState(JUST_DIED); or pet next target
@@ -1760,7 +1816,7 @@ namespace Game.Entities
}
}
public void KillSelf(bool durabilityLoss = true) { Kill(this, durabilityLoss); }
public void KillSelf(bool durabilityLoss = true, bool skipSettingDeathState = false) { Kill(this, durabilityLoss, skipSettingDeathState); }
public virtual float GetBlockPercent(uint attackerLevel) { return 30.0f; }
+2 -2
View File
@@ -940,8 +940,8 @@ namespace Game.Scripting
}
public class EffectAbsorbHandler : EffectBase
{
public EffectAbsorbHandler(AuraEffectAbsorbDelegate _pEffectHandlerScript, byte _effIndex)
: base(_effIndex, AuraType.SchoolAbsorb)
public EffectAbsorbHandler(AuraEffectAbsorbDelegate _pEffectHandlerScript, byte _effIndex, bool overKill = false)
: base(_effIndex, overKill ? AuraType.SchoolAbsorbOverkill : AuraType.SchoolAbsorb)
{
pEffectHandlerScript = _pEffectHandlerScript;
}
+4 -8
View File
@@ -615,19 +615,15 @@ namespace Scripts.Spells.Priest
void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount)
{
Unit target = GetTarget();
if (dmgInfo.GetDamage() >= target.GetHealth())
{
target.CastSpell(target, SpellIds.SpiritOfRedemption, new CastSpellExtraArgs(aurEff));
target.SetFullHealth();
return;
}
target.CastSpell(target, SpellIds.SpiritOfRedemption, new CastSpellExtraArgs(aurEff));
target.SetFullHealth();
PreventDefaultAction();
absorbAmount = dmgInfo.GetDamage();
}
public override void Register()
{
OnEffectAbsorb.Add(new EffectAbsorbHandler(HandleAbsorb, 0));
OnEffectAbsorb.Add(new EffectAbsorbHandler(HandleAbsorb, 0, true));
}
}