ttrpg-tools/src/doc-entries/journal-stat.md

244 lines
6.8 KiB
Markdown
Raw Normal View History

---
tag: journal-stat
icon: 📊
title: 属性系统
description: 在文档中定义属性,通过命令设置/删除/掷骰,在面板中查看属性表。
syntax: '```yaml role=stat'
props:
- name: 定义文件
type: —
desc: 在任意 .md 文档中使用 yaml role=stat 代码块定义属性
- name: 命令
type: —
desc: /stat set key=value | /stat del key | /stat roll key
- name: 属性类型
type: —
desc: number, string, enum, modifier, derived
- name: 权限
type: —
desc: GM 可修改所有属性,玩家只能修改自己的属性 (玩家名:xxx)
---
## 概述
属性系统允许你在文档中定义角色属性(如力量、生命值、技能等),
通过命令设置和掷骰,并在 Journal 面板的属性视图中查看当前值。
属性分为两层:
- **定义**Schema在 markdown 文档的 ` ```yaml role=stat ` 代码块中定义
- **值**State通过 `/stat set/del/roll` 命令在游戏过程中动态修改
## 属性类型
| 类型 | 说明 | 支持掷骰 |
|---|---|---|
| `number` | 数值,可声明 `roll` 公式 | ✅ |
| `string` | 自由文本 | ❌ |
| `enum` | 枚举选项,掷骰随机选择 | ✅ |
| `modifier` | 修饰值,自动加到 `target` 属性上 | ❌ |
| `derived` | 通过公式从其他属性计算 | ✅ |
## 属性定义语法
支持两种格式:**YAML**(适合复杂属性)和 **CSV**(适合同质列表)。
### YAML 格式
`.md` 文档中插入 ` ```yaml role=stat ` 代码块:
```yaml role=stat
- 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 格式
对于同质属性列表(如多个 `number` 类型的属性CSV 更紧凑。
插入 ` ```csv role=stat ` 代码块:
```csv role=stat
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` | `player``global` |
| `default` | — | — | 默认值 |
| `roll` | — | — | 掷骰公式 |
| `target` | — | — | modifier 的目标 key |
| `formula` | — | — | derived 的计算公式 |
| `options` | — | — | enum 选项,用 `\|` 分隔 |
示例 — enum 属性:
```csv role=stat
key,label,type,options
weather,天气,enum,晴天\|阴天\|雨天\|暴风雨
```
### 关键语法说明
- **`key`**:唯一标识符。使用纯名字(如 `strength`),不用加玩家前缀
- **`scope`**`player` 或 `global`。`player` 表示每个玩家各自独立的值,运行时 key 为 `玩家名:strength``global` 表示所有玩家共享
- **`label`**:在属性视图中显示的名称
- **`type`**:属性类型(见上表)
- **`default`**:默认值,在未通过命令设置时使用
- **`roll`**:掷骰公式(仅 `number` 类型),支持引用其他属性值(使用 bare key自动同 scope 解析)
- **`target`**`modifier` 类型的目标属性 keybare key同 scope 内解析)
- **`options`**`enum` 类型的选项列表,支持多行 `- value` 语法
- **`formula`**`derived` 类型的计算公式,支持 `+ - * / floor() ceil() round()`,属性引用使用 bare key
### 作用域说明
`scope: player` 的属性在运行时会自动加上玩家名前缀。例如 Alice 连接时,`strength` 的实际 key 是 `alice:strength`
在公式(`roll`、`formula`)和 `target` 中,使用 bare key 即可,系统会自动在相同 scope 内查找:
```yaml role=stat
- key: attack
scope: player
roll: "1d20 + attack" # attack 自动解析为 alice:attack
- key: str_mod
scope: player
target: strength # 自动解析为 alice:strength
```
## 命令
所有命令在 Journal 输入框中输入,前缀为 `/stat`。命令中使用 bare key
| 命令 | 示例 | 说明 |
|---|---|---|
| `/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`**:计算公式,结果写入属性值
例如 `/stat roll attack` 会:
1. 在当前玩家 scope 下查找 `attack` 的定义
2. 解析 `roll` 公式 `1d20 + attack`,将 `attack` 替换为当前值(含修饰符)→ 如 `1d20 + 3`
3. 掷骰 → 如结果 `15`
4.`15` 写入 `alice:attack`,同步到所有连接的客户端
## 属性视图
在 Journal 面板顶部点击 **属性** 标签切换视图:
- 属性按 scope 分组(全局属性 + 玩家属性)
- 显示属性名、当前值、默认值
- 修饰符自动合并显示(`strength = 16` 时,`str_mod` 自动加到 `strength` 上)
- 有掷骰属性的行显示 🎲 按钮,点击可快速掷骰
## 权限
- **GM**:可以修改所有属性
- **玩家**:只能修改自己 scope 下的属性(`scope: player` 的属性)
- **观察者**:不能修改任何属性
## 修饰符modifier详解
修饰符类型的属性会自动加到其 `target` 属性上:
```yaml role=stat
- 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详解
派生属性通过公式从其他属性计算:
```yaml role=stat
- key: hp_max
scope: player
type: derived
formula: "strength * 2 + 10"
```
公式中引用其他属性时,会自动使用其计算值(包含修饰符)。
支持的函数:`floor(x)`, `ceil(x)`, `round(x)`
## 掷骰公式中的属性引用
`roll` 字段中的标识符会自动替换为当前属性值:
```yaml role=stat
- key: attack
scope: player
type: number
default: 0
roll: "1d20 + attack + str_mod"
```
`/stat roll alice:attack` 时,`alice:attack` 和 `alice:str_mod` 会被替换为当前值后再掷骰。