diff --git a/src/components/journal-doc-data.ts b/src/components/journal-doc-data.ts index 4e2126c..29e0e02 100644 --- a/src/components/journal-doc-data.ts +++ b/src/components/journal-doc-data.ts @@ -43,9 +43,19 @@ function parseEntry(raw: string): JournalDocEntry | null { import journalGmRaw from "../doc-entries/journal-gm.md"; import journalPlayerRaw from "../doc-entries/journal-player.md"; -import journalStatRaw from "../doc-entries/journal-stat.md"; +import journalSetRaw from "../doc-entries/journal-set.md"; +import journalRollRaw from "../doc-entries/journal-roll.md"; +import journalSparkRaw from "../doc-entries/journal-spark.md"; +import journalLinkRaw from "../doc-entries/journal-link.md"; -const rawDocuments: string[] = [journalGmRaw, journalPlayerRaw, journalStatRaw]; +const rawDocuments: string[] = [ + journalGmRaw, + journalPlayerRaw, + journalSetRaw, + journalRollRaw, + journalSparkRaw, + journalLinkRaw, +]; let _entries: JournalDocEntry[] | null = null; diff --git a/src/doc-entries/journal-link.md b/src/doc-entries/journal-link.md new file mode 100644 index 0000000..db58b12 --- /dev/null +++ b/src/doc-entries/journal-link.md @@ -0,0 +1,39 @@ +--- +tag: journal-link +icon: 🔗 +title: 链接命令 +description: 在 Journal 中发送可点击的文档链接,可指向特定章节。 +syntax: '/link 路径#章节' +props: + - name: 路径 + type: string + desc: 文档路径(不含 .md 扩展名) + - name: 章节 + type: string + desc: 可选,文档中的章节标题 +--- + +## 概述 + +`/link` 命令用于在 Journal 流中发送文档链接,点击后可在文章区域打开对应文档。 + +## 语法 + +``` +/link 路径 +/link 路径#章节 +``` + +## 示例 + +``` +/link rules/combat +/link rules/combat#伤害计算 +/link npc/商人 +``` + +## 权限 + +- **GM**:可使用 +- **玩家**:不可使用 +- **观察者**:不可使用 \ No newline at end of file diff --git a/src/doc-entries/journal-roll.md b/src/doc-entries/journal-roll.md new file mode 100644 index 0000000..aca6ca1 --- /dev/null +++ b/src/doc-entries/journal-roll.md @@ -0,0 +1,47 @@ +--- +tag: journal-roll +icon: 🎲 +title: 掷骰命令 +description: 在 Journal 中发送掷骰结果,支持标准骰子表达式。 +syntax: '/roll 骰子表达式' +props: + - name: 骰子表达式 + type: string + desc: 标准骰子表达式,如 3d6、2d8kh1、d20+5 +--- + +## 概述 + +`/roll` 命令用于在 Journal 流中掷骰并发布结果。结果会同步到所有连接的客户端。 + +## 语法 + +``` +/roll 骰子表达式 +``` + +## 示例 + +``` +/roll d20 +/roll 3d6 +/roll 2d8kh1 +/roll 1d20+5 +/roll 4d6k3 +``` + +## 支持的骰子表达式 + +| 表达式 | 说明 | +|---|---| +| `d20` | 单个 20 面骰 | +| `3d6` | 3 个 6 面骰求和 | +| `2d8kh1` | 2 个 8 面骰保留最高 1 个 | +| `1d20+5` | 1 个 20 面骰加 5 | +| `4d6k3` | 4 个 6 面骰保留最高 3 个 | + +## 权限 + +- **GM**:可使用 +- **玩家**:不可使用 +- **观察者**:不可使用 \ No newline at end of file diff --git a/src/doc-entries/journal-set.md b/src/doc-entries/journal-set.md new file mode 100644 index 0000000..cb270ff --- /dev/null +++ b/src/doc-entries/journal-set.md @@ -0,0 +1,183 @@ +--- +tag: journal-set +icon: 🔢 +title: 变量系统 +description: 在文档中声明变量和标签,通过 /set 命令设置变量值,自动计算派生变量和标签效果。 +syntax: '```csv role=declare' +props: + - name: 定义文件 + type: — + desc: 在任意 .md 文档中使用 ```csv role=declare 代码块定义变量和标签 + - name: 命令 + type: — + desc: /set $key expression | /set $key #tag1|#tag2|#tag3 + - name: 权限 + type: — + desc: GM 和玩家均可设置变量 +--- + +## 概述 + +变量系统允许你定义数值变量和标签,通过命令设置值,系统自动计算派生变量和标签效果。 + +核心概念: +- **变量**(`$name`):存储数值或标签,通过 `/set` 命令修改 +- **标签**(`#tag`):当某个变量的值为 `#tag` 时,该标签被激活,触发相应的修饰效果 +- **声明**(`declare`):在 `role=declare` 代码块中定义派生变量和标签修饰符 + +## 代码块语法 + +```csv role=declare +tag,key,expr +,$hp,$con*5+$mod_hp +,$ac,10+$dex +#warrior,$mod_hp,20 +#warrior,$mod_str,1 +``` + +| 列 | 说明 | +|---|---| +| `tag` | 标签名(空表示普通变量声明) | +| `key` | 变量名,以 `$` 开头 | +| `expr` | 表达式,支持数字、`$var` 引用、骰子、算术、函数 | + +### 声明类型 + +**普通声明**(tag 为空):`$key` 是一个派生变量,其值由表达式计算。当依赖变量变化时自动重新计算。 + +```csv role=declare +tag,key,expr +,$hp,$con*5+$mod_hp +,$ac,10+$dex +``` + +**标签修饰符**(tag 非空):当 `#tag` 被激活时,`$key` 的当前值加上表达式的计算结果。 + +```csv role=declare +tag,key,expr +#warrior,$mod_hp,20 +#warrior,$mod_str,1 +``` + +## 表达式语法 + +支持以下表达式元素: + +| 元素 | 示例 | 说明 | +|---|---|---| +| 数字 | `10`, `3.5` | 整数或小数 | +| 变量引用 | `$str`, `$mod_hp` | 引用其他变量的值 | +| 骰子 | `3d6`, `2d8kh1` | 每次求值时重新掷骰 | +| 算术 | `+ - * /` | 四则运算 | +| 函数 | `floor(x)`, `ceil(x)`, `round(x)` | 取整函数 | +| 括号 | `(2+3)*4` | 分组 | + +变量引用必须解析为数值,不能是标签值(`#warrior`)。如果引用的变量是标签类型,求值会报错。 + +## 命令 + +所有命令在 Journal 输入框中输入: + +| 命令 | 示例 | 说明 | +|---|---|---| +| `/set $key expr` | `/set $str 16` | 设置变量为数值 | +| `/set $key #tag` | `/set $class #warrior` | 设置变量为标签 | +| `/set $key #a\|#b\|#c` | `/set $class #w\|#d\|#s` | 随机选择一个标签 | + +### 设置数值 + +``` +/set $con 14 +/set $dex 12 +``` + +设置后,依赖 `$con` 和 `$dex` 的派生变量(如 `$hp`、`$ac`)会自动重新计算。 + +### 设置标签 + +``` +/set $class #warrior +``` + +当 `$class` 设置为 `#warrior` 时: +1. `#warrior` 标签被激活 +2. 所有 `#warrior` 的修饰符生效:`$mod_hp += 20`,`$mod_str += 1` +3. 依赖这些变量的派生变量自动重新计算 + +### 随机标签 + +``` +/set $class #warrior|#druid|#sorcerer|#wizard +``` + +从给定标签中随机选择一个设置为变量值。 + +## 标签激活 + +标签的激活状态由变量的值决定: + +- 如果**任何**变量的值为 `#tag`,该标签被激活 +- 如果**没有**变量的值为 `#tag`,该标签被停用 +- 标签激活时,其修饰符**加到**目标变量上 +- 标签停用时,修饰符**从**目标变量中减去 + +一个变量只能存储一个值类型:数值或标签,不能同时存储两者。 + +## 变量视图 + +在 Journal 面板顶部点击 **变量** 标签切换视图: + +- **激活标签**:显示当前激活的标签、激活来源和修饰效果 +- **声明变量**:显示由表达式定义的派生变量及其当前值 +- **直接设置**:显示通过 `/set` 直接赋值的变量 +- **标签变量**:显示当前值为标签的变量 + +## 文档模板 + +在 markdown 文章中使用 `{{$key}}` 语法显示变量的实时值: + +``` +当前生命值:{{$hp}} +护甲等级:{{$ac}} +``` + +变量值会随着 Journal 流中的 `/set` 命令实时更新。 + +## 完整示例 + +在文档中定义: + +```csv role=declare +tag,key,expr +,$con,10 +,$dex,12 +,$hp,$con*5+$mod_hp +,$ac,10+$dex +#warrior,$mod_hp,20 +#warrior,$mod_str,1 +``` + +在 Journal 中输入: + +``` +/set $con 14 +/set $class #warrior +``` + +结果: +- `$con = 14` +- `$dex = 12` +- `$hp = 14*5 + 20 = 90` +- `$ac = 10 + 12 = 22` +- `$mod_hp = 20`(来自 `#warrior` 修饰符) +- `$mod_str = 1`(来自 `#warrior` 修饰符) + +## 循环依赖 + +系统在加载声明时检测循环依赖。如果声明之间存在循环引用(如 `$a = $b + 1`, `$b = $a + 1`),会抛出错误提示。 + +## 权限 + +- **GM**:可设置所有变量 +- **玩家**:可设置变量 +- **观察者**:不能设置变量 \ No newline at end of file diff --git a/src/doc-entries/journal-spark.md b/src/doc-entries/journal-spark.md new file mode 100644 index 0000000..f60f689 --- /dev/null +++ b/src/doc-entries/journal-spark.md @@ -0,0 +1,47 @@ +--- +tag: journal-spark +icon: 🎰 +title: 种子表命令 +description: 在 Journal 中随机生成种子表内容,用于生成随机遭遇、NPC、物品等。 +syntax: '/spark 种子表键名' +props: + - name: 种子表键名 + type: string + desc: 在文档中通过 :spark[CSV路径] 指令定义的种子表 slug +--- + +## 概述 + +`/spark` 命令用于从种子表中随机抽取一行并发布结果。种子表在 markdown 文档中通过 `:spark[CSV路径]` 指令定义。 + +## 语法 + +``` +/spark 种子表键名 +``` + +## 示例 + +``` +/spark npc +/spark encounter +/spark loot +``` + +## 种子表定义 + +种子表在文档中定义: + +``` +:spark[npc] +:spark[encounter] +:spark[loot] +``` + +CSV 文件的每一行对应种子表的一个条目,随机选取一行发布。 + +## 权限 + +- **GM**:可使用 +- **玩家**:不可使用 +- **观察者**:不可使用 \ No newline at end of file diff --git a/src/doc-entries/journal-stat.md b/src/doc-entries/journal-stat.md deleted file mode 100644 index b9ca0e2..0000000 --- a/src/doc-entries/journal-stat.md +++ /dev/null @@ -1,317 +0,0 @@ ---- -tag: journal-stat -icon: 📊 -title: 属性系统 -description: 在文档中定义属性,通过命令设置/删除/掷骰,在面板中查看属性表。 -syntax: '```yaml role=stat' -props: - - 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 格式 - -```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 格式 - -```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 | -| `template` | — | — | template 类型引用的模板 id | -| `formula` | — | — | derived 的计算公式 | -| `options` | — | — | enum 选项,用 `\|` 分隔 | - -### 属性类型 - -| 类型 | 说明 | 支持掷骰 | -|---|---|---| -| `number` | 数值,可声明 `roll` 公式 | ✅ | -| `string` | 自由文本 | ❌ | -| `enum` | 枚举选项,掷骰随机选择 | ✅ | -| `modifier` | 修饰值,自动加到 `target` 属性上 | ❌ | -| `derived` | 通过公式从其他属性计算 | ✅ | -| `template` | 查表属性,掷骰匹配范围并应用修饰符 | ✅ | - -### 关键字段说明 - -- **`key`**:唯一标识符。使用纯名字(如 `strength`),不用加玩家前缀 -- **`scope`**:`player` 或 `global`。`player` 表示每个玩家各自独立的值,运行时 key 为 `玩家名:strength`;`global` 表示所有玩家共享 -- **`label`**:在属性视图中显示的名称 -- **`default`**:默认值,在未通过命令设置时使用 -- **`roll`**:掷骰公式(`number` 类型),支持引用其他属性值(bare key,自动同 scope 解析) -- **`target`**:`modifier` 类型的目标属性 key -- **`options`**:`enum` 类型的选项列表,YAML 支持多行 `- value` 语法,CSV 用 `|` 分隔 -- **`formula`**:`derived` 类型的计算公式,支持 `+ - * / floor() ceil() round()` -- **`template`**:`template` 类型引用的模板 id(对应 `id=xxx` 的 stat-template 块) - -### 作用域 - -`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`: - -| 命令 | 示例 | 说明 | -|---|---|---| -| `/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` 属性上: - -```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)`。 - -## 模板属性(template) - -模板属性用于查表掷骰(年龄表、职业表等)。 - -### 方式一:stat-modifiers(推荐) - -一个代码块同时生成模板 stat 和修饰符 stat defs: - -```csv id=年龄 role=stat-modifiers -1d10,label,mind,heart,strength,speed -1-3,青少年,-10,+20,, -4-7,成年,,-10,,+20 -8-9,老年,,+20,-10, -10,换躯者,,,+30,-10 -``` - -这会自动生成: -- `age`(type: template, template: 年龄) -- `age_mind`(type: modifier, target: mind) -- `age_heart`(type: modifier, target: heart) -- `age_strength`(type: modifier, target: strength) -- `age_speed`(type: modifier, target: speed) - -修饰符键名规则:`{id}_{列名}`,目标为列名本身。 - -### 方式二:手动定义 - -分别定义模板表和修饰符 stat: - -```csv id=年龄 role=stat-template -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 -``` - -```yaml role=stat -- 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=-10`、`set alice:age_heart=+20` 等 - -修饰符值中的 `+`/`-` 前缀表示相对调整,基于当前值计算。 - -### 模板表语法 - -- **第一列(header)**:骰子表达式,如 `1d10` -- **第一列(rows)**:匹配范围,`1-3`(区间)、`4`(精确)、`1-3,5`(多个) -- **`label`**:显示名称 -- **其余列**:修饰符键名,值为变化量(`+`加、`-`减、空不修改) - -## 掷骰公式中的属性引用 - -`roll` 字段中的标识符自动替换为当前属性值: - -```yaml role=stat -- key: attack - scope: player - type: number - default: 0 - roll: "1d20 + attack + str_mod" -``` \ No newline at end of file