多轮审查和修复
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# 09 · 进度模块
|
||||
|
||||
> **命名空间** `BaseGames.Equipment`、`BaseGames.Skills`、`BaseGames.Progression`
|
||||
> **命名空间** `BaseGames.Player`、`BaseGames.Equipment`、`BaseGames.Skills`、`BaseGames.Progression`
|
||||
> **程序集** `BaseGames.Equipment`、`BaseGames.Skills`
|
||||
> **路径** `Assets/Scripts/Equipment/`、`Assets/Scripts/Skills/`
|
||||
> **路径** `Assets/Scripts/Player/`、`Assets/Scripts/World/`、`Assets/Scripts/Equipment/`、`Assets/Scripts/Skills/`
|
||||
> **依赖** `BaseGames.Core.Events`、`BaseGames.Combat`、`BaseGames.Player`
|
||||
|
||||
---
|
||||
@@ -33,6 +33,7 @@
|
||||
> - 原 `Dictionary<string, bool>` 存档方案每次查询需 `.ToString()` 装箱 + 字典哈希,在 AbilityGate.Start() 及 ParrySystem.TryActivateParry() 等热路径产生不必要开销
|
||||
> - 改为 bitmask 后:存档只存一个 `uint`,查询为单次位运算 `(_flags & ability) != 0`,兼容序列化
|
||||
> - **新增能力只需追加新的 `1 << N`,禁止修改已有枚举值**(防止存档数据错位)
|
||||
> - 本节以当前仓库中的 `Assets/Scripts/Player/AbilityType.cs` 为准;历史文档中的旧命名不再作为当前实现事实来源
|
||||
|
||||
```csharp
|
||||
// 路径: Assets/Scripts/Player/AbilityType.cs
|
||||
@@ -40,36 +41,41 @@
|
||||
[System.Flags]
|
||||
public enum AbilityType : uint
|
||||
{
|
||||
None = 0,
|
||||
None = 0,
|
||||
|
||||
// 移动
|
||||
WallCling = 1u << 0,
|
||||
WallJump = 1u << 1,
|
||||
Dash = 1u << 2,
|
||||
AerialDash = 1u << 3, // 空中冲刺(默认锁定,升级后解锁)
|
||||
InvincibleDash= 1u << 4, // 冲刺全程无敌(Dash 的升级版,默认锁定)
|
||||
DoubleJump = 1u << 5,
|
||||
ClimbVines = 1u << 6,
|
||||
Swim = 1u << 7, // 游泳(LiquidZone 内切换 SwimState)
|
||||
// 移动能力
|
||||
WallCling = 1u << 0, // 贴墙悬挂
|
||||
WallJump = 1u << 1, // 墙跳
|
||||
Dash = 1u << 2, // 地面冲刺
|
||||
AirDash = 1u << 3, // 空中冲刺(二段冲刺)
|
||||
DoubleJump = 1u << 4, // 二段跳
|
||||
SuperJump = 1u << 5, // 超级跳(聚气跳)
|
||||
Swim = 1u << 6, // 游泳(液体中自由移动)
|
||||
Dive = 1u << 7, // 下劈(空中下突)
|
||||
|
||||
// 战斗
|
||||
Parry = 1u << 8,
|
||||
Spring = 1u << 9, // 灵泉反弹
|
||||
UseTools = 1u << 10,
|
||||
// 法术能力
|
||||
Spell1 = 1u << 8, // 法术槽 1(策划自定义)
|
||||
Spell2 = 1u << 9, // 法术槽 2
|
||||
Spell3 = 1u << 10, // 法术槽 3
|
||||
|
||||
// 互动
|
||||
ReadShrine = 1u << 11,
|
||||
UseGrapple = 1u << 12,
|
||||
// 灵魄形态
|
||||
SpiritForm = 1u << 11, // 灵魄形态切换
|
||||
SpiritDash = 1u << 12, // 灵魄冲刺(穿透地形)
|
||||
|
||||
// 预留扩展位(13~31):新能力在此追加,禁止复用已有值
|
||||
// 战斗能力
|
||||
Parry = 1u << 13, // 格挡/弹反
|
||||
ChargeAttack = 1u << 14, // 蓄力攻击
|
||||
DownSlash = 1u << 15, // 下斩
|
||||
|
||||
// 互动能力
|
||||
Interact = 1u << 16, // 互动(NPC/机关)
|
||||
FastTravel = 1u << 17, // 快速旅行解锁
|
||||
|
||||
// 组合掩码
|
||||
AllMovement = WallCling | WallJump | Dash | AirDash | DoubleJump | SuperJump | Swim | Dive,
|
||||
AllSpells = Spell1 | Spell2 | Spell3,
|
||||
AllSpirit = SpiritForm | SpiritDash,
|
||||
}
|
||||
|
||||
// ── SaveMigrator 兼容说明 ─────────────────────────────────────────────────
|
||||
// SaveMeta.Version < "2.1" 的存档仍持有 Dictionary<string, bool> Abilities
|
||||
// SaveMigrator.MigrateV2ToV21 负责将其转换为 AbilityFlags uint:
|
||||
// foreach (var kv in old.Abilities)
|
||||
// if (kv.Value && Enum.TryParse<AbilityType>(kv.Key, out var a))
|
||||
// newFlags |= (uint)a;
|
||||
```
|
||||
|
||||
---
|
||||
@@ -418,10 +424,11 @@ public class WeaponOverrideEffect : ICharmEffect
|
||||
|
||||
```csharp
|
||||
// 路径: Assets/Scripts/Equipment/EquipmentManager.cs
|
||||
public class EquipmentManager : MonoBehaviour
|
||||
public class EquipmentManager : MonoBehaviour, ISaveable
|
||||
{
|
||||
[Header("配置")]
|
||||
[SerializeField] private EquipmentConfigSO _config; // 初始 Notch 数量等
|
||||
[SerializeField] private EquipmentConfigSO _config; // 初始 Notch 数量等
|
||||
[SerializeField] private CharmCatalogSO _charmCatalog; // CharmSO 查找表(Assets/Data/Equipment/CharmCatalog.asset)
|
||||
|
||||
[Header("Event Channels")]
|
||||
[SerializeField] private CharmEventChannelSO _onCharmEquipped;
|
||||
@@ -475,13 +482,38 @@ public class EquipmentManager : MonoBehaviour
|
||||
_onEquipmentChanged.Raise();
|
||||
}
|
||||
|
||||
public void AddToCollection(string charmId); // 加入收藏(存档)
|
||||
public void AddToCollection(string charmId)
|
||||
{
|
||||
// 通过 _charmCatalog.Find(charmId) 查找 CharmSO,去重后加入 _collected
|
||||
if (_charmCatalog == null) return;
|
||||
var charm = _charmCatalog.Find(charmId);
|
||||
if (charm != null && !_collected.Contains(charm)) _collected.Add(charm);
|
||||
}
|
||||
|
||||
public void IncreaseNotches(int amount) => _currentNotchCapacity += amount;
|
||||
|
||||
// 存档集成
|
||||
public EquipmentSaveData GetSaveData();
|
||||
public void LoadSaveData(EquipmentSaveData data);
|
||||
// 存档集成(ISaveable)
|
||||
public void OnSave(SaveData data)
|
||||
{
|
||||
data.Equipment.EquippedCharmIds = _equipped.Select(c => c.charmId).ToArray();
|
||||
data.Equipment.OwnedCharmIds = _collected.Select(c => c.charmId).ToArray();
|
||||
data.Equipment.NotchesUsed = UsedNotches;
|
||||
}
|
||||
public void OnLoad(SaveData data)
|
||||
{
|
||||
// 清除当前装备,恢复 _collected,再装备 _equipped
|
||||
foreach (var c in _equipped.ToList()) UnequipCharm(c);
|
||||
_collected.Clear();
|
||||
if (data.Equipment.OwnedCharmIds != null)
|
||||
foreach (var id in data.Equipment.OwnedCharmIds) AddToCollection(id);
|
||||
if (data.Equipment.EquippedCharmIds != null)
|
||||
foreach (var id in data.Equipment.EquippedCharmIds)
|
||||
{
|
||||
var charm = _charmCatalog?.Find(id);
|
||||
if (charm != null) TryEquipCharm(charm);
|
||||
}
|
||||
_onEquipmentChanged.Raise();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -531,6 +563,7 @@ public class ToolSlotManager : MonoBehaviour, ISaveable
|
||||
|
||||
[SerializeField] private ToolSO[] _slots = new ToolSO[SlotCount];
|
||||
[SerializeField] private int[] _remainingUses = new int[SlotCount]; // -1 = 无限
|
||||
[SerializeField] private ToolCatalogSO _toolCatalog; // ToolSO 查找表(Assets/Data/Equipment/ToolCatalog.asset)
|
||||
[SerializeField] private ToolUsedEventChannelSO _onToolUsed;
|
||||
|
||||
// 当前冷却倒计时(秒)
|
||||
@@ -582,7 +615,13 @@ public class ToolSlotManager : MonoBehaviour, ISaveable
|
||||
data.Tools.ToolSlot0 = _slots[0]?.toolId; // 注:工具数据归属 SaveData.Tools,不在 Equipment
|
||||
data.Tools.ToolSlot1 = _slots[1]?.toolId;
|
||||
}
|
||||
public void OnLoad(SaveData data) { /* 从 data.Tools 恢复 ToolSO 引用 */ }
|
||||
public void OnLoad(SaveData data)
|
||||
{
|
||||
// 重置冷却,通过 _toolCatalog.Find() 恢复两个槽位的 ToolSO 引用
|
||||
for (int i = 0; i < SlotCount; i++) _cooldowns[i] = 0f;
|
||||
EquipTool(0, _toolCatalog?.Find(data.Tools.ToolSlot0));
|
||||
EquipTool(1, _toolCatalog?.Find(data.Tools.ToolSlot1));
|
||||
}
|
||||
}
|
||||
|
||||
// 可选接口:带冷却时间的工具
|
||||
|
||||
Reference in New Issue
Block a user