188 lines
5.9 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|