跳到主要内容

字段建模与计算选择

决定事实归属,选择原始字段、类型公式、文档覆盖和关联揭露。

本页目录

为模组机制设计字段时,先判断每个值是事实、派生结果还是作者配置,再选择保存和计算方式。本页说明选择方法及常见错误;语法和校验约束见 文档类型与字段及计算字段。下面的字段名、数值和公式均为原创示例,不代表平台内置规则。

先决定事实来源

新增或修改关键字段时,说明值从哪里来、由谁修改、何时变化,以及会影响哪些展示或机制。需要时可在回复或已有说明中列一张简表,不必另建文件。

需求 优先方式 选择边界
当前生命、余量、关系、已发生事件 普通原始字段,需要游戏中变化时设置 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 则描述引用定义所管理的持有状态;实例不接受自己的公式覆盖。具体配置见文档类型与字段,计算上下文见计算字段。