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