剧情+对话完善
This commit is contained in:
@@ -12,8 +12,8 @@ namespace Ichni
|
||||
/// 全局存档入口。
|
||||
/// <para><see cref="SongSaveModule"/> 负责可重复游玩的歌曲成绩与谱面记录;</para>
|
||||
/// <para><see cref="UnlockSaveModule"/> 负责章节、歌曲及未来内容共用的 Offline 解锁 Key;</para>
|
||||
/// <para><see cref="StorySaveModule"/> 负责章节故事树、对话选项和 Yarn 变量。</para>
|
||||
/// 两套数据使用不同文件和不同生命周期,修改任一侧时不要把另一侧的字段或迁移规则混入其中。
|
||||
/// <para><see cref="StorySaveModule"/> 负责章节故事树、对话选项、章节 Yarn 变量和 Timeline 回滚快照。</para>
|
||||
/// 三套数据使用不同文件和不同生命周期,修改任一数据域时不要把其它数据域的字段或迁移规则混入其中。
|
||||
/// </summary>
|
||||
public class GameSaveManager : SerializedMonoBehaviour
|
||||
{
|
||||
@@ -46,9 +46,10 @@ namespace Ichni
|
||||
UnlockSaveModule = new UnlockSaveModule();
|
||||
UnlockSaveModule.LoadUnlockKeys();
|
||||
|
||||
// 剧情变量属于独立存档,不参与歌曲成绩的 Schema 或 Chart Revision 迁移。
|
||||
// 剧情变量属于章节存档,不参与歌曲成绩的 Schema 或 Chart Revision 迁移。
|
||||
// 章节真正被打开时,StoryTreeController 才加载对应 ChapterStorySave;
|
||||
// 不在启动阶段加载已经废弃的全局 StoryVariables 文件。
|
||||
StorySaveModule = new StorySaveModule();
|
||||
StorySaveModule.LoadVariables();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +88,11 @@ namespace Ichni
|
||||
songStatus.additionalInfo ??= string.Empty;
|
||||
songStatus.beatmapSavesByDifficultyId ??= new Dictionary<int, BeatmapSave>();
|
||||
|
||||
// 旧存档没有 isTried 字段。任何已拥有有效结算的歌曲都必然曾被尝试过,
|
||||
// 因而可在不丢失既有 Story SongBlock 进度的前提下安全补齐该字段。
|
||||
if (songStatus.isCompleted)
|
||||
songStatus.isTried = true;
|
||||
|
||||
foreach (DifficultyData difficulty in song.difficultyDataList)
|
||||
{
|
||||
if (difficulty == null || difficulty.saveDifficultyId < 0)
|
||||
@@ -204,6 +210,7 @@ namespace Ichni
|
||||
}
|
||||
|
||||
songStatus.additionalInfo ??= string.Empty;
|
||||
songStatus.isTried = true;
|
||||
BeatmapSave beatmapSave = songStatus.GetOrCreateBeatmapSave(saveDifficultyId);
|
||||
|
||||
bool recordChanged = beatmapSave.ApplyPlayResult(recorder, currentChartRevision);
|
||||
@@ -214,6 +221,38 @@ namespace Ichni
|
||||
return recordChanged || completionChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标记玩家已确认进入指定歌曲。
|
||||
/// <para>这是 Story SongBlock 的唯一完成依据:选择歌曲并启动 GameScene 即写入,即使玩家随后中途退出,
|
||||
/// 也能在下次打开剧情树时恢复对应 Block 的完成状态。该状态不影响 Accuracy、FC、AP、Max Combo 或 isCompleted。</para>
|
||||
/// </summary>
|
||||
/// <param name="songName">SongItemData.songName,对应 SongSaves 的稳定歌曲 Key。</param>
|
||||
/// <returns>本次是否首次写入 isTried。</returns>
|
||||
public bool MarkSongTried(string songName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(songName))
|
||||
{
|
||||
Debug.LogWarning("Cannot mark a song as tried without a song name.");
|
||||
return false;
|
||||
}
|
||||
|
||||
songStatusSaves ??= new Dictionary<string, SongStatusSave>();
|
||||
if (!songStatusSaves.TryGetValue(songName, out SongStatusSave songStatus) || songStatus == null)
|
||||
{
|
||||
// 正常流程会在启动时为当前内容创建空记录;此分支仅作为运行时防线,
|
||||
// 防止新增歌曲尚未完成内容对账时丢失一次已确认的游玩入口。
|
||||
songStatus = new SongStatusSave(false, string.Empty, new Dictionary<int, BeatmapSave>());
|
||||
songStatusSaves[songName] = songStatus;
|
||||
}
|
||||
|
||||
if (songStatus.isTried)
|
||||
return false;
|
||||
|
||||
songStatus.isTried = true;
|
||||
SaveSongStatuses();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取歌曲记录并执行内容对账和 Chart Revision 检查。
|
||||
/// 当前为正式发布前的重置策略:任何非 v1 的旧测试存档都会直接被新 v1 结构覆盖,
|
||||
@@ -290,5 +329,5 @@ namespace Ichni
|
||||
}
|
||||
}
|
||||
|
||||
// StorySaveModule 已迁移至 NewStorySystem/Save/StorySaveModule.cs(按章节存树/选项,全局存变量)
|
||||
// StorySaveModule 已迁移至 NewStorySystem/Save/StorySaveModule.cs(按章节保存 Block、选项、变量和回滚快照)。
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user