10 KiB
ichni Official 剧情变量登记表
状态:长期维护文档
适用范围:ichni Official全部章节的正式剧情变量。
维护原则:每当场景卡批准新增变量时,必须按照变量在剧情中首次写入的顺序登记;不得等到 Yarn 或 StoryData 已大量使用后再补记。
当前内容只登记已经确认并实际进入正式 Yarn 的变量,不预先虚构未来章节的变量。
一、文档用途
本登记表是剧情作者、Yarn 编写者、StoryData 配置人员、本地化人员与程序员共同使用的变量来源。它用于回答:
- 变量的稳定 Key 是什么;
- 变量首次出现在哪个 Chapter、场景、TextBlock 与 Yarn 文件;
- 变量使用何种类型和默认值;
- 每个合法取值代表什么;
- 哪些 Yarn Node 写入或读取变量;
- 哪些 StoryData Block 使用变量作为 Unlock/Forbidden 条件;
- Timeline 回滚会怎样处理该变量;
- 变量当前处于计划、已使用、废弃还是迁移状态。
本登记表不替代场景卡或 StoryData。场景卡解释叙事意图,StoryData 保存运行时初始值与条件;本登记表负责让所有使用者对同一个 Key 保持一致理解。
二、纳入与排除范围
必须登记
- 通过
set_bool、set_int、set_float或set_string写入的章节剧情变量; - 通过
add_int或add_float累积的章节数值; - 被 Yarn
if、StoryDataUnlock Condition、Forbidden 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;不得使用value1、temp、flag等含义不明的 Key。
一项语义只保留一个变量
不要同时创建 c0_contract_route 和 c0_contract_accepted 来表达同一选择。能够用一个枚举式 Int 完整表达的互斥路线,不再增加重复 Bool。
Key 稳定性
变量进入正式存档以后不得只为了“更好看”而重命名。确需改名时:
- 在本表把旧 Key 标记为
Deprecated; - 登记新 Key、迁移规则和首次生效版本;
- 完成 Story Save migration;
- 同步修改 Yarn、StoryData Conditions、Helper 条件和测试;
- 确认旧存档迁移后再停止读取旧 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:接受/拒绝二次确认后各写入一次 |
StoryData:c0_public_disclosure、c0_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 Unlock/Forbidden:
- Helper 条件:
- Timeline 回滚预期:
- 兼容/迁移要求:
九、变量新增检查清单
- 变量确实需要跨 Node、跨 TextBlock 或驱动 StoryData/Helper;单纯控制同一 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 一致。
十、维护流程
- 前置信息讨论:判断是否真的需要持久变量。
- 场景卡阶段:确定 Key、类型、默认值、合法值、首次写入点和回滚预期。
- 场景卡批准后:立即把变量按剧情顺序登记到本文档。
- Yarn 编写阶段:严格使用登记 Key;如发现语义不足,返回场景卡讨论,不在脚本中临时创造近义变量。
- StoryData 集成阶段:配置 Initial Variable、Unlock/Forbidden/Helper 条件,并把登记状态更新为
Active。 - 回归测试阶段:验证新档、对话 Back、已完成 TextBlock 回顾、互斥路线和 Timeline 回滚。
- 发布后修改:任何 Key、类型或语义变更都必须登记 migration 与版本影响。