Files
Cielonos/Assets/Scripts/MainGame/Items/SupportEquipments/ChaosPact.cs
SoulliesOfficial 39b43680a9 爆更
2026-07-18 03:16:20 -04:00

151 lines
6.3 KiB
C#

using Cielonos.MainGame.Characters;
using Cielonos.MainGame.FunctionalAnimation;
using SLSUtilities.General;
using UnityEngine;
namespace Cielonos.MainGame.Inventory.Collections
{
/// <summary>
/// Aleph 级支援装备:持续重掷 Luck、Curse、最终伤害倍率和敌方强力动作抗性。
/// </summary>
public class ChaosPact : SupportEquipmentBase
{
/// <summary>
/// 混沌契约每次重掷属性和伤害倍率的间隔。
/// </summary>
private const float RefreshInterval = 0.1f;
private const float MinimumDamageMultiplier = 0f;
private const float MaximumDamageMultiplier = 2f;
private const string ResistanceResolverKey = nameof(ChaosPact);
private float _refreshTimer;
private bool _isResistanceResolverRegistered;
public override bool CanUnequip => false;
public override void Initialize()
{
base.Initialize();
if (activeAttributeData != null)
{
activeAttributeSm = new AttributeSubmodule(this, activeAttributeData);
}
}
public override void OnEquipped()
{
base.OnEquipped();
RegisterResistanceResolver();
_refreshTimer = 0f;
RefreshChaosState();
}
public override void OnUnequipped()
{
UnregisterResistanceResolver();
RemoveChaosModifiers();
base.OnUnequipped();
}
protected override void Update()
{
if (!player.inventorySc.equipmentSm.currentSupportEquipments.Contains(this)) return;
base.Update();
_refreshTimer += player.selfTimeSm.DeltaTime;
if (_refreshTimer < RefreshInterval) return;
_refreshTimer %= RefreshInterval;
RefreshChaosState();
}
private void RefreshChaosState()
{
if (activeAttributeSm == null) return;
// 当前版本将 Luck 和 Curse 作为契约的运行时数值来源;未来可替换为正式的属性覆盖层。
activeAttributeSm.charAttrNumericChange[CharacterAttribute.Luck] = Randomizer.Roll01() * 100f;
activeAttributeSm.charAttrNumericChange[CharacterAttribute.Curse] = Randomizer.Roll01() * 100f;
player.attributeSm.RefreshAttribute(CharacterAttribute.Luck);
player.attributeSm.RefreshAttribute(CharacterAttribute.Curse);
float luck = player.attributeSm[CharacterAttribute.Luck];
float curse = player.attributeSm[CharacterAttribute.Curse];
activeAttributeSm.chaAttrPercentageChangeOfMultiplication[CharacterAttribute.FinalDamageDealtMultiplier] =
MapGoodnessToDealtDamageMultiplier(Randomizer.RollLuckCurse01(luck, curse));
activeAttributeSm.chaAttrPercentageChangeOfMultiplication[CharacterAttribute.FinalDamageReceivedMultiplier] =
MapGoodnessToReceivedDamageMultiplier(Randomizer.RollLuckCurse01(luck, curse));
player.attributeSm.RefreshAttribute(CharacterAttribute.FinalDamageDealtMultiplier);
player.attributeSm.RefreshAttribute(CharacterAttribute.FinalDamageReceivedMultiplier);
}
/// <summary>
/// 强力动作开始时按随机结果映射抗性等级。
/// 随机值越高,敌人越容易被较低等级的攻击打断。
/// </summary>
private Breakthrough.Type ResolveBreakthroughableType(Automata enemy, Breakthrough.Type originalType)
{
if (originalType is not (Breakthrough.Type.Heavy or Breakthrough.Type.Disruption or Breakthrough.Type.Forced))
{
return originalType;
}
float goodness = Randomizer.RollLuckCurse01(player.attributeSm[CharacterAttribute.Luck], player.attributeSm[CharacterAttribute.Curse]);
if (goodness >= 2f / 3f) return Breakthrough.Type.Heavy;
if (goodness >= 1f / 3f) return Breakthrough.Type.Disruption;
return Breakthrough.Type.Forced;
}
/// <summary>
/// 对玩家而言,较高的随机好坏值应提升造成伤害。
/// </summary>
private static float MapGoodnessToDealtDamageMultiplier(float goodness)
{
return Mathf.Lerp(MinimumDamageMultiplier, MaximumDamageMultiplier, goodness);
}
/// <summary>
/// 对玩家而言,较高的随机好坏值应降低受到伤害。
/// </summary>
private static float MapGoodnessToReceivedDamageMultiplier(float goodness)
{
return Mathf.Lerp(MaximumDamageMultiplier, MinimumDamageMultiplier, goodness);
}
private void RegisterResistanceResolver()
{
if (_isResistanceResolverRegistered) return;
SetBreakthroughResistance.onResolveBreakthroughableType.InsertByPriority(
ResistanceResolverKey,
new PrioritizedFunc<Automata, Breakthrough.Type, Breakthrough.Type>(ResolveBreakthroughableType));
_isResistanceResolverRegistered = true;
}
private void UnregisterResistanceResolver()
{
if (!_isResistanceResolverRegistered) return;
SetBreakthroughResistance.onResolveBreakthroughableType.Remove(ResistanceResolverKey);
_isResistanceResolverRegistered = false;
}
private void RemoveChaosModifiers()
{
if (activeAttributeSm == null) return;
// 强制卸下或 run 清理时必须还原运行时写入的四项属性。
activeAttributeSm.charAttrNumericChange.Remove(CharacterAttribute.Luck);
activeAttributeSm.charAttrNumericChange.Remove(CharacterAttribute.Curse);
activeAttributeSm.chaAttrPercentageChangeOfMultiplication.Remove(CharacterAttribute.FinalDamageDealtMultiplier);
activeAttributeSm.chaAttrPercentageChangeOfMultiplication.Remove(CharacterAttribute.FinalDamageReceivedMultiplier);
player.attributeSm.RefreshAttribute(CharacterAttribute.Luck);
player.attributeSm.RefreshAttribute(CharacterAttribute.Curse);
player.attributeSm.RefreshAttribute(CharacterAttribute.FinalDamageDealtMultiplier);
player.attributeSm.RefreshAttribute(CharacterAttribute.FinalDamageReceivedMultiplier);
}
}
}