152 lines
5.6 KiB
C#
152 lines
5.6 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace Cielonos.MainGame.Characters
|
||
{
|
||
public partial class AttributeSubmodule : SubmoduleBase<CharacterBase>
|
||
{
|
||
public AttributeGroup attributeGroup;
|
||
|
||
/// <summary>
|
||
/// 属性值变更回调表。Key 为属性名,Value 为回调委托 (oldValue, newValue)。
|
||
/// 当属性值通过 indexer 或 RefreshAttribute 发生实际变化时自动触发。
|
||
/// </summary>
|
||
private readonly Dictionary<string, Action<float, float>> _onValueChanged = new();
|
||
|
||
/// <summary>
|
||
/// 当为 true 时,暂时不触发属性变更回调。
|
||
/// 用于批量修改属性时避免中间状态触发回调。
|
||
/// </summary>
|
||
private bool _suppressCallbacks;
|
||
|
||
public bool Has(string attributeName) => attributeGroup.current.ContainsKey(attributeName);
|
||
public float Get(string attributeName, float defaultValue) => attributeGroup.current.GetValueOrDefault(attributeName, defaultValue);
|
||
|
||
public float this[string attributeName]
|
||
{
|
||
get => attributeGroup.current.GetValueOrDefault(attributeName, attributeName.Contains("Multiplier") ? 1 : 0);
|
||
set
|
||
{
|
||
float oldValue = attributeGroup.current.GetValueOrDefault(attributeName, 0f);
|
||
attributeGroup.current[attributeName] = value;
|
||
|
||
if (!_suppressCallbacks && Math.Abs(oldValue - value) > float.Epsilon)
|
||
{
|
||
NotifyValueChanged(attributeName, oldValue, value);
|
||
}
|
||
}
|
||
}
|
||
|
||
public AttributeSubmodule(CharacterBase character) : base(character)
|
||
{
|
||
Initialize(character.attributeData);
|
||
}
|
||
|
||
public AttributeSubmodule(CharacterBase character, AttributeData attributeData) : base(character)
|
||
{
|
||
Initialize(attributeData);
|
||
}
|
||
|
||
private void Initialize(AttributeData attributeData)
|
||
{
|
||
attributeGroup = new AttributeGroup(attributeData.originalAttributes);
|
||
attributeGroup.SetUpEndowments(attributeData.runtimeAttributes);
|
||
}
|
||
|
||
public void RefreshAttribute(string attributeName)
|
||
{
|
||
float oldValue = attributeGroup.current.GetValueOrDefault(attributeName, 0f);
|
||
|
||
attributeGroup.ResetAttribute(attributeName);
|
||
|
||
float numeric = 0;
|
||
float pAccumulation = 0;
|
||
float pMultiplication = 1;
|
||
|
||
if (owner is Player player)
|
||
{
|
||
player.inventorySc.ApplyAttributeChange(attributeName, ref numeric, ref pAccumulation, ref pMultiplication);
|
||
}
|
||
|
||
owner.buffSm.ApplyAttributeChange(attributeName, ref numeric, ref pAccumulation, ref pMultiplication);
|
||
attributeGroup.ModifyAttribute(attributeName, numeric, pAccumulation, pMultiplication);
|
||
|
||
float newValue = attributeGroup.current.GetValueOrDefault(attributeName, 0f);
|
||
if (!_suppressCallbacks && Math.Abs(oldValue - newValue) > float.Epsilon)
|
||
{
|
||
NotifyValueChanged(attributeName, oldValue, newValue);
|
||
}
|
||
}
|
||
|
||
public void RefreshAllAttributes()
|
||
{
|
||
foreach (var attributeName in attributeGroup.original.Keys)
|
||
{
|
||
RefreshAttribute(attributeName);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 属性变更回调注册与触发
|
||
/// </summary>
|
||
public partial class AttributeSubmodule
|
||
{
|
||
/// <summary>
|
||
/// 为指定属性注册一个值变更回调。多次注册同一属性会追加委托。
|
||
/// </summary>
|
||
/// <param name="attributeName">属性名(使用 CharacterAttribute 常量)</param>
|
||
/// <param name="callback">回调委托,参数为 (oldValue, newValue)</param>
|
||
public void RegisterValueChangedCallback(string attributeName, Action<float, float> callback)
|
||
{
|
||
if (_onValueChanged.TryGetValue(attributeName, out var existing))
|
||
{
|
||
_onValueChanged[attributeName] = existing + callback;
|
||
}
|
||
else
|
||
{
|
||
_onValueChanged[attributeName] = callback;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 为指定属性注销一个值变更回调。
|
||
/// </summary>
|
||
public void UnregisterValueChangedCallback(string attributeName, Action<float, float> callback)
|
||
{
|
||
if (_onValueChanged.TryGetValue(attributeName, out var existing))
|
||
{
|
||
var updated = existing - callback;
|
||
if (updated == null)
|
||
{
|
||
_onValueChanged.Remove(attributeName);
|
||
}
|
||
else
|
||
{
|
||
_onValueChanged[attributeName] = updated;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 暂时挂起所有属性变更回调。调用 ResumeCallbacks 恢复。
|
||
/// 适用于批量初始化等不需要触发 UI 更新的场景。
|
||
/// </summary>
|
||
public void SuppressCallbacks() => _suppressCallbacks = true;
|
||
|
||
/// <summary>
|
||
/// 恢复属性变更回调触发。
|
||
/// </summary>
|
||
public void ResumeCallbacks() => _suppressCallbacks = false;
|
||
|
||
private void NotifyValueChanged(string attributeName, float oldValue, float newValue)
|
||
{
|
||
if (_onValueChanged.TryGetValue(attributeName, out var callback))
|
||
{
|
||
callback.Invoke(oldValue, newValue);
|
||
}
|
||
}
|
||
}
|
||
}
|