字段建模与计算选择
决定事实归属,选择原始字段、类型公式、文档覆盖和关联揭露。
本页目录
为模组机制设计字段时,先判断每个值是事实、派生结果还是作者配置,再选择保存和计算方式。本页说明选择方法及常见错误;语法和校验约束见 文档类型与字段及计算字段。下面的字段名、数值和公式均为原创示例,不代表平台内置规则。
先决定事实来源
新增或修改关键字段时,说明值从哪里来、由谁修改、何时变化,以及会影响哪些展示或机制。需要时可在回复或已有说明中列一张简表,不必另建文件。
| 需求 | 优先方式 | 选择边界 |
|---|---|---|
| 当前生命、余量、关系、已发生事件 | 普通原始字段,需要游戏中变化时设置 mutable |
这些是需保存的事实,不能靠重读公式重新生成 |
| 固定描述、基础参数、原始正文与图片 | 普通只读原值 | 不用恒定公式代替已有数据 |
| 同一类型共有的上限、阈值、汇总或显示规则 | 类型字段的 compute |
公式读取当前事实,派生结果不另存一份 |
| 同一规则仅基础值、加成或系数不同 | 文档参数与共用 compute |
优先改变数据,不为每份文档复制公式 |
| 个别文档计算方法不同,但字段语义与结构一致 | 文档顶层 computed |
只覆盖例外字段,不改其他同类型文档或复制整套定义 |
| 一组实体具有不同字段含义、结构或职责 | 合适的独立文档类型 | 不用大量局部公式掩盖类型建模差异,也不为一件特殊物品单独建类型 |
| 读取另一实体的当前数据 | 声明 reference 并用 load() |
不把引用路径硬编码进公式或复制目标当前值;历史快照是另一个明确事实 |
| 按状态隐藏某项内容 | 计算字段返回 null 并启用 hideWhenEmpty,或使用主持字段 |
控制该字段,不自动隐藏其他摘要、图片或手写秘密 |
| 整份资料暂不进入玩家目录 | 类型顶层 displayWhen |
控制整份文档展示,不代替字段权限或删除真实状态 |
| 只改变排列、标签或显示控件 | 布局配置 | 不为布局便利复制同一事实,不把布局当作修改权限 |
类型 compute:共用规则
规则对同类型文档成立时,把公式放在 .types/类型.fields.* 的相应字段中。例如各角色按相同规则从属性计算生命上限,各技能条目从当前值计算困难阈值,物品按同一发现状态显示名称。
当前生命 hp 保存普通可修改值;上限 max_hp 可按规则派生。上限变化不等于自动治疗,治疗、伤害或钳制当前值需要明确结算。若选定规则中上限本身是独立掷出的结果,则保存原始上限,不套用别的系统的公式。
纯派生字段省略原值;需要显示完整原始正文、名称或图片时可以保存同名原值,再由公式通过 $raw 读取。类型公式字段不标记 required 或 mutable,实际可变输入另用普通字段。临时效果、永久成长和手动修正保存为相应状态,再由公式组合。
文档 computed:公式例外
仅当前文档采用不同计算方法、且仍符合该字段含义时使用顶层 computed。它会替换当前文档中该字段的公式,不修改类型定义。计算结果不会再传给类型默认公式,也没有“调用默认公式”的接口。
先排除只是数据差异的情况。例如所有武器都按“基础攻击加修正”计算时,基础攻击不同或某件武器多 5 点都可写成参数,共用公式即可。只有少数武器的计算规则不同时,才需要覆盖公式。若相同例外在多份资料反复出现,可以考虑用含义明确的规则参数、共用条件或独立类型来表达;避免按文档文件名判断特殊规则。
完整类型示例 .types/weapon.fields.json:
{ "fields": { "baseAttack": { "type": "number", "required": true }, "bonus": { "type": "number", "mutable": true }, "attack": { "type": "number", "compute": "$self.baseAttack + ($self.bonus ?? 0)" } }}两份文档示例:
{ "name": "铁剑", "baseAttack": 10, "bonus": 5}{ "name": "夜刃", "baseAttack": 10, "bonus": 0, "computed": { "attack": "$self.baseAttack * 2 + ($self.bonus ?? 0)" }}铁剑沿用共用公式,结果为 15;夜刃采用自己的倍增规则,结果为 20。主持将夜刃的普通 bonus 改为 5 后,结果为 25。若倍增成为同类武器的常见规则,可改用明确的系数参数和共用公式。示例的 bonus 存在物品上,实际模组中,如果加成只属于某个持有者,应保存在该持有者的文档或持有状态中。
已有冒险不能通过 update 修改 computed,也不能直接更新 attack。动态加成和玩家取得的新能力应通过普通状态表达;作者调整公式时,应修改源配置,再由开发者在新冒险或同步模组后的测试冒险中确认结果。覆盖目标、点路径、容器、保留配置与权限要求见文档公式覆盖。
同名原值与独立来源字段
公式只改变原始资料的显示时,优先保留同名原值:
{ "fields": { "revealed": { "type": "boolean", "mutable": true, "visibility": "gm" }, "name": { "type": "text", "compute": "$self.revealed ? $raw.name : '陌生人'" }, "body": { "type": "text", "compute": "$self.revealed ? $raw.body : null" } }}此例仅适用于揭露后整段原始名称与正文都可公开的资料。名称公式用 $raw.name 读取自身原值;用 $self.name 读取自身结果会形成循环。Markdown 原始正文继续放在 frontmatter 后,不必搬到新建的 source_body。
当“主持真相”和“玩家当前观察”是不同事实时,才设置不同字段。例如完整地点攻略保留在原始正文中,玩家看到的描述存入可修改的主持字段 known_text,公开 body 的公式读取它。作者应在规则中约定:环境变化后,主持更新当前观察记录,而不只是翻转发现标记。名称、已取得的证据、推断含义和可展示图片可以有不同揭露条件,不能因到达地点就公开全部真相。
同名计算字段的原值不能作为运行时可修改目标。需要不断更新的观察内容、手动覆盖或当前状态必须有独立普通字段;作者修改原始正文与主持更新本局观察记录是不同操作。独立字段应对应不同事实或确实需要修改的输入,避免只为公式读取而复制所有 name、body、image。
关联、继承与独立发现
确实共享上级状态时,用声明引用和 load() 派生。例如规则明确“场景揭露后,关联物品公开”,物品可以从场景状态计算 revealed,无需再保存一份需要同步的揭露标记。
若物品必须单独搜索、机关尚未触发或线索含义要另外查明,则保存独立发现事实;派生可见条件可组合父级状态与独立事实。选择依据是游戏中的因果关系,不是为了少写几个字段。玩家仅看见房间,不代表发现里面所有实体。
引用目标提供当前数据,load() 使用目标自己的有效公式,包含目标的文档覆盖。公式的引用必须来自当前文档原始数据中已声明且类型匹配的引用;正文双链和临时拼接路径不是计算依赖。若需要记录某次行动时的旧数值,则它是明确的历史结果,保存该结果并说明记录时点。
物品文档保存物品定义;角色的持有状态保存数量、余量或持有者专属效果。普通数据、共享定义与个人状态分别修改,不能为一人扣除消耗而改掉所有角色引用的物品基础值。
表达式与修改边界
$raw是原始文档根,读取公式字段同名原值时使用它;嵌套条目中的$raw仍是文档根。$self是整份文档的计算视图;$item是公式所属的当前对象或列表条目。列表通用阈值用$item.value,不用固定下标,也不用为每条技能复制公式。compute和computed都只读求值,不生成新骰点、推进时间、扣除资源或触发状态更新。实际骰点和已发生的耗时应建模为普通事实,并在模组规则中写清来源与记录条件。- 普通缺省输入可以用
??;不能用||把合法的 0 或false当作缺省。计算字段合法返回null时,可以用??提供默认值;hideWhenEmpty只影响展示,不传播计算失败。公式报错或返回错误类型时,实际依赖它的字段也会失效,不能用??或捕获异常恢复;默认值仍应符合规则含义。 visibility控制字段公开范围,mutable控制运行时修改,displayWhen控制文档展示。公式覆盖继续遵守字段类型和可见性,布局不赋予权限。- 需要主持在游戏中直接更新的事实必须是可修改的非计算字段。建卡写入目标也必须是非计算字段,但不要求
mutable = true,可以填写只读初值;计算父字段下的子字段同样不能作为建卡写入目标。
实现后检查正常值、0、缺省输入、相关状态变化与揭露状态,核对类型规则和文档例外各自的结果。存在文档覆盖时至少推演一份默认文档和一份例外文档,保证例外不改变同类资料。运行真实 CLI 检查错误;玩家界面仍由开发者按手动清单确认。
物品定义管理实例状态
一件物品需要特殊状态时,先区分共用定义和实际持有状态。固定占格、性质与实例公式由物品定义拥有;当前燃料、剩余次数、开启状态保存在持有者行装条目的 state。角色类型只声明引用、数量、位置及实例绑定,新增特殊物品无需追加角色专属字段。
使用顶层 instance.fields 定义这件物品的实例字段,instance.display 定义摘要。相同引用的多个条目共享规则并保留各自状态。必填初值必须显式提供;计算结果不保存,不用角色字段或额外事件记录重复维护同一份资源。转交移动完整原始实例,重新读取和恢复不能补充资源。
类型公式负责同类型文档的共用规则,文档 computed 负责整份文档的公式例外,instance 则描述引用定义所管理的持有状态;实例不接受自己的公式覆盖。具体配置见文档类型与字段,计算上下文见计算字段。