using System; using System.Collections.Generic; using UnityEngine; [Serializable] public class ChartFileEntry { [Header("难度序列号0/1/2/3 -> ez/hd/im/in")] public int difficulty; // 该谱面对应的难度序列号 [Header("展示给用户的难度分级:float数字")] public float difficultyLEVEL; [Header("本难本难度敌人总生命值=音符数量×下面的倍率")] public float enemyTotalHP_Multiplier; [Header("ez/hd/im/in 没啥用")] public string difficultyName; // 难度名称 [Header("谱面文件 json")] public TextAsset chartFile; // 谱面文件 [Header("本关本难度描述 文本")] [TextArea(3,10)] public string difficultyDescription; [Header("本关本难度上次游玩分数记录")] public int lastScoreForThisDifficulty; // 上次游玩(总分/参考) [Header("本关本难度个人分记录(谱面分)")] public int chartPersonalRecordForThisDifficulty; // 谱面(个人)分 [Header("本关本难度偶像分记录")] public int idolPersonalRecordForThisDifficulty; // 偶像分 [Header("本关本难度总分展示 (谱面分 + 偶像分)")] public int totalPersonalRecordForThisDifficulty; // 展示用:谱面分 + 偶像分 (总分) [Header("本关本难度进度")] public float levelProgressForThisDifficulty; [Header("本关本难度最后游玩时间")] public DateTime lastPlayTimeForThisDifficulty; [Header("本关本难度提供的经验值")] public int experienceProvidedForThisDifficulty; } [CreateAssetMenu(fileName = "NewSongData", menuName = "EaseOut/SongData")] public class SongData : ScriptableObject { public string usernameID = "user_TestUser@FloatGaming"; public string songName; public int songID; public int songLength_second; public string artistName; public string painter; public string level_creator; public string belongsTo_whichDLC; public int bpm; public float songDuration; public int game_enterTimes; public float time_totalPlayingTime; public DateTime uploadData; [Header("各种图")] public Sprite illustration; public Sprite backgroudPIC; public Sprite fullscreen_songPicture; public Sprite card_profileImage; [Header("右侧卡片用图")] public Sprite right_pic_bottom_image; public Sprite right_pic_top_image; [Header("音乐")] public AudioClip audioFile; public AudioClip audio_previewAudio; [Header("")] // 支持不同难度的数据 public Dictionary difficultyNumberMap = new Dictionary(); // 各个难度的难度数值 public Dictionary personalRecordMap = new Dictionary(); // 各个难度的谱面(个人)最高分 public Dictionary idolRecordMap = new Dictionary(); // 各个难度的偶像分 public Dictionary chartScoreMap = new Dictionary(); // 各个难度的谱面(上次)分数记录 public Dictionary chartFileMap = new Dictionary(); // 各个难度下的谱面文件 // 用于在 Inspector 选择谱面文件 public List chartFiles = new List(); // 个人最高记录(所有难度中的最高分) - 这里表示最高的「谱面分 + 偶像分」之和(全谱面最高) public int personalRecord; // 当前游玩的难度 public int difficultyID; public float current_levelProgress; public bool _if_level_is_EASE; public int max_comboRecord; [Header("当前选择的关卡难度")] public int thisLevel_selectedDifficultyID; [Header("本关卡加入时间:字符串格式yyyy-mm-dd")] public string thisLevel_addDateString; [Header("本关卡总体简介")] [TextArea(3,10)] public string thisLevel_overallDescription; // Ensure dictionaries initialized when ScriptableObject is loaded/deserialized private void OnEnable() { if (difficultyNumberMap == null) difficultyNumberMap = new Dictionary(); if (personalRecordMap == null) personalRecordMap = new Dictionary(); if (idolRecordMap == null) idolRecordMap = new Dictionary(); if (chartScoreMap == null) chartScoreMap = new Dictionary(); if (chartFileMap == null) chartFileMap = new Dictionary(); // If chartFiles exist in inspector, ensure maps reflect them // Commented out automatic sync — disabled per request // if (chartFiles != null && chartFiles.Count > 0) // { // SyncRecordsFromChartFiles(); // SyncChartFileMap(); // } } /* // 构造函数:从 JSON 数据创建 SongData public SongData(SongDataSerializable jsonData) { usernameID = jsonData.usernameID; songName = jsonData.songName; songID = jsonData.songID; songLength_second = jsonData.songLength_second; artistName = jsonData.artistName; painter = jsonData.painter; level_creator = jsonData.level_creator; belongsTo_whichDLC = jsonData.belongsTo_whichDLC; bpm = jsonData.bpm; songDuration = jsonData.songDuration; game_enterTimes = jsonData.game_enterTimes; time_totalPlayingTime = jsonData.time_totalPlayingTime; uploadData = DateTime.Parse(jsonData.uploadData); difficultyID = jsonData.difficultyID; current_levelProgress = jsonData.current_levelProgress; _if_level_is_EASE = jsonData._if_level_is_EASE; max_comboRecord = jsonData.max_comboRecord; difficultyNumberMap = jsonData.difficultyNumberMap ?? new Dictionary(); personalRecordMap = jsonData.personalRecordMap ?? new Dictionary(); idolRecordMap = jsonData.idolRecordMap ?? new Dictionary(); chartScoreMap = jsonData.chartScoreMap ?? new Dictionary(); personalRecord = jsonData.personalRecord; // 赋值最高成绩 // 确保 JSON 里的谱面文件映射到可用的 List foreach (var kvp in jsonData.chartFileMap) { chartFiles.Add(new ChartFileEntry { difficulty = kvp.Key, chartFile = Resources.Load("Charts/" + kvp.Value) }); } SyncChartFileMap(); // 从 chartFiles 中同步各难度的记录到字典(如果 inspector 中有填写) SyncRecordsFromChartFiles(); // Ensure per-difficulty chartScoreMap populated from entries if not present foreach (var entry in chartFiles) { if (!chartScoreMap.ContainsKey(entry.difficulty)) chartScoreMap[entry.difficulty] = entry.lastScoreForThisDifficulty; } } */ // 获取所有难度中最高的成绩(谱面分 + 偶像分 的最大和) public int CalculateHighestPersonalRecord() { if (personalRecordMap == null) personalRecordMap = new Dictionary(); if (idolRecordMap == null) idolRecordMap = new Dictionary(); int highest = 0; foreach (var kvp in personalRecordMap) { int diff = kvp.Key; int p = kvp.Value; int i = idolRecordMap.ContainsKey(diff) ? idolRecordMap[diff] : 0; int combined = p + i; if (combined > highest) { highest = combined; } } personalRecord = highest; return highest; } // 更新指定难度的最高纪录 (只有当总分更高时才更新) public void UpdateDifficultyRecord(int difficulty, int pmScore, int idolScore) { if (personalRecordMap == null) personalRecordMap = new Dictionary(); if (idolRecordMap == null) idolRecordMap = new Dictionary(); int currentBestTotal = GetPersonalRecord(difficulty) + GetIdolRecord(difficulty); int newTotal = pmScore + idolScore; if (newTotal > currentBestTotal) { personalRecordMap[difficulty] = pmScore; idolRecordMap[difficulty] = idolScore; // also update corresponding ChartFileEntry if exists var entry = chartFiles != null ? chartFiles.Find(e => e.difficulty == difficulty) : null; if (entry != null) { entry.chartPersonalRecordForThisDifficulty = pmScore; entry.idolPersonalRecordForThisDifficulty = idolScore; entry.totalPersonalRecordForThisDifficulty = newTotal; } CalculateHighestPersonalRecord(); } } // 获取全难度下的最高分及其对应的难度名称 public void GetAbsoluteHighestScore(out int highestScore, out int bestDifficulty, out string bestDifficultyName) { highestScore = 0; bestDifficulty = -1; bestDifficultyName = ""; // 优先遍历 chartFiles 获取数据和名称 if (chartFiles != null && chartFiles.Count > 0) { foreach (var entry in chartFiles) { if (entry == null) continue; // 重新计算总分以确保准确 int total = GetPersonalRecord(entry.difficulty) + GetIdolRecord(entry.difficulty); // 如果字典里没数据,尝试用 entry 里的初始数据 if (total <= 0) total = entry.totalPersonalRecordForThisDifficulty; if (total <= 0) total = entry.chartPersonalRecordForThisDifficulty + entry.idolPersonalRecordForThisDifficulty; if (total > highestScore || bestDifficulty == -1) { highestScore = total; bestDifficulty = entry.difficulty; bestDifficultyName = !string.IsNullOrEmpty(entry.difficultyName) ? entry.difficultyName : GetDifficultyDefaultName(entry.difficulty); } } } // 如果 chartFiles 为空,检查字典作为备选 if (bestDifficulty == -1 && personalRecordMap != null) { foreach (var kvp in personalRecordMap) { int diff = kvp.Key; int p = kvp.Value; int i = GetIdolRecord(diff); int combined = p + i; if (combined > highestScore || bestDifficulty == -1) { highestScore = combined; bestDifficulty = diff; bestDifficultyName = GetDifficultyDefaultName(diff); } } } } private string GetDifficultyDefaultName(int difficulty) { switch (difficulty) { case 0: return "Easy"; case 1: return "Hard"; case 2: return "Incredible"; case 3: return "Impossible"; default: return "Unknown"; } } // 更新指定难度的谱面(个人)最高成绩 public void UpdatePersonalRecord(int difficulty, int newScore) { if (personalRecordMap == null) personalRecordMap = new Dictionary(); if (!personalRecordMap.ContainsKey(difficulty) || newScore > personalRecordMap[difficulty]) { personalRecordMap[difficulty] = newScore; } // also update corresponding ChartFileEntry if exists var entry = chartFiles != null ? chartFiles.Find(e => e.difficulty == difficulty) : null; if (entry != null) { entry.chartPersonalRecordForThisDifficulty = personalRecordMap[difficulty]; int idol = idolRecordMap != null && idolRecordMap.ContainsKey(difficulty) ? idolRecordMap[difficulty] : 0; entry.totalPersonalRecordForThisDifficulty = personalRecordMap[difficulty] + idol; } CalculateHighestPersonalRecord(); } // 更新指定难度的偶像分 public void UpdateIdolRecord(int difficulty, int newIdolScore) { if (idolRecordMap == null) idolRecordMap = new Dictionary(); if (!idolRecordMap.ContainsKey(difficulty) || newIdolScore > idolRecordMap[difficulty]) { idolRecordMap[difficulty] = newIdolScore; } // also update corresponding ChartFileEntry if exists var entry = chartFiles != null ? chartFiles.Find(e => e.difficulty == difficulty) : null; if (entry != null) { entry.idolPersonalRecordForThisDifficulty = idolRecordMap[difficulty]; int personal = personalRecordMap != null && personalRecordMap.ContainsKey(difficulty) ? personalRecordMap[difficulty] : 0; entry.totalPersonalRecordForThisDifficulty = personal + idolRecordMap[difficulty]; } CalculateHighestPersonalRecord(); } // 更新或设置谱面上次分数记录(last run 总分) public void UpdateChartScore(int difficulty, int newChartScore) { if (chartScoreMap == null) chartScoreMap = new Dictionary(); chartScoreMap[difficulty] = newChartScore; var entry = chartFiles != null ? chartFiles.Find(e => e.difficulty == difficulty) : null; if (entry != null) { entry.lastScoreForThisDifficulty = newChartScore; } } // 获取特定难度的谱面(个人)最高分 public int GetPersonalRecord(int difficulty) { if (personalRecordMap == null) return 0; return personalRecordMap.ContainsKey(difficulty) ? personalRecordMap[difficulty] : 0; } // 获取特定难度的偶像分 public int GetIdolRecord(int difficulty) { if (idolRecordMap == null) return 0; return idolRecordMap.ContainsKey(difficulty) ? idolRecordMap[difficulty] : 0; } // 获取特定难度的谱面(上次)分数 public int GetChartScore(int difficulty) { if (chartScoreMap == null) return 0; return chartScoreMap.ContainsKey(difficulty) ? chartScoreMap[difficulty] : 0; } // 获取指定难度的谱面文件 public TextAsset GetChartFile(int difficulty) { if (chartFiles == null) return null; foreach (var entry in chartFiles) { if (entry.difficulty == difficulty) return entry.chartFile; } return null; } // 同步 Dictionary 和 List 确保数据一致 public void SyncChartFileMap() { if (chartFileMap == null) chartFileMap = new Dictionary(); chartFileMap.Clear(); if (chartFiles == null) return; foreach (var entry in chartFiles) { if (entry.chartFile != null) { chartFileMap[entry.difficulty] = entry.chartFile; } } } // 从 chartFiles 中读取各难度的谱面分/偶像分到 Map(用于 inspector 已填写时) public void SyncRecordsFromChartFiles() { if (personalRecordMap == null) personalRecordMap = new Dictionary(); if (idolRecordMap == null) idolRecordMap = new Dictionary(); if (chartScoreMap == null) chartScoreMap = new Dictionary(); if (chartFiles == null) return; foreach (var entry in chartFiles) { if (entry == null) continue; if (!personalRecordMap.ContainsKey(entry.difficulty) || entry.chartPersonalRecordForThisDifficulty > personalRecordMap[entry.difficulty]) { personalRecordMap[entry.difficulty] = entry.chartPersonalRecordForThisDifficulty; } if (!idolRecordMap.ContainsKey(entry.difficulty) || entry.idolPersonalRecordForThisDifficulty > idolRecordMap[entry.difficulty]) { idolRecordMap[entry.difficulty] = entry.idolPersonalRecordForThisDifficulty; } if (!chartScoreMap.ContainsKey(entry.difficulty) || entry.lastScoreForThisDifficulty > chartScoreMap[entry.difficulty]) { chartScoreMap[entry.difficulty] = entry.lastScoreForThisDifficulty; } // keep per-entry convenience field in sync to combined total int p = personalRecordMap.ContainsKey(entry.difficulty) ? personalRecordMap[entry.difficulty] : 0; int i = idolRecordMap.ContainsKey(entry.difficulty) ? idolRecordMap[entry.difficulty] : 0; entry.totalPersonalRecordForThisDifficulty = p + i; } CalculateHighestPersonalRecord(); } }