Files
ichni_Official/Assets/Scripts/NewStorySystem/Progress/StoryProgress.cs

116 lines
4.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}
}
}