using System; using Cielonos.MainGame.Buffs.Character; using Cielonos.MainGame.Characters; using SLSUtilities.General; namespace Cielonos.MainGame.Inventory.Collections { /// /// 时空乱流 / Spacetime Turbulence /// 降低直接攻击伤害,并将被降低的部分转化为 Decay。 /// public class SpacetimeTurbulence : PassiveEquipmentBase { private const string EventKey = nameof(SpacetimeTurbulence); private const string DamageReductionAttribute = "DamageReduction"; private const string DecayMultiplierAttribute = "DecayMultiplier"; // 数值越高越先执行;减伤应处于 onBeforeDamageApplied 的末端。 private const int BeforeDamagePriority = -100; // 让 Decay 在攻击完成后尽早施加,供后续攻击完成事件和受击事件读取。 private const int FinishAttackPriority = 100; public override void OnObtained() { base.OnObtained(); Action onBeforeDamageApplied = OnBeforeDamageApplied; player.eventSm.onBeforeDamageApplied.InsertByPriority( EventKey, onBeforeDamageApplied.ToPrioritized(BeforeDamagePriority)); Action onFinishAttack = OnFinishAttack; player.eventSm.onFinishAttack.InsertByPriority( EventKey, onFinishAttack.ToPrioritized(FinishAttackPriority)); } public override void OnDiscarded() { player.eventSm.onBeforeDamageApplied.Remove(EventKey); player.eventSm.onFinishAttack.Remove(EventKey); base.OnDiscarded(); } private void OnBeforeDamageApplied(AttackAreaBase attackArea, CharacterBase target, Attack.Result result) { if (target is not Enemy) { return; } result.value.damageMultiplier *= (1 - passiveAttributeSm.GetItemAttribute(DamageReductionAttribute)); } private void OnFinishAttack(AttackAreaBase attackArea, CharacterBase target, Attack.Result result) { if (target is not Enemy || result.causedDeath) { return; } float reducedDamage = result.finalDamage + result.shieldBlockedDamage; if (reducedDamage <= 0f) { return; } float damageMultiplier = (1 - passiveAttributeSm.GetItemAttribute(DamageReductionAttribute)); if (damageMultiplier <= 0f) { return; } // 当前直接伤害为原伤害的 damageMultiplier,反推被降低部分后再乘 Decay 系数。 float decayDamage = reducedDamage * (1f - damageMultiplier) / damageMultiplier; decayDamage *= passiveAttributeSm.GetItemAttribute(DecayMultiplierAttribute); if (decayDamage <= 0f) { return; } new Decay(decayDamage).Apply(target, player, this); } } }