Files
2026-09-18 21:43:22 +08:00

188 lines
5.9 KiB
C#

using System;
using System.Collections.Generic;
using SepCore.Definition;
namespace SepCore.Battle
{
/// <summary>
/// 多维属性修饰器管线(Attribute Pipeline)。
/// 管理角色所有属性维度,提供三段修饰求值、脏标记缓存与按 Source 批量移除机制。
/// 纯 C# 类,无 MonoBehaviour 依赖。
/// </summary>
public sealed class AttributePipeline : IAttributeProvider
{
private readonly Dictionary<StatType, CharacterStat> _stats = new();
/// <summary>
/// 当某个属性的值发生变动(添加/移除修饰器、修改基础值)时触发。
/// 参数:(StatType 属性类型, float 新的当前值)。
/// </summary>
public event Action<StatType, float> OnStatChanged;
public AttributePipeline()
{
// 预初始化已定义的所有 StatType 枚举
Array values = Enum.GetValues(typeof(StatType));
for (int i = 0; i < values.Length; i++)
{
StatType statType = (StatType)values.GetValue(i);
_stats[statType] = new CharacterStat(statType, 0f);
}
}
/// <summary>
/// 获取指定类型的属性容器。
/// </summary>
public CharacterStat Get(StatType statType)
{
if (!_stats.TryGetValue(statType, out CharacterStat stat))
{
stat = new CharacterStat(statType, 0f);
_stats.Add(statType, stat);
}
return stat;
}
/// <summary>
/// 获取指定属性的当前最终计算值(带脏标记缓存与边界钳制)。
/// </summary>
public float GetValue(StatType statType)
{
return Get(statType).Value;
}
/// <summary>
/// 设置指定属性的基础值。
/// </summary>
public void SetBaseValue(StatType statType, float baseValue)
{
CharacterStat stat = Get(statType);
float oldValue = stat.Value;
stat.BaseValue = baseValue;
float newValue = stat.Value;
if (Math.Abs(oldValue - newValue) > 1e-6f)
{
OnStatChanged?.Invoke(statType, newValue);
}
}
/// <summary>
/// 添加属性修饰器。
/// </summary>
public void AddModifier(StatType statType, StatModifier modifier)
{
if (modifier == null)
{
throw new ArgumentNullException(nameof(modifier));
}
CharacterStat stat = Get(statType);
stat.AddModifier(modifier);
OnStatChanged?.Invoke(statType, stat.Value);
}
/// <summary>
/// 移除属性修饰器。
/// </summary>
public bool RemoveModifier(StatType statType, StatModifier modifier)
{
if (modifier == null)
{
return false;
}
CharacterStat stat = Get(statType);
bool removed = stat.RemoveModifier(modifier);
if (removed)
{
OnStatChanged?.Invoke(statType, stat.Value);
}
return removed;
}
/// <summary>
/// 添加 Luban 导出的 modifier(自动转换为 StatModifier)。
/// </summary>
public void AddModifier(StatModifierConfig lubanMod, object source = null)
{
if (lubanMod == null)
{
throw new ArgumentNullException(nameof(lubanMod));
}
StatModifier statMod = StatModifier.FromLuban(lubanMod, source);
AddModifier(lubanMod.StatType, statMod);
}
/// <summary>
/// 移除由 Luban 导出的 modifier 所生成的对应修饰器。
/// </summary>
public bool RemoveModifier(StatModifierConfig lubanMod, object source = null)
{
if (lubanMod == null)
{
return false;
}
CharacterStat stat = Get(lubanMod.StatType);
float targetValue = lubanMod.Value;
ModifierType targetType = lubanMod.ModifierType;
IReadOnlyList<StatModifier> modifiers = stat.Modifiers;
for (int i = modifiers.Count - 1; i >= 0; i--)
{
StatModifier m = modifiers[i];
if (m.Type == targetType &&
Math.Abs(m.Value - targetValue) < 1e-6f &&
(source == null || ReferenceEquals(m.Source, source) || Equals(m.Source, source)))
{
return RemoveModifier(lubanMod.StatType, m);
}
}
return false;
}
/// <summary>
/// 一键移除所有属性中指定来源(道具、武器、羁绊、Buff 等)的所有修饰器。
/// </summary>
/// <param name="source">来源对象引用</param>
/// <returns>移除的修饰器总数</returns>
public int RemoveAllModifiersFromSource(object source)
{
if (source == null)
{
return 0;
}
int totalRemoved = 0;
foreach (KeyValuePair<StatType, CharacterStat> pair in _stats)
{
int removed = pair.Value.RemoveAllModifiersFromSource(source);
if (removed > 0)
{
totalRemoved += removed;
OnStatChanged?.Invoke(pair.Key, pair.Value.Value);
}
}
return totalRemoved;
}
/// <summary>
/// 清空所有属性的修饰器并标记为脏。
/// </summary>
public void Clear()
{
foreach (KeyValuePair<StatType, CharacterStat> pair in _stats)
{
pair.Value.ClearModifiers();
OnStatChanged?.Invoke(pair.Key, pair.Value.Value);
}
}
}
}