引入属性、伤害管线
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user