Files
Cielonos/Assets/Scripts/MainGame/Managers/CombatManager/CombatSystems/PassionSystem/PassionSystem.cs
SoulliesOfficial a024305799 我说次元斩
2026-06-13 18:43:40 -04:00

376 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using Cielonos.MainGame.Characters;
using Sirenix.OdinInspector;
using SLSUtilities.General;
using UnityEngine;
using UnityEngine.Serialization;
namespace Cielonos.MainGame
{
/// <summary>
/// 激情系统(战斗评分/战斗引擎)
/// 管理玩家的定性与定量战斗状态。
/// 采用逐级递进机制,每个等级具有独立的 0-100% 进度。
/// </summary>
public partial class PassionSystem : CombatSystemBase
{
// ==========================================
// 配置与设置 / Settings & Configurations
// ==========================================
[TitleGroup("衰减设置")]
[Tooltip("每秒基础衰减率(占当前等级总进度的百分比)。")]
[SerializeField] private float baseDecayRate = 5f;
// ==========================================
// 运行时状态 / Runtime State
// ==========================================
[TitleGroup("运行时状态")]
[ReadOnly] [ShowInInspector] public int levelIndex;
[ReadOnly] [ShowInInspector] public float percent;
[ReadOnly] [ShowInInspector] private float _timeSinceLastAction;
[TitleGroup("等级配置")]
public List<PassionLevel> passionLevels;
// ==========================================
// 事件 / Events
// ==========================================
/// <summary>
/// 当激情等级段位发生改变时触发。参数1旧等级索引参数2新等级索引。
/// </summary>
public event Action<int, int> OnLevelChanged;
/// <summary>
/// 当当前等级的百分比进度发生改变时触发。
/// </summary>
public event Action<float> OnPercentChanged;
/// <summary>
/// 当激情值增加时触发。参数1实际增加值参数2是否应用了乘数通常代表主动或技术行为加成
/// </summary>
public event Action<float, bool> OnPassionIncreased;
/// <summary>
/// 当激情值减少时触发。参数1实际减少值参数2是否应用了受击乘数通常代表受击等负面反应降低
/// </summary>
public event Action<float, bool> OnPassionDecreased;
// ==========================================
// 属性 / Properties
// ==========================================
public int LevelIndex => levelIndex;
public float Percent => percent;
public float TimeSinceLastAction => _timeSinceLastAction;
public PassionLevel.Type CurrentLevelType => passionLevels[levelIndex].levelType;
// ==========================================
// 生命周期 / Lifecycle
// ==========================================
private void Awake()
{
InitializeRankInfos();
}
private void Start()
{
PlayerEventSubmodule eventSm = MainGameManager.Player.eventSm;
eventSm.onFinishAttack.TryAdd("PassionSystem",
new PrioritizedAction<AttackAreaBase, CharacterBase, Attack.Result>(
(attacker, target, result) => OnAttackHit(result.value.breakthroughType)
)
);
eventSm.onPerfectBlockSuccess.TryAdd("PassionSystem",
new PrioritizedAction<AttackAreaBase, BlockSource>(
(attacker, source) => OnPerfectBlock()
)
);
eventSm.onPerfectDodgeSuccess.TryAdd("PassionSystem",
new PrioritizedAction<AttackAreaBase, DodgeSource>(
(attacker, source) => OnPerfectDodge()
)
);
eventSm.onAfterGetAttacked.TryAdd("PassionSystem",
new PrioritizedAction<AttackAreaBase, Attack.Result>(
(attacker, result) => OnGetHit(result.value.breakthroughType)
)
);
}
private void Update()
{
var player = MainGameManager.Player;
if (player == null || player.selfTimeSm == null) return;
float playerLocalDt = player.selfTimeSm.DeltaTime;
_timeSinceLastAction += playerLocalDt;
// 如果无动作时间超过延迟设定,则触发自然衰减
float keepDuration = player.attributeSm[CharacterAttribute.PassionKeepDuration];
if (_timeSinceLastAction >= keepDuration)
{
float amplifier = player.attributeSm[CharacterAttribute.PassionTimeDecreaseAmplifier];
float decayRate = baseDecayRate * passionLevels[levelIndex].timeDecreaseMultiplier * (1 + amplifier);
// 时间引起的自然衰减:直接传入计算时间乘数后的值,并忽略受击等其他乘数,标记 isTimeDecay 为 true
DecreasePassion(decayRate * playerLocalDt, false, isTimeDecay: true);
}
}
}
public partial class PassionSystem
{
[Serializable]
public struct PassionLevel
{
public enum Type
{
C = 0,
B = 1,
A = 2,
S = 3,
SS = 4,
SSS = 5
}
public Type levelType;
public Color levelColor; // 该等级的 UI 显示颜色
public float increaseMultiplier; // 激情值获取乘数
[FormerlySerializedAs("decayMultiplier")]
public float timeDecreaseMultiplier; // 随时间自然衰减的乘数
public float reactiveDecreaseMultiplier; // 受击时瞬间衰减的乘数
public PassionLevel(Type levelType, Color levelColor, float increaseMultiplier, float timeDecreaseMultiplier, float reactiveDecreaseMultiplier)
{
this.levelType = levelType;
this.levelColor = levelColor;
this.increaseMultiplier = increaseMultiplier;
this.timeDecreaseMultiplier = timeDecreaseMultiplier;
this.reactiveDecreaseMultiplier = reactiveDecreaseMultiplier;
}
}
[Button("初始化段位配置")]
private void InitializeRankInfos()
{
if (passionLevels == null || passionLevels.Count == 0)
{
passionLevels = new List<PassionLevel>
{
new PassionLevel(PassionLevel.Type.C, new Color(0f, 0.8f, 1f, 1f), 1f, 1f, 1f),
new PassionLevel(PassionLevel.Type.B, new Color(0.2f, 0.6f, 1f, 1f), 0.95f, 1f, 1.25f),
new PassionLevel(PassionLevel.Type.A, new Color(0.4f, 0.4f, 1f, 1f), 0.9f, 1f, 1.5f),
new PassionLevel(PassionLevel.Type.S, new Color(0.8f, 0.2f, 0.8f, 1f), 0.85f, 1.5f, 2f),
new PassionLevel(PassionLevel.Type.SS, new Color(0.9f, 0.2f, 0.4f, 1f), 0.8f, 1.5f, 3f),
new PassionLevel(PassionLevel.Type.SSS, new Color(1f, 0f, 0f, 1f), 0.8f, 1.5f, 4f),
};
}
}
}
public partial class PassionSystem
{
// ==========================================
// 公共 API / Public API
// ==========================================
/// <summary>
/// 重置衰减计时器,延迟自然衰减的触发。
/// </summary>
public void ResetDecayTimer()
{
_timeSinceLastAction = 0f;
}
/// <summary>
/// 当攻击命中敌人时触发根据打断等级Breakthrough.Type增加激情值。
/// </summary>
/// <param name="breakthroughType">攻击的打断级别</param>
public void OnAttackHit(Breakthrough.Type breakthroughType)
{
float baseAmount = breakthroughType switch
{
Breakthrough.Type.None => 0f,
Breakthrough.Type.Weak => 1f,
Breakthrough.Type.Medium => 2f,
Breakthrough.Type.Heavy => 4f,
Breakthrough.Type.Disruption => 4f,
Breakthrough.Type.Forced => 4f,
_ => 0f
};
IncreasePassion(baseAmount);
}
/// <summary>
/// 触发完美格挡时增加激情值。
/// </summary>
public void OnPerfectBlock()
{
IncreasePassion(20f);
}
/// <summary>
/// 触发完美闪避时增加激情值。
/// </summary>
public void OnPerfectDodge()
{
IncreasePassion(20f);
}
/// <summary>
/// 当主角受到伤害时触发根据敌人的攻击打断等级Breakthrough.Type降低激情值。
/// </summary>
/// <param name="breakthroughType">敌人攻击的打断级别</param>
public void OnGetHit(Breakthrough.Type breakthroughType)
{
float baseAmount = breakthroughType switch
{
Breakthrough.Type.None => 0f,
Breakthrough.Type.Weak => 1f,
Breakthrough.Type.Medium => 5f,
Breakthrough.Type.Heavy => 10f,
Breakthrough.Type.Disruption => 10f,
Breakthrough.Type.Forced => 10f,
_ => 1f
};
DecreasePassion(baseAmount);
}
/// <summary>
/// 增加激情值。自动处理等级提升与溢出(当百分比超过 100% 时自动进入下一等级)。
/// </summary>
/// <param name="amount">基础增加百分比量0-100 范围)。</param>
/// <param name="applyMultipliers">是否应用当前等级的获取乘数。</param>
public void IncreasePassion(float amount, bool applyMultipliers = true)
{
if (amount <= 0f) return;
// 重置衰减计时器以推迟自然衰减
ResetDecayTimer();
float finalAmount = amount;
if (applyMultipliers)
{
var player = MainGameManager.Player;
float amplifier = player.attributeSm[CharacterAttribute.PassionIncreaseAmplifier];
finalAmount *= passionLevels[levelIndex].increaseMultiplier * (1 + amplifier);
}
percent += finalAmount;
OnPassionIncreased?.Invoke(finalAmount, applyMultipliers);
int oldLevel = levelIndex;
while (percent >= 100f)
{
if (levelIndex >= passionLevels.Count - 1)
{
percent = 100f; // 钳制在最大等级SSS
break;
}
else
{
percent -= 100f;
levelIndex++;
}
}
if (oldLevel != levelIndex)
{
OnLevelChanged?.Invoke(oldLevel, levelIndex);
}
OnPercentChanged?.Invoke(percent);
}
/// <summary>
/// 减少激情值。自动处理等级降低与退级(当百分比低于 0% 时自动退回上一等级)。
/// </summary>
/// <param name="amount">基础减少百分比量0-100 范围)。</param>
/// <param name="applyMultipliers">是否应用当前等级的受击衰减乘数。</param>
/// <param name="isTimeDecay">是否为时间引起的自然衰减(如果为 true当跌至 0% 时会短暂保留等级而非直接退级)</param>
public void DecreasePassion(float amount, bool applyMultipliers = true, bool isTimeDecay = false)
{
if (amount <= 0f) return;
float finalAmount = amount;
if (applyMultipliers)
{
var player = MainGameManager.Player;
float amplifier = player.attributeSm[CharacterAttribute.PassionReactiveDecreaseAmplifier];
finalAmount *= passionLevels[levelIndex].reactiveDecreaseMultiplier * (1 + amplifier);
}
// 如果是时间自然衰减,且当前等级进度会从大于 0% 跌至 0% 以下:
// 我们将其钳制在 0% 并重置衰减计时器(暂停衰减一段时间),而不是立即降低等级。
// 注意当percent正好等于0时不会进入这个条件分支于是PassionLevel会正常退级。
// 这样设计是为了让玩家在自然衰减时有一个短暂的缓冲区,而不是直接退级,增加游戏的容错性和玩家体验。
if (isTimeDecay)
{
if (percent > 0f && percent - finalAmount <= 0f)
{
percent = 0f;
ResetDecayTimer();
OnPassionDecreased?.Invoke(finalAmount, applyMultipliers);
OnPercentChanged?.Invoke(percent);
return;
}
}
percent -= finalAmount;
OnPassionDecreased?.Invoke(finalAmount, applyMultipliers);
int oldLevel = levelIndex;
while (percent < 0f)
{
if (levelIndex <= 0)
{
percent = 0f; // 钳制在最低等级C
break;
}
else
{
percent += 100f;
levelIndex--;
}
}
if (oldLevel != levelIndex)
{
OnLevelChanged?.Invoke(oldLevel, levelIndex);
}
OnPercentChanged?.Invoke(percent);
}
}
#if UNITY_EDITOR
public partial class PassionSystem
{
// ==========================================
// 调试工具 / Debug Tools
// ==========================================
[Button("Debug: 增加激情值 100%")]
public void IncreasePassion()
{
IncreasePassion(100f, false);
}
[Button("Debug: 减少激情值 100%")]
public void DecreasePassion()
{
DecreasePassion(100f, false);
}
}
#endif
}