Core/Auras: Implemented SPELL_AURA_SCHOOL_ABSORB_OVERKILL
Port From (https://github.com/TrinityCore/TrinityCore/commit/530631e0a73c0bcd540f063cef975ecd827307b2)
This commit is contained in:
@@ -1125,15 +1125,68 @@ namespace Game.Entities
|
|||||||
victim.ToCreature().LowerPlayerDamageReq(health < damage ? health : damage);
|
victim.ToCreature().LowerPlayerDamageReq(health < damage ? health : damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool killed = false;
|
||||||
|
bool skipSettingDeathState = false;
|
||||||
|
|
||||||
if (health <= damage)
|
if (health <= damage)
|
||||||
{
|
{
|
||||||
|
killed = true;
|
||||||
|
|
||||||
Log.outDebug(LogFilter.Unit, "DealDamage: victim just died");
|
Log.outDebug(LogFilter.Unit, "DealDamage: victim just died");
|
||||||
|
|
||||||
if (victim.IsTypeId(TypeId.Player) && victim != this)
|
if (victim.IsTypeId(TypeId.Player) && victim != this)
|
||||||
victim.ToPlayer().UpdateCriteria(CriteriaTypes.TotalDamageReceived, health);
|
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
|
else
|
||||||
{
|
{
|
||||||
Log.outDebug(LogFilter.Unit, "DealDamageAlive");
|
Log.outDebug(LogFilter.Unit, "DealDamageAlive");
|
||||||
@@ -1484,7 +1537,7 @@ namespace Game.Entities
|
|||||||
Cell.VisitWorldObjects(this, notifier, GetVisibilityRange());
|
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)
|
// Prevent killing unit twice (and giving reward from kill twice)
|
||||||
if (victim.GetHealth() == 0)
|
if (victim.GetHealth() == 0)
|
||||||
@@ -1599,8 +1652,11 @@ namespace Game.Entities
|
|||||||
if (player != null)
|
if (player != null)
|
||||||
player.UpdateCriteria(CriteriaTypes.GetKillingBlows, 1, 0, 0, victim);
|
player.UpdateCriteria(CriteriaTypes.GetKillingBlows, 1, 0, 0, victim);
|
||||||
|
|
||||||
Log.outDebug(LogFilter.Unit, "SET JUST_DIED");
|
if (!skipSettingDeathState)
|
||||||
victim.SetDeathState(DeathState.JustDied);
|
{
|
||||||
|
Log.outDebug(LogFilter.Unit, "SET JUST_DIED");
|
||||||
|
victim.SetDeathState(DeathState.JustDied);
|
||||||
|
}
|
||||||
|
|
||||||
// Inform pets (if any) when player kills target)
|
// Inform pets (if any) when player kills target)
|
||||||
// MUST come after victim.setDeathState(JUST_DIED); or pet next 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; }
|
public virtual float GetBlockPercent(uint attackerLevel) { return 30.0f; }
|
||||||
|
|
||||||
|
|||||||
@@ -940,8 +940,8 @@ namespace Game.Scripting
|
|||||||
}
|
}
|
||||||
public class EffectAbsorbHandler : EffectBase
|
public class EffectAbsorbHandler : EffectBase
|
||||||
{
|
{
|
||||||
public EffectAbsorbHandler(AuraEffectAbsorbDelegate _pEffectHandlerScript, byte _effIndex)
|
public EffectAbsorbHandler(AuraEffectAbsorbDelegate _pEffectHandlerScript, byte _effIndex, bool overKill = false)
|
||||||
: base(_effIndex, AuraType.SchoolAbsorb)
|
: base(_effIndex, overKill ? AuraType.SchoolAbsorbOverkill : AuraType.SchoolAbsorb)
|
||||||
{
|
{
|
||||||
pEffectHandlerScript = _pEffectHandlerScript;
|
pEffectHandlerScript = _pEffectHandlerScript;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -615,19 +615,15 @@ namespace Scripts.Spells.Priest
|
|||||||
void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount)
|
void HandleAbsorb(AuraEffect aurEff, DamageInfo dmgInfo, ref uint absorbAmount)
|
||||||
{
|
{
|
||||||
Unit target = GetTarget();
|
Unit target = GetTarget();
|
||||||
if (dmgInfo.GetDamage() >= target.GetHealth())
|
target.CastSpell(target, SpellIds.SpiritOfRedemption, new CastSpellExtraArgs(aurEff));
|
||||||
{
|
target.SetFullHealth();
|
||||||
target.CastSpell(target, SpellIds.SpiritOfRedemption, new CastSpellExtraArgs(aurEff));
|
|
||||||
target.SetFullHealth();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PreventDefaultAction();
|
absorbAmount = dmgInfo.GetDamage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Register()
|
public override void Register()
|
||||||
{
|
{
|
||||||
OnEffectAbsorb.Add(new EffectAbsorbHandler(HandleAbsorb, 0));
|
OnEffectAbsorb.Add(new EffectAbsorbHandler(HandleAbsorb, 0, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user