引入属性、伤害管线
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SepCore.Definition;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SepCore.Battle
|
||||
{
|
||||
/// <summary>
|
||||
/// 单个属性实例容器。
|
||||
/// 维护基础值、修饰器列表,通过脏标记(Dirty Flag)缓存计算结果,并基于 StatConfig 进行边界钳制。
|
||||
/// </summary>
|
||||
public sealed class CharacterStat
|
||||
{
|
||||
private readonly List<StatModifier> _modifiers = new();
|
||||
private float _baseValue;
|
||||
private bool _isDirty = true;
|
||||
private float _cachedValue;
|
||||
private StatConfig _config;
|
||||
|
||||
public StatType Type { get; }
|
||||
|
||||
public StatConfig Config
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_config == null && GameEntry.Luban != null && GameEntry.Luban.IsReady)
|
||||
{
|
||||
_config = GameEntry.Luban.Get<StatConfig>((int)Type);
|
||||
}
|
||||
|
||||
return _config;
|
||||
}
|
||||
set
|
||||
{
|
||||
_config = value;
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public float BaseValue
|
||||
{
|
||||
get => _baseValue;
|
||||
set
|
||||
{
|
||||
if (Math.Abs(_baseValue - value) > 1e-6f)
|
||||
{
|
||||
_baseValue = value;
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_isDirty)
|
||||
{
|
||||
_cachedValue = CalculateFinalValue();
|
||||
_isDirty = false;
|
||||
}
|
||||
|
||||
return _cachedValue;
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<StatModifier> Modifiers => _modifiers;
|
||||
|
||||
public CharacterStat(StatType type, float baseValue = 0f, StatConfig config = null)
|
||||
{
|
||||
Type = type;
|
||||
_baseValue = baseValue;
|
||||
_config = config;
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
public void AddModifier(StatModifier modifier)
|
||||
{
|
||||
if (modifier == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modifier));
|
||||
}
|
||||
|
||||
_modifiers.Add(modifier);
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
public bool RemoveModifier(StatModifier modifier)
|
||||
{
|
||||
if (modifier == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_modifiers.Remove(modifier))
|
||||
{
|
||||
_isDirty = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int RemoveAllModifiersFromSource(object source)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int removed = _modifiers.RemoveAll(m => ReferenceEquals(m.Source, source) || Equals(m.Source, source));
|
||||
if (removed > 0)
|
||||
{
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
public void ClearModifiers()
|
||||
{
|
||||
if (_modifiers.Count > 0)
|
||||
{
|
||||
_modifiers.Clear();
|
||||
_isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void MarkDirty()
|
||||
{
|
||||
_isDirty = true;
|
||||
}
|
||||
|
||||
private float CalculateFinalValue()
|
||||
{
|
||||
float sumFlat = 0f;
|
||||
float sumPercentAdd = 0f;
|
||||
float prodPercentMult = 1f;
|
||||
|
||||
for (int i = 0; i < _modifiers.Count; i++)
|
||||
{
|
||||
StatModifier mod = _modifiers[i];
|
||||
switch (mod.Type)
|
||||
{
|
||||
case ModifierType.Flat:
|
||||
sumFlat += mod.Value;
|
||||
break;
|
||||
case ModifierType.PercentAdd:
|
||||
sumPercentAdd += mod.Value;
|
||||
break;
|
||||
case ModifierType.PercentMult:
|
||||
prodPercentMult *= mod.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float finalValue = ((_baseValue + sumFlat) * (1f + sumPercentAdd)) * prodPercentMult;
|
||||
return ClampStat(finalValue);
|
||||
}
|
||||
|
||||
private float ClampStat(float value)
|
||||
{
|
||||
StatConfig config = Config;
|
||||
if (config != null)
|
||||
{
|
||||
if (config.HasMin && value < config.MinValue)
|
||||
{
|
||||
value = config.MinValue;
|
||||
}
|
||||
|
||||
if (config.HasMax && value > config.MaxValue)
|
||||
{
|
||||
value = config.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user