This commit is contained in:
SoulliesOfficial
2026-07-24 03:43:11 -04:00
parent 48e7364981
commit fe00ecfcc7
90 changed files with 9610 additions and 461 deletions

View File

@@ -0,0 +1,231 @@
# ichni Official 剧情变量登记表
> 状态:**长期维护文档**
> 适用范围:`ichni Official` 全部章节的正式剧情变量。
> 维护原则:每当场景卡批准新增变量时,必须按照变量在剧情中**首次写入的顺序**登记;不得等到 Yarn 或 StoryData 已大量使用后再补记。
> 当前内容只登记已经确认并实际进入正式 Yarn 的变量,不预先虚构未来章节的变量。
## 一、文档用途
本登记表是剧情作者、Yarn 编写者、StoryData 配置人员、本地化人员与程序员共同使用的变量来源。它用于回答:
- 变量的稳定 Key 是什么;
- 变量首次出现在哪个 Chapter、场景、TextBlock 与 Yarn 文件;
- 变量使用何种类型和默认值;
- 每个合法取值代表什么;
- 哪些 Yarn Node 写入或读取变量;
- 哪些 StoryData Block 使用变量作为 UnlockForbidden 条件;
- Timeline 回滚会怎样处理该变量;
- 变量当前处于计划、已使用、废弃还是迁移状态。
本登记表不替代场景卡或 StoryData。场景卡解释叙事意图StoryData 保存运行时初始值与条件;本登记表负责让所有使用者对同一个 Key 保持一致理解。
## 二、纳入与排除范围
### 必须登记
- 通过 `set_bool``set_int``set_float``set_string` 写入的章节剧情变量;
- 通过 `add_int``add_float` 累积的章节数值;
- 被 Yarn `if`、StoryData `Unlock 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 稳定性
变量进入正式存档以后不得只为了“更好看”而重命名。确需改名时:
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/""` 掩盖漏配。
其它可用接口:
```yarn
<<remove_variable "key">>
<<if has_variable("key")>>
// 该 Key 存在已保存值,或已在 StoryData Initial Variables 中定义。
<<endif>>
```
`has_variable("key")` 会把 StoryData Initial Variable 也视为存在。由于正式变量都应显式配置初始值,它通常会从章节开始便返回 `true`,不能用于判断“玩家是否已经在剧情中写入过这个变量”。若确实需要记录事件是否发生,应创建语义明确的 Bool而不是依赖变量是否存在。
正式剧情不得使用:
```yarn
<<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
```text
Key: c0_contract_route
Type: Int
Default: 0
```
#### Yarn 写入
接受二次确认以后:
```yarn
<<set_int "c0_contract_route" 1>>
```
拒绝二次确认以后:
```yarn
<<set_int "c0_contract_route" 2>>
```
不得在 C0-S01、C0-S02 或玩家尚未完成二次确认时提前写入路线值。
#### StoryData 条件
`c0_public_disclosure`
```text
Unlock Condition: c0_contract_route == 1
Forbidden Condition: c0_contract_route == 2
```
`c0_refusal_ending`
```text
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 小节,并插入正确的剧情位置:
```markdown
| `C?-???` | `C?-S??` 场景名 | `c?_stable_key` | `Bool/Int/Float/String` | 默认值 | 合法值/范围 | 一句话语义 | 首次写入 Yarn/Node | Yarn/StoryData/Helper 读取位置 | 最近相关 Marker | Planned/Active/Deprecated |
```
同时补充详细说明:
```markdown
### `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 与版本影响。