using System; using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace BaseGames.Core.Save { // ─── 顶层 ───────────────────────────────────────────────────────────────── [Serializable] public class SaveData { [JsonExtensionData] public Dictionary 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 Dictionary 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 } // ─── 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 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 EquippedCharmIds = new(); public int NotchesUsed; public int MaxNotches; public List OwnedCharmIds = new(); public List UpgradedCharmIds = new(); } // ─── World ──────────────────────────────────────────────────────────────── [Serializable] public class WorldSaveData { public List VisitedScenes = new(); public List ActivatedSavePoints = new(); public List OpenedDoors = new(); public List DefeatedBossIds = new(); public List CollectedIds = new(); public Dictionary Switches = new(); public Dictionary NpcRelations = new(); public HashSet ChallengeFirstClears = new(); } // ─── Map ────────────────────────────────────────────────────────────────── [Serializable] public class MapSaveData { public Dictionary> DiscoveredRooms = new(); public Dictionary MapPurchased = new(); } // ─── Quests ─────────────────────────────────────────────────────────────── [Serializable] public class QuestSaveData { public Dictionary QuestStates = new(); public List AvailableQuestIds = new(); } [Serializable] public class QuestState { public string Status; // "NotStarted"|"Active"|"Completed"|"Failed" public int ObjectiveIndex; public List ProgressCounts = new(); public string GiverNpcId; } // ─── Achievements ───────────────────────────────────────────────────────── [Serializable] public class AchievementSaveData { public List Unlocked = new(); public Dictionary 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 int SaveCount; public Dictionary SkillUseCounts = new(); public Dictionary DeathsByBoss = new(); } // ─── Tools ──────────────────────────────────────────────────────────────── [Serializable] public class ToolsSaveData { public string ToolSlot0; public string ToolSlot1; public List OwnedToolIds = new(); public Dictionary ToolStates = new(); } // ─── ChallengeRooms ─────────────────────────────────────────────────────── [Serializable] public class ChallengeRoomsSaveData { public Dictionary 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 ChainStates = new(); public Dictionary WorldFlags = new(); } // ─── Shops ──────────────────────────────────────────────────────────────── [Serializable] public class ShopsSaveData { public Dictionary ShopRecords = new(); } [Serializable] public class ShopRecord { public List SoldUniqueItems = new(); public Dictionary PurchaseCounts = new(); } // ─── NGPlus ─────────────────────────────────────────────────────────────── [Serializable] public class NGPlusSaveData { public int NGPlusCount; public bool SteelSoulMode; public Dictionary NGPlusFlags = new(); } // ─── SlotSummary(主菜单 UI 用)──────────────────────────────────────────── public class SlotSummary { public int SlotIndex; public float Playtime; public string LastSaved; public string SceneName; public string ActiveFormId; } }