超大量的更新 修复很多问题,gameplay特效初步
This commit is contained in:
+267
-190
@@ -5,34 +5,39 @@ using UnityEngine;
|
||||
[Serializable]
|
||||
public class ChartFileEntry
|
||||
{
|
||||
[Header("难度序列号0/1/2/3 -> ez/hd/im/in")]
|
||||
public int difficulty; // 该谱面对应的难度序列号
|
||||
[Header("展示给用户的难度分级:float数字")]
|
||||
[Header("Inspector")]
|
||||
public int difficulty;
|
||||
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;
|
||||
|
||||
[Header("Inspector")]
|
||||
public float enemyTotalHP_Multiplier;
|
||||
|
||||
[Header("Inspector")]
|
||||
public string difficultyName;
|
||||
|
||||
[Header("Inspector")]
|
||||
public TextAsset chartFile;
|
||||
|
||||
[Header("Inspector")]
|
||||
[TextArea(3, 10)]
|
||||
public string difficultyDescription;
|
||||
|
||||
[Header("Inspector")]
|
||||
public int lastScoreForThisDifficulty;
|
||||
|
||||
[Header("Inspector")]
|
||||
public int chartPersonalRecordForThisDifficulty;
|
||||
public int idolPersonalRecordForThisDifficulty;
|
||||
public int totalPersonalRecordForThisDifficulty;
|
||||
|
||||
[Header("Inspector")]
|
||||
public float levelProgressForThisDifficulty;
|
||||
|
||||
[Header("Inspector")]
|
||||
public DateTime lastPlayTimeForThisDifficulty;
|
||||
|
||||
[Header("Inspector")]
|
||||
public int experienceProvidedForThisDifficulty;
|
||||
}
|
||||
|
||||
[CreateAssetMenu(fileName = "NewSongData", menuName = "EaseOut/SongData")]
|
||||
@@ -54,49 +59,58 @@ public class SongData : ScriptableObject
|
||||
public float time_totalPlayingTime;
|
||||
public DateTime uploadData;
|
||||
|
||||
[Header("各种图")]
|
||||
[Header("Inspector")]
|
||||
public Sprite illustration;
|
||||
public Sprite backgroudPIC;
|
||||
public Sprite fullscreen_songPicture;
|
||||
public Sprite card_profileImage;
|
||||
[Header("右侧卡片用图")]
|
||||
|
||||
[Header("Inspector")]
|
||||
public Sprite right_pic_bottom_image;
|
||||
public Sprite right_pic_top_image;
|
||||
[Header("音乐")]
|
||||
|
||||
[Header("Inspector")]
|
||||
public AudioClip audioFile;
|
||||
public AudioClip audio_previewAudio;
|
||||
|
||||
[Header("")]
|
||||
// 支持不同难度的数据
|
||||
public Dictionary<int, int> difficultyNumberMap = new Dictionary<int, int>(); // 各个难度的难度数值
|
||||
public Dictionary<int, int> personalRecordMap = new Dictionary<int, int>(); // 各个难度的谱面(个人)最高分
|
||||
public Dictionary<int, int> idolRecordMap = new Dictionary<int, int>(); // 各个难度的偶像分
|
||||
public Dictionary<int, int> chartScoreMap = new Dictionary<int, int>(); // 各个难度的谱面(上次)分数记录
|
||||
public Dictionary<int, TextAsset> chartFileMap = new Dictionary<int, TextAsset>(); // 各个难度下的谱面文件
|
||||
[Header("Inspector")]
|
||||
public int difficultyID;
|
||||
public Dictionary<int, int> difficultyNumberMap = new Dictionary<int, int>();
|
||||
public Dictionary<int, int> personalRecordMap = new Dictionary<int, int>();
|
||||
public Dictionary<int, int> idolRecordMap = new Dictionary<int, int>();
|
||||
public Dictionary<int, int> chartScoreMap = new Dictionary<int, int>();
|
||||
public Dictionary<int, TextAsset> chartFileMap = new Dictionary<int, TextAsset>();
|
||||
|
||||
// 用于在 Inspector 选择谱面文件
|
||||
public List<ChartFileEntry> chartFiles = new List<ChartFileEntry>();
|
||||
|
||||
// 个人最高记录(所有难度中的最高分) - 这里表示最高的「谱面分 + 偶像分」之和(全谱面最高)
|
||||
public int personalRecord;
|
||||
|
||||
// 当前游玩的难度
|
||||
public int difficultyID;
|
||||
public float current_levelProgress;
|
||||
public bool _if_level_is_EASE;
|
||||
public int max_comboRecord;
|
||||
|
||||
[Header("当前选择的关卡难度")]
|
||||
[Header("Inspector")]
|
||||
public int thisLevel_selectedDifficultyID;
|
||||
|
||||
[Header("本关卡加入时间:字符串格式yyyy-mm-dd")]
|
||||
[Header("Inspector")]
|
||||
public string thisLevel_addDateString;
|
||||
|
||||
[Header("本关卡总体简介")]
|
||||
[TextArea(3,10)]
|
||||
[Header("Inspector")]
|
||||
[TextArea(3, 10)]
|
||||
public string thisLevel_overallDescription;
|
||||
|
||||
// Ensure dictionaries initialized when ScriptableObject is loaded/deserialized
|
||||
[Header("Enemy Configuration")]
|
||||
[Tooltip("List of enemy IDs for this song (0-5 enemies)")]
|
||||
public List<int> enemyList = new List<int>();
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
if (enemyList != null && enemyList.Count > 5)
|
||||
{
|
||||
enemyList.RemoveRange(5, enemyList.Count - 5);
|
||||
Debug.LogWarning($"[SongData] {songName}: enemyList length restricted to a maximum of 5.");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (difficultyNumberMap == null) difficultyNumberMap = new Dictionary<int, int>();
|
||||
@@ -104,71 +118,16 @@ public class SongData : ScriptableObject
|
||||
if (idolRecordMap == null) idolRecordMap = new Dictionary<int, int>();
|
||||
if (chartScoreMap == null) chartScoreMap = new Dictionary<int, int>();
|
||||
if (chartFileMap == null) chartFileMap = new Dictionary<int, TextAsset>();
|
||||
if (chartFiles == null) chartFiles = new List<ChartFileEntry>();
|
||||
|
||||
// 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<int,int>();
|
||||
personalRecordMap = jsonData.personalRecordMap ?? new Dictionary<int,int>();
|
||||
idolRecordMap = jsonData.idolRecordMap ?? new Dictionary<int,int>();
|
||||
chartScoreMap = jsonData.chartScoreMap ?? new Dictionary<int,int>();
|
||||
personalRecord = jsonData.personalRecord; // 赋值最高成绩
|
||||
|
||||
// 确保 JSON 里的谱面文件映射到可用的 List
|
||||
foreach (var kvp in jsonData.chartFileMap)
|
||||
{
|
||||
chartFiles.Add(new ChartFileEntry { difficulty = kvp.Key, chartFile = Resources.Load<TextAsset>("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;
|
||||
}
|
||||
SyncChartFileMap();
|
||||
}
|
||||
*/
|
||||
|
||||
// 获取所有难度中最高的成绩(谱面分 + 偶像分 的最大和)
|
||||
public int CalculateHighestPersonalRecord()
|
||||
{
|
||||
if (personalRecordMap == null) personalRecordMap = new Dictionary<int,int>();
|
||||
if (idolRecordMap == null) idolRecordMap = new Dictionary<int,int>();
|
||||
if (personalRecordMap == null) personalRecordMap = new Dictionary<int, int>();
|
||||
if (idolRecordMap == null) idolRecordMap = new Dictionary<int, int>();
|
||||
|
||||
int highest = 0;
|
||||
foreach (var kvp in personalRecordMap)
|
||||
@@ -178,15 +137,149 @@ public class SongData : ScriptableObject
|
||||
int i = idolRecordMap.ContainsKey(diff) ? idolRecordMap[diff] : 0;
|
||||
int combined = p + i;
|
||||
if (combined > highest)
|
||||
{
|
||||
highest = combined;
|
||||
}
|
||||
}
|
||||
|
||||
personalRecord = highest;
|
||||
return highest;
|
||||
}
|
||||
|
||||
// 更新指定难度的最高纪录 (只有当总分更高时才更新)
|
||||
/// <summary>
|
||||
/// 将数据保存到持久化存储,并附加 MD5 校验和防止篡改。
|
||||
/// </summary>
|
||||
public void SavePersistent()
|
||||
{
|
||||
try
|
||||
{
|
||||
string path = System.IO.Path.Combine(Application.persistentDataPath, $"SongData_{songID}.json");
|
||||
SongDataSerializable serializable = new SongDataSerializable(this);
|
||||
|
||||
// 1. 序列化基础数据
|
||||
string jsonWithoutHash = JsonUtility.ToJson(serializable);
|
||||
|
||||
// 2. 计算 MD5 (使用自定义盐值提高安全性)
|
||||
serializable.dataHash = CalculateMD5(jsonWithoutHash + "bansonic2026@fudongyouxi");
|
||||
|
||||
// 3. 再次序列化包含 Hash 的最终数据
|
||||
string finalJson = JsonUtility.ToJson(serializable, true);
|
||||
System.IO.File.WriteAllText(path, finalJson);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
UnityEditor.AssetDatabase.SaveAssets();
|
||||
}
|
||||
#endif
|
||||
Debug.Log($"[SongData] {songName} saved with hash validation.");
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"[SongData] Save failed: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从持久化 JSON 恢复数据。
|
||||
/// 校验逻辑已迁移至 DataCheck 脚本,此处仅执行基础加载。
|
||||
/// </summary>
|
||||
public void LoadPersistent()
|
||||
{
|
||||
string path = System.IO.Path.Combine(Application.persistentDataPath, $"SongData_{songID}.json");
|
||||
if (System.IO.File.Exists(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = System.IO.File.ReadAllText(path);
|
||||
// 尝试解析数据
|
||||
SongDataSerializable serializable = JsonUtility.FromJson<SongDataSerializable>(json);
|
||||
if (serializable != null)
|
||||
{
|
||||
serializable.ApplyTo(this);
|
||||
// Debug.Log($"[SongData] {songName} data restored.");
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogWarning($"[SongData] {songName} 基础加载跳过: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当检测到篡改或文件损坏时,重置所有动态记录并立即重新保存文件以恢复合法性。
|
||||
/// </summary>
|
||||
private void ResetToZeroAndSave()
|
||||
{
|
||||
// 1. 重置所有动态数值字段
|
||||
game_enterTimes = 0;
|
||||
time_totalPlayingTime = 0;
|
||||
current_levelProgress = 0;
|
||||
_if_level_is_EASE = false;
|
||||
max_comboRecord = 0;
|
||||
personalRecord = 0;
|
||||
|
||||
// 2. 清空并确保初始化所有动态字典映射
|
||||
if (difficultyNumberMap == null) difficultyNumberMap = new Dictionary<int, int>();
|
||||
else difficultyNumberMap.Clear();
|
||||
|
||||
if (personalRecordMap == null) personalRecordMap = new Dictionary<int, int>();
|
||||
else personalRecordMap.Clear();
|
||||
|
||||
if (idolRecordMap == null) idolRecordMap = new Dictionary<int, int>();
|
||||
else idolRecordMap.Clear();
|
||||
|
||||
if (chartScoreMap == null) chartScoreMap = new Dictionary<int, int>();
|
||||
else chartScoreMap.Clear();
|
||||
|
||||
// 3. 立即调用保存方法,生成一个新的、带有正确哈希值的合法文件
|
||||
SavePersistent();
|
||||
|
||||
Debug.LogWarning($"[SongData] {songName} has been fully reset to zero due to data integrity failure.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 静态校验方法,可在异步线程调用,判断 JSON 内容是否合法。
|
||||
/// </summary>
|
||||
public static bool VerifyJsonIntegrity(string json, string salt, out SongDataSerializable result)
|
||||
{
|
||||
result = null;
|
||||
try
|
||||
{
|
||||
SongDataSerializable serializable = JsonUtility.FromJson<SongDataSerializable>(json);
|
||||
if (serializable == null) return false;
|
||||
|
||||
string savedHash = serializable.dataHash;
|
||||
serializable.dataHash = "";
|
||||
string currentJson = JsonUtility.ToJson(serializable);
|
||||
|
||||
// 使用静态 MD5 计算
|
||||
string calculatedHash = StaticCalculateMD5(currentJson + salt);
|
||||
|
||||
result = serializable;
|
||||
return savedHash == calculatedHash;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static string StaticCalculateMD5(string input)
|
||||
{
|
||||
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
|
||||
{
|
||||
byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
|
||||
byte[] hashBytes = md5.ComputeHash(inputBytes);
|
||||
return System.BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
|
||||
}
|
||||
}
|
||||
|
||||
private string CalculateMD5(string input)
|
||||
{
|
||||
return StaticCalculateMD5(input);
|
||||
}
|
||||
|
||||
public void UpdateDifficultyRecord(int difficulty, int pmScore, int idolScore)
|
||||
{
|
||||
if (personalRecordMap == null) personalRecordMap = new Dictionary<int, int>();
|
||||
@@ -194,43 +287,37 @@ public class SongData : ScriptableObject
|
||||
|
||||
int currentBestTotal = GetPersonalRecord(difficulty) + GetIdolRecord(difficulty);
|
||||
int newTotal = pmScore + idolScore;
|
||||
if (newTotal <= currentBestTotal)
|
||||
return;
|
||||
|
||||
if (newTotal > currentBestTotal)
|
||||
personalRecordMap[difficulty] = pmScore;
|
||||
idolRecordMap[difficulty] = idolScore;
|
||||
|
||||
ChartFileEntry entry = chartFiles != null ? chartFiles.Find(e => e != null && e.difficulty == difficulty) : null;
|
||||
if (entry != null)
|
||||
{
|
||||
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();
|
||||
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)
|
||||
if (chartFiles != null)
|
||||
{
|
||||
foreach (var entry in chartFiles)
|
||||
for (int i = 0; i < chartFiles.Count; i++)
|
||||
{
|
||||
ChartFileEntry entry = chartFiles[i];
|
||||
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;
|
||||
|
||||
@@ -243,21 +330,18 @@ public class SongData : ScriptableObject
|
||||
}
|
||||
}
|
||||
|
||||
// 如果 chartFiles 为空,检查字典作为备选
|
||||
if (bestDifficulty == -1 && personalRecordMap != null)
|
||||
if (bestDifficulty != -1 || personalRecordMap == null)
|
||||
return;
|
||||
|
||||
foreach (var kvp in personalRecordMap)
|
||||
{
|
||||
foreach (var kvp in personalRecordMap)
|
||||
int diff = kvp.Key;
|
||||
int total = kvp.Value + GetIdolRecord(diff);
|
||||
if (total > highestScore || bestDifficulty == -1)
|
||||
{
|
||||
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);
|
||||
}
|
||||
highestScore = total;
|
||||
bestDifficulty = diff;
|
||||
bestDifficultyName = GetDifficultyDefaultName(diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -274,17 +358,13 @@ public class SongData : ScriptableObject
|
||||
}
|
||||
}
|
||||
|
||||
// 更新指定难度的谱面(个人)最高成绩
|
||||
public void UpdatePersonalRecord(int difficulty, int newScore)
|
||||
{
|
||||
if (personalRecordMap == null) personalRecordMap = new Dictionary<int,int>();
|
||||
if (personalRecordMap == null) personalRecordMap = new Dictionary<int, int>();
|
||||
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;
|
||||
ChartFileEntry entry = chartFiles != null ? chartFiles.Find(e => e != null && e.difficulty == difficulty) : null;
|
||||
if (entry != null)
|
||||
{
|
||||
entry.chartPersonalRecordForThisDifficulty = personalRecordMap[difficulty];
|
||||
@@ -295,17 +375,13 @@ public class SongData : ScriptableObject
|
||||
CalculateHighestPersonalRecord();
|
||||
}
|
||||
|
||||
// 更新指定难度的偶像分
|
||||
public void UpdateIdolRecord(int difficulty, int newIdolScore)
|
||||
{
|
||||
if (idolRecordMap == null) idolRecordMap = new Dictionary<int,int>();
|
||||
if (idolRecordMap == null) idolRecordMap = new Dictionary<int, int>();
|
||||
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;
|
||||
ChartFileEntry entry = chartFiles != null ? chartFiles.Find(e => e != null && e.difficulty == difficulty) : null;
|
||||
if (entry != null)
|
||||
{
|
||||
entry.idolPersonalRecordForThisDifficulty = idolRecordMap[difficulty];
|
||||
@@ -316,93 +392,94 @@ public class SongData : ScriptableObject
|
||||
CalculateHighestPersonalRecord();
|
||||
}
|
||||
|
||||
// 更新或设置谱面上次分数记录(last run 总分)
|
||||
public void UpdateChartScore(int difficulty, int newChartScore)
|
||||
{
|
||||
if (chartScoreMap == null) chartScoreMap = new Dictionary<int,int>();
|
||||
if (chartScoreMap == null) chartScoreMap = new Dictionary<int, int>();
|
||||
chartScoreMap[difficulty] = newChartScore;
|
||||
var entry = chartFiles != null ? chartFiles.Find(e => e.difficulty == difficulty) : null;
|
||||
|
||||
ChartFileEntry entry = chartFiles != null ? chartFiles.Find(e => e != null && 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;
|
||||
return personalRecordMap.TryGetValue(difficulty, out int v) ? v : 0;
|
||||
}
|
||||
|
||||
// 获取特定难度的偶像分
|
||||
public int GetIdolRecord(int difficulty)
|
||||
{
|
||||
if (idolRecordMap == null) return 0;
|
||||
return idolRecordMap.ContainsKey(difficulty) ? idolRecordMap[difficulty] : 0;
|
||||
return idolRecordMap.TryGetValue(difficulty, out int v) ? v : 0;
|
||||
}
|
||||
|
||||
// 获取特定难度的谱面(上次)分数
|
||||
public int GetChartScore(int difficulty)
|
||||
{
|
||||
if (chartScoreMap == null) return 0;
|
||||
return chartScoreMap.ContainsKey(difficulty) ? chartScoreMap[difficulty] : 0;
|
||||
return chartScoreMap.TryGetValue(difficulty, out int v) ? v : 0;
|
||||
}
|
||||
|
||||
// 获取指定难度的谱面文件
|
||||
public TextAsset GetChartFile(int difficulty)
|
||||
{
|
||||
if (chartFiles == null) return null;
|
||||
foreach (var entry in chartFiles)
|
||||
if (chartFiles != null)
|
||||
{
|
||||
if (entry.difficulty == difficulty)
|
||||
return entry.chartFile;
|
||||
for (int i = 0; i < chartFiles.Count; i++)
|
||||
{
|
||||
ChartFileEntry entry = chartFiles[i];
|
||||
if (entry != null && entry.difficulty == difficulty)
|
||||
return entry.chartFile;
|
||||
}
|
||||
}
|
||||
|
||||
if (chartFileMap != null && chartFileMap.TryGetValue(difficulty, out TextAsset mapped))
|
||||
return mapped;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// 同步 Dictionary 和 List 确保数据一致
|
||||
public void SyncChartFileMap()
|
||||
{
|
||||
if (chartFileMap == null) chartFileMap = new Dictionary<int, TextAsset>();
|
||||
chartFileMap.Clear();
|
||||
|
||||
if (chartFiles == null) return;
|
||||
foreach (var entry in chartFiles)
|
||||
for (int i = 0; i < chartFiles.Count; i++)
|
||||
{
|
||||
if (entry.chartFile != null)
|
||||
{
|
||||
ChartFileEntry entry = chartFiles[i];
|
||||
if (entry != null && entry.chartFile != null)
|
||||
chartFileMap[entry.difficulty] = entry.chartFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 从 chartFiles 中读取各难度的谱面分/偶像分到 Map(用于 inspector 已填写时)
|
||||
public void SyncRecordsFromChartFiles()
|
||||
{
|
||||
if (personalRecordMap == null) personalRecordMap = new Dictionary<int,int>();
|
||||
if (idolRecordMap == null) idolRecordMap = new Dictionary<int,int>();
|
||||
if (chartScoreMap == null) chartScoreMap = new Dictionary<int,int>();
|
||||
if (personalRecordMap == null) personalRecordMap = new Dictionary<int, int>();
|
||||
if (idolRecordMap == null) idolRecordMap = new Dictionary<int, int>();
|
||||
if (chartScoreMap == null) chartScoreMap = new Dictionary<int, int>();
|
||||
|
||||
if (chartFiles == null) return;
|
||||
foreach (var entry in chartFiles)
|
||||
|
||||
for (int i = 0; i < chartFiles.Count; i++)
|
||||
{
|
||||
ChartFileEntry entry = chartFiles[i];
|
||||
if (entry == null) continue;
|
||||
|
||||
if (!difficultyNumberMap.ContainsKey(entry.difficulty))
|
||||
difficultyNumberMap[entry.difficulty] = Mathf.RoundToInt(entry.difficultyLEVEL);
|
||||
|
||||
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;
|
||||
int idol = idolRecordMap.ContainsKey(entry.difficulty) ? idolRecordMap[entry.difficulty] : 0;
|
||||
entry.totalPersonalRecordForThisDifficulty = p + idol;
|
||||
}
|
||||
|
||||
CalculateHighestPersonalRecord();
|
||||
|
||||
Reference in New Issue
Block a user