Files
ichni_Official/docs/story-variable-registry.md
SoulliesOfficial fe00ecfcc7 微调
2026-07-24 03:43:11 -04:00

10 KiB
Raw Blame History

ichni Official 剧情变量登记表

状态:长期维护文档
适用范围:ichni Official 全部章节的正式剧情变量。
维护原则:每当场景卡批准新增变量时,必须按照变量在剧情中首次写入的顺序登记;不得等到 Yarn 或 StoryData 已大量使用后再补记。
当前内容只登记已经确认并实际进入正式 Yarn 的变量,不预先虚构未来章节的变量。

一、文档用途

本登记表是剧情作者、Yarn 编写者、StoryData 配置人员、本地化人员与程序员共同使用的变量来源。它用于回答:

  • 变量的稳定 Key 是什么;
  • 变量首次出现在哪个 Chapter、场景、TextBlock 与 Yarn 文件;
  • 变量使用何种类型和默认值;
  • 每个合法取值代表什么;
  • 哪些 Yarn Node 写入或读取变量;
  • 哪些 StoryData Block 使用变量作为 UnlockForbidden 条件;
  • Timeline 回滚会怎样处理该变量;
  • 变量当前处于计划、已使用、废弃还是迁移状态。

本登记表不替代场景卡或 StoryData。场景卡解释叙事意图StoryData 保存运行时初始值与条件;本登记表负责让所有使用者对同一个 Key 保持一致理解。

二、纳入与排除范围

必须登记

  • 通过 set_boolset_intset_floatset_string 写入的章节剧情变量;
  • 通过 add_intadd_float 累积的章节数值;
  • 被 Yarn if、StoryData Unlock ConditionForbidden Condition 或 Helper Availability 读取的剧情变量;
  • 为存档迁移而保留的旧变量与替代 Key。

不在本表登记

  • Yarn 选项记忆:由 StoryChoiceMemory 根据 Option Line ID 自动保存;
  • Block 完成状态:由章节存档的 completedBlockIds 保存;
  • Timeline Marker ID 与 checkpoint登记在场景卡和 StoryData
  • Localization Key
  • grant_unlock、歌曲解锁、教程解锁等全局 Unlock Key
  • Settings、歌曲成绩、isTried 或其它非剧情变量;
  • C0_RollbackDemo_* 等测试 Yarn 中的示例变量;
  • 废弃旧稿 C0_A0.yarn 中的 Yarn 原生 $variable

三、命名规范

Key 格式

  • 使用小写英文、数字与下划线:^[a-z0-9_]+$
  • 使用章节前缀Chapter 0 为 c0_Chapter 1 为 c1_,依此类推。
  • Key 表达稳定的剧情语义不使用具体台词、UI 文案或临时 Node 名。
  • 路线变量使用 _route 后缀,例如 c0_contract_route
  • 状态变量使用能够直接读懂的过去式或状态名;只有正式批准后才可确定实际 Key、登记并使用。
  • 计数或强度必须在名称中表明语义,例如未来可能出现的 _count_level_trust;不得使用 value1tempflag 等含义不明的 Key。

一项语义只保留一个变量

不要同时创建 c0_contract_routec0_contract_accepted 来表达同一选择。能够用一个枚举式 Int 完整表达的互斥路线,不再增加重复 Bool。

Key 稳定性

变量进入正式存档以后不得只为了“更好看”而重命名。确需改名时:

  1. 在本表把旧 Key 标记为 Deprecated
  2. 登记新 Key、迁移规则和首次生效版本
  3. 完成 Story Save migration
  4. 同步修改 Yarn、StoryData Conditions、Helper 条件和测试;
  5. 确认旧存档迁移后再停止读取旧 Key。

四、类型、默认值与命令

类型 未配置时读取回退 正式写入 读取 累加 适用内容
Bool false <<set_bool "key" true>> get_bool("key") 已发生/未发生、二态状态
Int 0 <<set_int "key" 1>> get_int("key") <<add_int "key" 1>> 路线编号、整数计数、离散等级
Float 0f <<set_float "key" 0.5>> get_float("key") <<add_float "key" 0.1>> 连续强度或比例
String "" <<set_string "key" "value">> get_string("key") 稳定文本 ID 或不能用数字表达的状态

虽然运行时在缺少定义时存在回退值,每个正式变量仍必须在对应 Chapter 的 StoryData Initial Variables 中显式配置类型与默认值。不得依赖隐式 0/false/"" 掩盖漏配。

其它可用接口:

<<remove_variable "key">>
<<if has_variable("key")>>
    // 该 Key 存在已保存值,或已在 StoryData Initial Variables 中定义。
<<endif>>

has_variable("key") 会把 StoryData Initial Variable 也视为存在。由于正式变量都应显式配置初始值,它通常会从章节开始便返回 true,不能用于判断“玩家是否已经在剧情中写入过这个变量”。若确实需要记录事件是否发生,应创建语义明确的 Bool而不是依赖变量是否存在。

正式剧情不得使用:

<<declare $variable = 0>>
<<set $variable = 1>>

这些 Yarn 原生变量不受当前章节事务、StoryData 条件和 Timeline 回滚系统统一管理。

五、存档与回滚规则

  • 剧情变量属于当前 StoryData.chapterIndex 对应的章节存档;不同章节完全隔离。
  • TextBlock 开始时建立章节事务。set_*add_* 在对话内更新当前章节状态,但只有对话正常结束才提交存档。
  • 玩家使用 Back 中途退出 TextBlock 时,本次变量变化、选项记忆与 Block 进度全部恢复到进入前状态。
  • Timeline Marker checkpoint 保存进入目标列以前的章节变量快照。回滚后,目标列及右侧剧情产生的变量变化被撤销。
  • Timeline 回滚不会修改歌曲成绩、Settings、全局 Unlock Key 或其它章节进度。
  • 如果变量控制互斥路线,所有相关 Block 必须同时配置相反的 Unlock 与 Forbidden 条件,不能只在 Yarn 内写 if

六、按剧情顺序登记

Chapter 0

顺序 首次写入场景 Variable Key 类型 默认值 合法值/范围 意义 写入位置 读取位置 回滚点 状态
C0-001 C0-S03 契约抉择与镜的降临 c0_contract_route Int 0 0 未选择;1 接受;2 拒绝 记录曦对神之契约的最终选择,并控制接受主线与拒绝彩蛋的互斥开放 C0_ContractDecision.yarn:接受/拒绝二次确认后各写入一次 StoryDatac0_public_disclosurec0_refusal_ending c0_contract_decision_checkpoint;回滚后恢复为 0 Yarn 已使用StoryData 待配置

Chapter 1 及以后

尚未开始登记。未来变量在所属场景卡批准后,按首次写入的剧情顺序添加到对应 Chapter 小节;不得提前创建占位 Key。

七、当前变量详细说明

c0_contract_route

叙事意义

该变量只表达曦是否接受神的契约,是 Chapter 0 当前唯一正式剧情变量:

叙事状态 可进入 Block 必须 Forbidden 的 Block
0 尚未作出选择 c0_contract_decision 无;两个后续均保持 Locked
1 接受契约 c0_public_disclosure c0_refusal_ending
2 拒绝契约 c0_refusal_ending c0_public_disclosure

StoryData Initial Variable

Key: c0_contract_route
Type: Int
Default: 0

Yarn 写入

接受二次确认以后:

<<set_int "c0_contract_route" 1>>

拒绝二次确认以后:

<<set_int "c0_contract_route" 2>>

不得在 C0-S01、C0-S02 或玩家尚未完成二次确认时提前写入路线值。

StoryData 条件

c0_public_disclosure

Unlock Condition: c0_contract_route == 1
Forbidden Condition: c0_contract_route == 2

c0_refusal_ending

Unlock Condition: c0_contract_route == 2
Forbidden Condition: c0_contract_route == 1

回滚行为

Timeline Marker c0_contract_decision_checkpoint 锚定 c0_contract_decision,保存进入抉择以前的快照。玩家从任一路线回滚后:

  • c0_contract_route 恢复为 0
  • 接受/拒绝选项记忆被清除;
  • 该列及右侧 Block 完成状态被恢复;
  • 两个互斥后续重新按未选择状态计算。

八、新增变量登记模板

未来新增变量时,先在所属场景卡确认叙事必要性,再复制以下模板到相应 Chapter 小节,并插入正确的剧情位置:

| `C?-???` | `C?-S??` 场景名 | `c?_stable_key` | `Bool/Int/Float/String` | 默认值 | 合法值/范围 | 一句话语义 | 首次写入 Yarn/Node | Yarn/StoryData/Helper 读取位置 | 最近相关 Marker | Planned/Active/Deprecated |

同时补充详细说明:

### `c?_stable_key`

- 叙事意义:
- 为什么不能使用现有变量或选项记忆:
- StoryData Initial Variable
- 首次写入时机:
- 所有合法值:
- Yarn 读取:
- StoryData UnlockForbidden
- Helper 条件:
- Timeline 回滚预期:
- 兼容/迁移要求:

九、变量新增检查清单

  • 变量确实需要跨 Node、跨 TextBlock 或驱动 StoryDataHelper单纯控制同一 Node 内一句台词时不滥用持久变量。
  • Key 使用正确章节前缀和 snake_case。
  • 没有与既有变量表达重复语义。
  • 类型与默认值已经在场景卡和 StoryData 中明确。
  • 所有合法值均有解释,没有未定义的魔法数字。
  • Yarn 只使用项目 set_*get_*add_* 接口。
  • 写入发生在玩家真正确认以后,不会因预览选项提前改变路线。
  • 互斥 Block 同时配置 Unlock 和 Forbidden。
  • Back 中断与 Timeline 回滚行为已经说明。
  • 不把 Localization Key、Unlock Key、Block ID 或 Option Memory 错记为剧情变量。
  • 变量进入正式存档后,任何重命名都配套 migration。
  • 本登记表中的剧情顺序与正式场景卡、Yarn 和 StoryData 一致。

十、维护流程

  1. 前置信息讨论:判断是否真的需要持久变量。
  2. 场景卡阶段:确定 Key、类型、默认值、合法值、首次写入点和回滚预期。
  3. 场景卡批准后:立即把变量按剧情顺序登记到本文档。
  4. Yarn 编写阶段:严格使用登记 Key如发现语义不足返回场景卡讨论不在脚本中临时创造近义变量。
  5. StoryData 集成阶段:配置 Initial Variable、UnlockForbiddenHelper 条件,并把登记状态更新为 Active
  6. 回归测试阶段:验证新档、对话 Back、已完成 TextBlock 回顾、互斥路线和 Timeline 回滚。
  7. 发布后修改:任何 Key、类型或语义变更都必须登记 migration 与版本影响。