114 lines
5.1 KiB
C#
114 lines
5.1 KiB
C#
using UnityEngine;
|
||
using BaseGames.Core;
|
||
using BaseGames.Core.Events;
|
||
using BaseGames.Core.Save;
|
||
using BaseGames.Player.States;
|
||
|
||
namespace BaseGames.Equipment
|
||
{
|
||
/// <summary>
|
||
/// 工具槽管理器(架构 09_ProgressionModule §7.5)。
|
||
/// 管理玩家的 2 个工具槽(装备、使用、冷却)。
|
||
/// 实现 ISaveable 以持久化槽位状态。
|
||
/// </summary>
|
||
public class ToolSlotManager : MonoBehaviour, ISaveable, IToolSlotService
|
||
{
|
||
private const int SlotCount = 2;
|
||
|
||
[SerializeField] private ToolCatalogSO _toolCatalog;
|
||
[SerializeField] private ToolSO[] _slots = new ToolSO[SlotCount];
|
||
[SerializeField] private int[] _remainingUses = new int[SlotCount]; // -1 = 无限
|
||
[SerializeField] private ToolUsedEventChannelSO _onToolUsed;
|
||
|
||
private readonly float[] _cooldowns = new float[SlotCount];
|
||
|
||
private void Awake()
|
||
{
|
||
Debug.Assert(_toolCatalog != null, "[ToolSlotManager] _toolCatalog 未赋值,请在 Inspector 中指定 ToolCatalogSO。", this);
|
||
}
|
||
|
||
private void OnEnable()
|
||
{
|
||
ServiceLocator.GetOrDefault<ISaveableRegistry>()?.Register(this);
|
||
ServiceLocator.Register<IToolSlotService>(this);
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
ServiceLocator.GetOrDefault<ISaveableRegistry>()?.Unregister(this);
|
||
ServiceLocator.Unregister<IToolSlotService>(this);
|
||
}
|
||
|
||
// ── 装备 ─────────────────────────────────────────────────────────────
|
||
public void EquipTool(int slotIndex, ToolSO tool)
|
||
{
|
||
if (slotIndex < 0 || slotIndex >= SlotCount) return;
|
||
_slots[slotIndex] = tool;
|
||
_remainingUses[slotIndex] = tool != null ? tool.maxUses : 0;
|
||
_cooldowns[slotIndex] = 0f;
|
||
}
|
||
|
||
// ── 使用 ─────────────────────────────────────────────────────────────
|
||
public bool TryUseTool(int slotIndex, PlayerController player)
|
||
{
|
||
if (slotIndex < 0 || slotIndex >= SlotCount) return false;
|
||
var tool = _slots[slotIndex];
|
||
if (tool == null) return false;
|
||
if (_cooldowns[slotIndex] > 0f) return false;
|
||
if (_remainingUses[slotIndex] == 0) return false; // 已耗尽(-1 = 无限不触发)
|
||
|
||
tool.effect?.Use(player);
|
||
|
||
if (_remainingUses[slotIndex] > 0) _remainingUses[slotIndex]--;
|
||
_cooldowns[slotIndex] = tool is IToolCooldown tc ? tc.CooldownDuration : 0f;
|
||
|
||
_onToolUsed?.Raise(new ToolUsedPayload
|
||
{
|
||
SlotIndex = slotIndex,
|
||
ToolId = tool.toolId
|
||
});
|
||
return true;
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
for (int i = 0; i < SlotCount; i++)
|
||
if (_cooldowns[i] > 0f) _cooldowns[i] -= Time.deltaTime;
|
||
}
|
||
|
||
// ── 查询 ─────────────────────────────────────────────────────────────
|
||
public ToolSO GetTool(int slotIndex) => _slots[slotIndex];
|
||
public int GetRemainingUses(int slotIndex) => _remainingUses[slotIndex];
|
||
public float GetCooldownRatio(int slotIndex)
|
||
{
|
||
if (_slots[slotIndex] is IToolCooldown tc && tc.CooldownDuration > 0f)
|
||
return _cooldowns[slotIndex] / tc.CooldownDuration;
|
||
return 0f;
|
||
}
|
||
|
||
// ── ISaveable ────────────────────────────────────────────────────────
|
||
public void OnSave(SaveData data)
|
||
{
|
||
data.Tools.ToolSlot0 = _slots[0]?.toolId;
|
||
data.Tools.ToolSlot1 = _slots[1]?.toolId;
|
||
// 持久化剩余使用次数(-1 = 无限,保持原值)
|
||
data.Tools.ToolStates["Slot0_Uses"] = Newtonsoft.Json.Linq.JObject.FromObject(new { uses = _remainingUses[0] });
|
||
data.Tools.ToolStates["Slot1_Uses"] = Newtonsoft.Json.Linq.JObject.FromObject(new { uses = _remainingUses[1] });
|
||
}
|
||
|
||
public void OnLoad(SaveData data)
|
||
{
|
||
_cooldowns[0] = _cooldowns[1] = 0f;
|
||
|
||
EquipTool(0, _toolCatalog.Find(data.Tools.ToolSlot0));
|
||
EquipTool(1, _toolCatalog.Find(data.Tools.ToolSlot1));
|
||
|
||
// 恢复剩余使用次数(EquipTool 会重置为 maxUses,此处覆盖还原)
|
||
if (data.Tools.ToolStates.TryGetValue("Slot0_Uses", out var uses0))
|
||
_remainingUses[0] = (int?)uses0["uses"] ?? _remainingUses[0];
|
||
if (data.Tools.ToolStates.TryGetValue("Slot1_Uses", out var uses1))
|
||
_remainingUses[1] = (int?)uses1["uses"] ?? _remainingUses[1];
|
||
}
|
||
}
|
||
}
|