Story流程+本地化

This commit is contained in:
SoulliesOfficial
2026-07-24 17:56:30 -04:00
parent b0e0a7d5aa
commit de70870682
250 changed files with 5719 additions and 272966 deletions

View File

@@ -63,11 +63,6 @@ namespace Ichni.Story
issues.Add("[Warning] Yarn Project 未配置TextBlock 无法开始对应的 Yarn 节点。");
}
if (yarnLineStringTable == null || yarnLineStringTable.IsEmpty)
{
issues.Add("[Error] Yarn Line String Table 未配置Player 中无法在启动对话前加载当前 Locale 的台词表。");
}
foreach (StoryVariableDefinition variable in initialVariables)
{
if (variable == null)
@@ -121,6 +116,7 @@ namespace Ichni.Story
}
ValidateTextBlockYarnNodes(issues);
ValidateUniqueSongBlockIds(issues);
HashSet<string> reachableBlockIds = ValidateStoryGraph(blockIds, issues);
foreach (StoryTimelineMarkerDefinition marker in timelineMarkers)
@@ -262,6 +258,43 @@ namespace Ichni.Story
/// 对 StoryData 的连接图做只读的结构检查:入口、不可达 Block、环路、非向前连接与终点。
/// 这些检查不评价具体剧情质量,只定位最容易造成“永远无法游玩”或“无法结束章节”的配置问题。
/// </summary>
/// <summary>
/// SongSelection -> Story 的定向入口以 SongItemData.songName 匹配 SongBlock.songName。
/// 同一章节内重复配置同一 Song ID 时,运行时只能按列表顺序定位第一个 Block
/// 因此在编辑阶段输出 Warning让配置者消除这个导航歧义。
/// </summary>
private void ValidateUniqueSongBlockIds(List<string> issues)
{
Dictionary<string, List<string>> blockIdsBySongId = new Dictionary<string, List<string>>();
foreach (StoryBlockDefinition block in blocks)
{
if (block == null || block.blockType != StoryBlockType.Song ||
string.IsNullOrWhiteSpace(block.songName))
{
continue;
}
if (!blockIdsBySongId.TryGetValue(block.songName, out List<string> referencedBlocks))
{
referencedBlocks = new List<string>();
blockIdsBySongId[block.songName] = referencedBlocks;
}
referencedBlocks.Add(block.blockId);
}
foreach (KeyValuePair<string, List<string>> pair in blockIdsBySongId)
{
if (pair.Value.Count <= 1)
continue;
issues.Add(
$"[Warning] Song ID '{pair.Key}' 被多个 SongBlock 引用({string.Join(", ", pair.Value)})。" +
"SongSelection -> Story 只能定位列表中的第一个 Block请保留每章每首歌唯一的 SongBlock。"
);
}
}
private HashSet<string> ValidateStoryGraph(HashSet<string> blockIds, List<string> issues)
{
Dictionary<string, List<string>> adjacency = new Dictionary<string, List<string>>();