84 lines
3.1 KiB
C#
84 lines
3.1 KiB
C#
using System;
|
||
using Cielonos.MainGame.Buffs.Character;
|
||
using Cielonos.MainGame.Characters;
|
||
using SLSUtilities.General;
|
||
|
||
namespace Cielonos.MainGame.Inventory.Collections
|
||
{
|
||
/// <summary>
|
||
/// 时空乱流 / Spacetime Turbulence
|
||
/// 降低直接攻击伤害,并将被降低的部分转化为 Decay。
|
||
/// </summary>
|
||
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<AttackAreaBase, CharacterBase, Attack.Result> onBeforeDamageApplied = OnBeforeDamageApplied;
|
||
player.eventSm.onBeforeDamageApplied.InsertByPriority(
|
||
EventKey, onBeforeDamageApplied.ToPrioritized(BeforeDamagePriority));
|
||
|
||
Action<AttackAreaBase, CharacterBase, Attack.Result> 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);
|
||
}
|
||
}
|
||
}
|