多轮审查和修复
This commit is contained in:
143
Assets/Scripts/Equipment/EquipmentManager.cs
Normal file
143
Assets/Scripts/Equipment/EquipmentManager.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using BaseGames.Core;
|
||||
using BaseGames.Player;
|
||||
using BaseGames.Core.Events;
|
||||
using BaseGames.Core.Save;
|
||||
using BaseGames.Skills;
|
||||
using BaseGames.Feedback;
|
||||
|
||||
namespace BaseGames.Equipment
|
||||
{
|
||||
/// <summary>
|
||||
/// 装备管理器(架构 09_ProgressionModule §6)。
|
||||
/// 挂在 Player 上,管理护符的装备/卸下及 Notch 容量。
|
||||
/// 实现 ISaveable 以持久化装备状态。
|
||||
/// </summary>
|
||||
public class EquipmentManager : MonoBehaviour, ISaveable
|
||||
{
|
||||
[Header("配置")]
|
||||
[SerializeField] private EquipmentConfigSO _config;
|
||||
[SerializeField] private CharmCatalogSO _charmCatalog;
|
||||
|
||||
[Header("Event Channels")]
|
||||
[SerializeField] private CharmEventChannelSO _onCharmEquipped;
|
||||
[SerializeField] private CharmEventChannelSO _onCharmUnequipped;
|
||||
[SerializeField] private VoidEventChannelSO _onEquipmentChanged;
|
||||
|
||||
private readonly List<CharmSO> _equipped = new(4);
|
||||
private readonly List<CharmSO> _collected = new(32);
|
||||
private int _currentNotchCapacity;
|
||||
private int _usedNotches;
|
||||
|
||||
private EquipmentContext _ctx;
|
||||
|
||||
// ── 生命周期 ──────────────────────────────────────────────────────────
|
||||
private void Awake()
|
||||
{
|
||||
_ctx = new EquipmentContext
|
||||
{
|
||||
Stats = GetComponent<PlayerStats>(),
|
||||
Feedback = GetComponent<PlayerFeedback>(),
|
||||
Events = ServiceLocator.GetOrDefault<IEventChannelRegistry>(),
|
||||
SkillMods = GetComponent<SkillModifierRegistry>(),
|
||||
WeaponMgr = GetComponent<WeaponManager>(),
|
||||
};
|
||||
Debug.Assert(_config != null, "[EquipmentManager] _config 未赋值,请在 Inspector 中指定 EquipmentConfigSO。", this);
|
||||
Debug.Assert(_charmCatalog != null, "[EquipmentManager] _charmCatalog 未赋值,请在 Inspector 中指定 CharmCatalogSO。", this);
|
||||
_currentNotchCapacity = _config.initialNotchCount;
|
||||
|
||||
Debug.Assert(_ctx.Stats != null, "[EquipmentManager] 缺少 PlayerStats,护符效果无法修改属性。", this);
|
||||
Debug.Assert(_ctx.Feedback != null, "[EquipmentManager] 缺少 PlayerFeedback,护符效果无法触发反馈。", this);
|
||||
Debug.Assert(_ctx.SkillMods != null, "[EquipmentManager] 缺少 SkillModifierRegistry。", this);
|
||||
}
|
||||
|
||||
// ── 查询属性 ─────────────────────────────────────────────────────────
|
||||
public int UsedNotches => _usedNotches; // 缓存值,避免每次调用 LINQ Sum
|
||||
public int TotalNotches => _currentNotchCapacity;
|
||||
public IReadOnlyList<CharmSO> Equipped => _equipped;
|
||||
public IReadOnlyList<CharmSO> Collected => _collected;
|
||||
|
||||
// ── 装备操作 ─────────────────────────────────────────────────────────
|
||||
/// <summary>
|
||||
/// 装备护符。返回 null 表示成功;返回错误字符串表示失败原因。
|
||||
/// </summary>
|
||||
public string TryEquipCharm(CharmSO charm)
|
||||
{
|
||||
if (charm == null) return "护符不存在";
|
||||
if (_equipped.Contains(charm)) return "已经装备";
|
||||
if (!_collected.Contains(charm)) return "尚未收集此护符";
|
||||
int remaining = _currentNotchCapacity - UsedNotches;
|
||||
if (charm.notchCost > remaining)
|
||||
return $"笔记不足(需要 {charm.notchCost},剩余 {remaining})";
|
||||
|
||||
_equipped.Add(charm);
|
||||
_usedNotches += charm.notchCost;
|
||||
foreach (var fx in charm.effects) fx?.OnEquip(_ctx);
|
||||
_onCharmEquipped?.Raise(charm);
|
||||
_onEquipmentChanged?.Raise();
|
||||
return null;
|
||||
}
|
||||
|
||||
public void UnequipCharm(CharmSO charm)
|
||||
{
|
||||
if (charm == null || !_equipped.Remove(charm)) return;
|
||||
_usedNotches -= charm.notchCost;
|
||||
foreach (var fx in charm.effects) fx?.OnUnequip(_ctx);
|
||||
_onCharmUnequipped?.Raise(charm);
|
||||
_onEquipmentChanged?.Raise();
|
||||
}
|
||||
|
||||
/// <summary>将护符加入收藏(拾取时调用)。</summary>
|
||||
public void AddToCollection(string charmId)
|
||||
{
|
||||
var charm = _charmCatalog.Find(charmId);
|
||||
if (charm == null) { Debug.LogWarning($"[EquipmentManager] 找不到护符: {charmId}"); return; }
|
||||
if (!_collected.Contains(charm))
|
||||
_collected.Add(charm);
|
||||
}
|
||||
|
||||
public void IncreaseNotches(int amount)
|
||||
{
|
||||
_currentNotchCapacity += amount;
|
||||
_onEquipmentChanged?.Raise();
|
||||
}
|
||||
|
||||
// ── ISaveable ────────────────────────────────────────────────────────
|
||||
public void OnSave(SaveData data)
|
||||
{
|
||||
data.Equipment.EquippedCharmIds.Clear();
|
||||
data.Equipment.EquippedCharmIds.AddRange(_equipped.Select(c => c.charmId));
|
||||
data.Equipment.OwnedCharmIds.Clear();
|
||||
data.Equipment.OwnedCharmIds.AddRange(_collected.Select(c => c.charmId));
|
||||
data.Equipment.NotchesUsed = UsedNotches;
|
||||
}
|
||||
|
||||
public void OnLoad(SaveData data)
|
||||
{
|
||||
// 卸下所有当前护符(不触发事件,逆序遍历避免 ToList() GC 分配)
|
||||
for (int i = _equipped.Count - 1; i >= 0; i--)
|
||||
foreach (var fx in _equipped[i].effects) fx?.OnUnequip(_ctx);
|
||||
_equipped.Clear();
|
||||
_usedNotches = 0;
|
||||
|
||||
// 从 CharmCatalog 按 ID 恢复收藏并重新装备
|
||||
_collected.Clear();
|
||||
foreach (var id in data.Equipment.OwnedCharmIds)
|
||||
{
|
||||
var charm = _charmCatalog.Find(id);
|
||||
if (charm != null && !_collected.Contains(charm))
|
||||
_collected.Add(charm);
|
||||
}
|
||||
|
||||
foreach (var id in data.Equipment.EquippedCharmIds)
|
||||
{
|
||||
var charm = _charmCatalog.Find(id);
|
||||
if (charm != null) TryEquipCharm(charm);
|
||||
}
|
||||
|
||||
_onEquipmentChanged?.Raise();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user