存档重构,游戏内容解锁机制;教程完善(未完成)
This commit is contained in:
115
Assets/Scripts/NewStorySystem/Progress/StoryProgress.cs
Normal file
115
Assets/Scripts/NewStorySystem/Progress/StoryProgress.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.Story
|
||||
{
|
||||
/// <summary>
|
||||
/// 外部玩法系统修改剧情进度的统一入口。
|
||||
///
|
||||
/// StoryVariables 只负责读写内存中的变量字典,不会自动落盘或刷新故事树。
|
||||
/// 本类将“写变量、保存变量、重算 Block 状态”收口,避免教程、小游戏等系统重复实现
|
||||
/// 不完整的存档流程。
|
||||
/// </summary>
|
||||
public static class StoryProgress
|
||||
{
|
||||
/// <summary>
|
||||
/// 写入布尔剧情变量、保存到 StorySaveModule,并立即重新推导当前故事树。
|
||||
/// 可供教程以外的玩法系统使用。
|
||||
/// </summary>
|
||||
public static bool SetBoolAndRefresh(string variableName, bool value)
|
||||
{
|
||||
if (!TrySetBoolAndSave(variableName, value))
|
||||
return false;
|
||||
|
||||
StoryManager.instance?.treeController?.RefreshAllStates();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理一次 TutorialBlock 的选择结果。
|
||||
/// 无论选择“游玩”还是“跳过”,都会将其进度变量设为 true,并将教程节点标记为完成。
|
||||
/// 后续 Block 的解锁应依赖 <see cref="StoryBlockDefinition.tutorialProgressVariable"/>,
|
||||
/// 而不是依赖该节点的 completedBlockIds,以便和 Yarn 及其它剧情变量共用同一条件系统。
|
||||
/// </summary>
|
||||
public static bool ResolveTutorial(StoryBlockDefinition tutorialBlock)
|
||||
{
|
||||
if (tutorialBlock == null || tutorialBlock.blockType != StoryBlockType.Tutorial)
|
||||
{
|
||||
Debug.LogWarning("[StoryProgress] 无法处理空对象或非 Tutorial 类型的 Block。");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(tutorialBlock.blockId) ||
|
||||
string.IsNullOrWhiteSpace(tutorialBlock.tutorialProgressVariable))
|
||||
{
|
||||
Debug.LogWarning($"[StoryProgress] TutorialBlock '{tutorialBlock?.blockId}' 缺少 Block ID 或 Progress Variable,拒绝解锁。");
|
||||
return false;
|
||||
}
|
||||
|
||||
StoryTreeController treeController = StoryManager.instance?.treeController;
|
||||
if (treeController == null)
|
||||
{
|
||||
Debug.LogWarning("[StoryProgress] StoryTreeController 未就绪,拒绝写入教程进度。");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TrySetBoolAndSave(tutorialBlock.tutorialProgressVariable, true))
|
||||
return false;
|
||||
|
||||
// completedBlockIds 只负责教程节点自身的 Completed 外观与不可重复点击;
|
||||
// 后续节点应在 StoryData 中以 VariableCondition 读取上面的剧情变量。
|
||||
treeController.OnBlockCompleted(tutorialBlock.blockId);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除一个章节中所有 TutorialBlock 声明的进度变量。
|
||||
/// 目前供 StoryTreeController 的章节进度调试重置使用,确保变量条件与 completedBlockIds 一起回到初始状态。
|
||||
/// </summary>
|
||||
public static void ClearTutorialProgressForChapter(StoryData storyData)
|
||||
{
|
||||
if (storyData?.blocks == null ||
|
||||
GameSaveManager.instance == null || GameSaveManager.instance.StorySaveModule == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
foreach (StoryBlockDefinition block in storyData.blocks)
|
||||
{
|
||||
if (block == null || block.blockType != StoryBlockType.Tutorial ||
|
||||
string.IsNullOrWhiteSpace(block.tutorialProgressVariable))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!StoryVariables.HasVariable(block.tutorialProgressVariable))
|
||||
continue;
|
||||
|
||||
StoryVariables.Remove(block.tutorialProgressVariable);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
GameSaveManager.instance.StorySaveModule.SaveVariables();
|
||||
}
|
||||
|
||||
private static bool TrySetBoolAndSave(string variableName, bool value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(variableName))
|
||||
{
|
||||
Debug.LogWarning("[StoryProgress] 剧情变量名为空,拒绝写入。");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GameSaveManager.instance == null || GameSaveManager.instance.StorySaveModule == null)
|
||||
{
|
||||
Debug.LogWarning("[StoryProgress] StorySaveModule 未就绪,拒绝写入剧情变量。");
|
||||
return false;
|
||||
}
|
||||
|
||||
StoryVariables.SetBool(variableName, value);
|
||||
GameSaveManager.instance.StorySaveModule.SaveVariables();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user