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);
}
}
}