Files
zeling_v2/Assets/Scripts/Core/Save/SaveData.cs
2026-05-12 15:34:08 +08:00

262 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BaseGames.Core.Save
{
// ─── 顶层 ─────────────────────────────────────────────────────────────────
[Serializable]
public class SaveData
{
[JsonExtensionData]
public Dictionary<string, JToken> ExtensionData = new();
public SaveMeta Meta = new();
public PlayerSaveData Player = new();
public EquipmentSaveData Equipment = new();
public WorldSaveData World = new();
public MapSaveData Map = new();
public QuestSaveData Quests = new();
public AchievementSaveData Achievements = new();
public ToolsSaveData Tools = new();
public ChallengeRoomsSaveData ChallengeRooms = new();
public EventChainsSaveData EventChains = new();
public ShopsSaveData Shops = new();
public StatsSaveData Stats = new();
public NGPlusSaveData NGPlus = null; // null = 非 NG+ 模式
public TutorialSaveData Tutorial = new();
public SettingsSaveData Settings = new();
public Dictionary<string, JObject> DLC = new();
}
// ─── Meta ─────────────────────────────────────────────────────────────────
[Serializable]
public class SaveMeta
{
public string Version = "2.1";
public int SlotIndex;
public string LastSaved; // ISO 8601
public float Playtime;
public string SavePointId;
public int NGPlusCount;
public int SaveCount;
public string Checksum; // HMAC-SHA256
/// <summary>此存档是否以钢铁之魂(一命)模式开始;加载后 DifficultyManager 会锁定到 SteelSoul。</summary>
public bool IsSteelSoul;
}
// ─── Player ───────────────────────────────────────────────────────────────
[Serializable]
public class PlayerSaveData
{
public float PosX, PosY;
public string Scene;
public int CurrentHP, MaxHP;
public int CurrentGeo, LifetimeGeo;
// 能力解锁位掩码AbilityType [Flags] uint bitmask
public uint AbilityFlags = 0;
public string ActiveFormId;
public List<string> UnlockedFormIds = new();
public DeathShadeSaveData DeathShade;
// 护盾:-1 = 满护盾(默认),>= 0 = 当前耐久值
public int ShieldHP = -1;
public bool ShieldIsBroken = false;
}
[Serializable]
public class DeathShadeSaveData
{
public float PosX, PosY;
public string SceneId;
public int GeoAmount;
}
// ─── Equipment ────────────────────────────────────────────────────────────
[Serializable]
public class EquipmentSaveData
{
public List<string> EquippedCharmIds = new();
public int NotchesUsed;
public int MaxNotches;
public List<string> OwnedCharmIds = new();
public List<string> UpgradedCharmIds = new();
}
// ─── World ────────────────────────────────────────────────────────────────
[Serializable]
public class WorldSaveData
{
public List<string> VisitedScenes = new();
public List<string> ActivatedSavePoints = new();
public List<string> OpenedDoors = new();
public List<string> DefeatedBossIds = new();
public List<string> CollectedIds = new();
public List<string> DestroyedObjectIds = new();
public Dictionary<string, bool> Switches = new();
public Dictionary<string, int> NpcRelations = new();
public HashSet<string> ChallengeFirstClears = new();
}
// ─── Map ──────────────────────────────────────────────────────────────────
[Serializable]
public class MapSaveData
{
public List<string> ExploredRooms = new(); // 踏入过的房间 ID
public List<string> MappedRooms = new(); // 完整地图信息(购买/存档点揭示)
public List<MapPin> Pins = new(); // 玩家自定义地图标记
}
/// <summary>玩家在地图上放置的自定义标记(架构 15_MapShopModule §1.5)。</summary>
[Serializable]
public class MapPin
{
public string RoomId;
public float NormalizedPosX;
public float NormalizedPosY;
public int PinTypeInt; // PinType 枚举整数值,避免 SaveData 依赖 Map 程序集
public string Note; // 玩家备注(最多 64 字符)
}
public enum PinType
{
Marker = 0,
Chest = 1,
Enemy = 2,
Path = 3,
Note = 4,
}
// ─── Quests ───────────────────────────────────────────────────────────────
[Serializable]
public class QuestSaveData
{
public Dictionary<string, QuestState> QuestStates = new();
public List<string> AvailableQuestIds = new();
}
[Serializable]
public class QuestState
{
public string Status; // "NotStarted"|"Active"|"Completed"|"Failed"
public int ObjectiveIndex;
public List<int> ProgressCounts = new();
public string GiverNpcId;
}
// ─── Achievements ─────────────────────────────────────────────────────────
[Serializable]
public class AchievementSaveData
{
public List<string> Unlocked = new();
public Dictionary<string, AchievementProgress> Progress = new();
}
[Serializable]
public class AchievementProgress
{
public int Count;
public float Percent;
}
// ─── Stats ────────────────────────────────────────────────────────────────
[Serializable]
public class StatsSaveData
{
public int EnemyKills, Deaths, ParrySuccess, ParryFail;
public int GeoEarned, GeoLost;
public float DistanceTraveled;
public float SpeedrunTime;
public int SaveCount;
public Dictionary<string, int> SkillUseCounts = new();
public Dictionary<string, int> DeathsByBoss = new();
}
// ─── Tools ────────────────────────────────────────────────────────────────
[Serializable]
public class ToolsSaveData
{
public string ToolSlot0;
public string ToolSlot1;
public List<string> OwnedToolIds = new();
public Dictionary<string, JObject> ToolStates = new();
}
// ─── ChallengeRooms ───────────────────────────────────────────────────────
[Serializable]
public class ChallengeRoomsSaveData
{
public Dictionary<string, ChallengeRoomRecord> Records = new();
}
[Serializable]
public class ChallengeRoomRecord
{
public int BestScore;
public float BestTime;
public string BestRank; // "S"/"A"/"B"/"C"
public int CompletionCount;
}
// ─── EventChains ──────────────────────────────────────────────────────────
[Serializable]
public class EventChainsSaveData
{
public Dictionary<string, string> ChainStates = new();
public Dictionary<string, bool> WorldFlags = new();
}
// ─── Shops ────────────────────────────────────────────────────────────────
[Serializable]
public class ShopsSaveData
{
public Dictionary<string, ShopRecord> ShopRecords = new();
}
[Serializable]
public class ShopRecord
{
public List<string> SoldUniqueItems = new();
public Dictionary<string, int> PurchaseCounts = new();
}
// ─── NGPlus ───────────────────────────────────────────────────────────────
[Serializable]
public class NGPlusSaveData
{
public int NGPlusCount;
public bool SteelSoulMode;
public Dictionary<string, bool> NGPlusFlags = new();
}
// ─── SlotSummary主菜单 UI 用)────────────────────────────────────────────
public class SlotSummary
{
public int SlotIndex;
public float Playtime;
public string LastSaved;
public string SceneName;
public string ActiveFormId;
}
// ─── Tutorial ─────────────────────────────────────────────────────────────
[Serializable]
public class TutorialSaveData
{
/// <summary>已完成(不再弹出)的提示 ID 列表。</summary>
public List<string> CompletedHintIds = new();
}
// ─── Settings ─────────────────────────────────────────────────────────────
[Serializable]
public class SettingsSaveData
{
/// <summary>玩家选择的语言。空字符串 = 使用系统默认。</summary>
public string Language = string.Empty;
}
}