Files
ttrpg-tools/src/doc-entries/journal-stat.md
T
hypercross ef71a43f0a feat: add stat-modifiers role for automatic stat generation
Introduces a new `stat-modifiers` CSV role that simplifies the
creation of template stats and their associated modifier stats.
A single CSV block now automatically generates:
- A template stat definition.
- Multiple modifier stat definitions (prefixed with the template ID).
- The corresponding template table.

This reduces the need for manual YAML definitions for every
modifier associated with a template.
2026-07-09 11:16:39 +08:00

8.6 KiB
Raw Blame History

tag, icon, title, description, syntax, props
tag icon title description syntax props
journal-stat 📊 属性系统 在文档中定义属性,通过命令设置/删除/掷骰,在面板中查看属性表。 ```yaml role=stat
name type desc
定义文件 在任意 .md 文档中使用 ```yaml role=stat 或 ```csv role=stat 代码块定义属性
name type desc
命令 /stat set key=value | /stat del key | /stat roll key
name type desc
属性类型 number, string, enum, modifier, derived, template
name type desc
权限 GM 可修改所有属性,玩家只能修改自己的属性

概述

属性系统允许你在文档中定义角色属性,通过命令设置和掷骰, 并在 Journal 面板的属性视图中查看当前值。

属性分为两层:

  • 定义Schema):在 markdown 文档的 ```yaml role=stat```csv role=stat 代码块中定义
  • State):通过 /stat set/del/roll 命令在游戏过程中动态修改

代码块语法

所有属性相关代码块使用统一的属性语法:

```lang role=xxx [id=xxx]
属性 说明 示例
lang 代码语言 yaml, csv
role 块用途 stat(属性定义), stat-template(模板表)
id 引用标识 模板名称,如 id=年龄

代码块默认会被剥离(不渲染到页面),仅用于数据提取。 如需保留为可见代码块,添加 as=codeblock

属性定义

支持两种格式:YAML(适合复杂属性)和 CSV(适合同质列表)。

YAML 格式

- key: strength
  scope: player
  label: "力量"
  type: number
  default: 10

- key: str_mod
  scope: player
  label: "力量调整"
  type: modifier
  target: strength

- key: attack
  scope: player
  label: "近战攻击"
  type: number
  default: 0
  roll: "1d20 + attack"

- key: loot
  scope: player
  label: "战利品"
  type: enum
  options:
    - 金币 x10
    - 魔法药水
    - 破旧长剑

- key: hp_max
  scope: player
  label: "最大生命值"
  type: derived
  formula: "strength * 2 + 10"

- key: notes
  scope: player
  label: "备注"
  type: string

- key: weather
  scope: global
  label: "天气"
  type: enum
  options:
    - 晴天
    - 阴天
    - 雨天
    - 暴风雨

CSV 格式

key,label,type,roll
mind,心智,number,2d10+20
heart,心灵,number,2d10+20
strength,力量,number,2d10+20
speed,速度,number,2d10+20

CSV 列说明:

必填 默认值 说明
key 属性标识符
label key 的值 显示名称
type number 属性类型
scope player playerglobal
default 默认值
roll 掷骰公式
target modifier 的目标 key
template template 类型引用的模板 id
formula derived 的计算公式
options enum 选项,用 | 分隔

属性类型

类型 说明 支持掷骰
number 数值,可声明 roll 公式
string 自由文本
enum 枚举选项,掷骰随机选择
modifier 修饰值,自动加到 target 属性上
derived 通过公式从其他属性计算
template 查表属性,掷骰匹配范围并应用修饰符

关键字段说明

  • key:唯一标识符。使用纯名字(如 strength),不用加玩家前缀
  • scopeplayerglobalplayer 表示每个玩家各自独立的值,运行时 key 为 玩家名:strengthglobal 表示所有玩家共享
  • label:在属性视图中显示的名称
  • default:默认值,在未通过命令设置时使用
  • roll:掷骰公式(number 类型),支持引用其他属性值(bare key,自动同 scope 解析)
  • targetmodifier 类型的目标属性 key
  • optionsenum 类型的选项列表,YAML 支持多行 - value 语法,CSV 用 | 分隔
  • formuladerived 类型的计算公式,支持 + - * / floor() ceil() round()
  • templatetemplate 类型引用的模板 id(对应 id=xxx 的 stat-template 块)

作用域

scope: player 的属性在运行时自动加上玩家名前缀。Alice 连接时,strength 的实际 key 是 alice:strength

在公式(rollformula)和 target 中,使用 bare key 即可,系统自动在相同 scope 内查找:

- key: attack
  scope: player
  roll: "1d20 + attack"         # attack 自动解析为 alice:attack

- key: str_mod
  scope: player
  target: strength              # 自动解析为 alice:strength

命令

所有命令在 Journal 输入框中输入,前缀为 /stat

命令 示例 说明
/stat set key=value /stat set strength=16 设置属性值
/stat del key /stat del strength 删除属性值,恢复默认
/stat roll key /stat roll attack 掷骰并发布结果

掷骰行为

  • number + roll:解析公式中的属性引用,掷骰,结果写入属性值
  • enum:从选项列表中随机选择一项
  • derived + formula:计算公式,结果写入属性值
  • template:掷模板头部骰子,匹配范围,应用修饰符

例如 /stat roll attack

  1. 在当前玩家 scope 下查找 attack 的定义
  2. 解析 roll 公式 1d20 + attack,将 attack 替换为当前值(含修饰符)→ 1d20 + 3
  3. 掷骰 → 15
  4. 15 写入 alice:attack,同步到所有客户端

属性视图

在 Journal 面板顶部点击 属性 标签切换视图:

  • 属性按 scope 分组(全局 + 玩家)
  • 显示属性名、当前值、默认值
  • 修饰符自动合并显示
  • 可掷骰的行显示 🎲 按钮

权限

  • GM:可修改所有属性
  • 玩家:只能修改 scope: player 的属性
  • 观察者:不能修改任何属性

修饰符(modifier

修饰符自动加到 target 属性上:

- key: strength
  scope: player
  type: number
  default: 10

- key: str_mod
  scope: player
  type: modifier
  target: strength

/stat set str_mod=3 后,strength 的计算值为 10 + 3 = 13。 多个修饰符指向同一目标时累加。

派生属性(derived

通过公式从其他属性计算:

- key: hp_max
  scope: player
  type: derived
  formula: "strength * 2 + 10"

公式引用其他属性时自动使用计算值(含修饰符)。 支持的函数:floor(x), ceil(x), round(x)

模板属性(template

模板属性用于查表掷骰(年龄表、职业表等)。

方式一:stat-modifiers(推荐)

一个代码块同时生成模板 stat 和修饰符 stat defs

1d10,label,mind,heart,strength,speed
1-3,青少年,-10,+20,,
4-7,成年,,-10,,+20
8-9,老年,,+20,-10,
10,换躯者,,,+30,-10

这会自动生成:

  • agetype: template, template: 年龄)
  • age_mindtype: modifier, target: mind
  • age_hearttype: modifier, target: heart
  • age_strengthtype: modifier, target: strength
  • age_speedtype: modifier, target: speed

修饰符键名规则:{id}_{列名},目标为列名本身。

方式二:手动定义

分别定义模板表和修饰符 stat

1d10,label,age_mind,age_heart,age_strength,age_speed
1-3,青少年,-10,+20,,
4-7,成年,,-10,,+20
8-9,老年,,+20,-10,
10,换躯者,,,+30,-10
- key: age_mind
  type: modifier
  target: mind
- key: age_heart
  type: modifier
  target: heart
- key: age
  type: template
  template: 年龄

使用

使用

  • /stat roll age — 掷 1d10,匹配范围,应用修饰符
  • /stat set age=换躯者 — 直接设置,同样应用修饰符

/stat roll age/stat set age=青少年 时:

  1. 发布 set age=青少年
  2. 同时发布 set alice:age_mind=-10set alice:age_heart=+20

修饰符值中的 +/- 前缀表示相对调整,基于当前值计算。

模板表语法

  • 第一列(header:骰子表达式,如 1d10
  • 第一列(rows:匹配范围,1-3(区间)、4(精确)、1-3,5(多个)
  • label:显示名称
  • 其余列:修饰符键名,值为变化量(+加、-减、空不修改)

掷骰公式中的属性引用

roll 字段中的标识符自动替换为当前属性值:

- key: attack
  scope: player
  type: number
  default: 0
  roll: "1d20 + attack + str_mod"