9.4 KiB
9.4 KiB
CSV 编写说明
TTRPG Tools 使用带有 YAML Front Matter 的 CSV 格式来定义卡牌/表格数据。这种格式支持在 CSV 文件头部定义元数据、字段配置和共享属性。
文件结构
---
# YAML Front Matter(可选)
fields:
- name: 字段名
description: 字段描述
deck:
size: 54x86
grid: 5x8
shared_prop: 共享属性值
---
# CSV 数据
label,body,field1,field2
1,内容,值 1,值 2
YAML Front Matter
Front Matter 是可选的,位于文件开头,使用 --- 包裹的 YAML 格式内容。
基本结构
---
fields:
- name: name
description: 卡牌名称
- name: effect
description: 效果描述
examples: ["造成 5d6 伤害", "恢复 2d4 生命值"]
deck:
size: 63x88
grid: 5x5
bleed: 1
padding: 2
custom_prop: 自定义属性
---
Front Matter 属性
fields - 字段定义
定义 CSV 中各列的含义和配置。
fields:
- name: name # 字段名称(英文,用于 CSV 列名)
description: 卡牌名称 # 字段描述
examples: # 示例值列表(可选)
- 火球术卷轴
- 治疗药水
dataType: word # 数据类型(可选):word/paragraph/number/symbol/symbol_list
function: identify # 字段功能(可选):identify/compare/flavor/rule
数据类型说明:
| 类型 | 说明 | 示例 |
|---|---|---|
word |
词语 - 短文本 | "火球术"、"战士"、"传说" |
paragraph |
文本段落 - 长描述 | "造成 5d6 点火焰伤害,范围内的所有生物进行敏捷豁免" |
number |
数字 - 可比较的数值 | 3、5、10 |
symbol |
单一符号 - 图标/标记 | 🔥、⚔️、🛡️ |
symbol_list |
符号列表 - 多个图标/标记 | 🔥🔥🔥、⚔️🛡️💫 |
字段功能说明:
| 功能 | 说明 | 示例 |
|---|---|---|
identify |
辨识 - 用于识别卡牌身份 | 名称、编号、唯一标识 |
compare |
比较 - 用于游戏机制中的数值比较 | 费用、攻击力、防御力 |
flavor |
游戏风味描述 - 提供背景故事/氛围 | 背景故事、引言、lore |
rule |
规则确认 - 明确游戏规则相关的信息 | 效果文本、触发条件、限制 |
deck - 卡牌显示配置
用于 :md-deck 组件的默认配置。
deck:
size: 63x88 # 卡牌尺寸(mm),格式 "宽 x 高"
grid: 5x5 # 网格布局,格式 "列 x 行"
bleed: 1 # 出血边距(mm)
padding: 2 # 内边距(mm)
shape: rectangle # 卡牌形状:rectangle/circle/hex/diamond
layers: "name:1-2,14" # 图层配置(可选)
back_layers: "" # 背面图层配置(可选)
图层配置语法遵循layer:1,1-5,8f8s格式:
layer:图层名称,多个图层用空格分隔1,1-5,8:网格范围,覆盖卡牌排版网格中的指定区域。f8:字体大小,使用8mm字体。可选。s:图层朝向,有nwse东西南北四种方向,描述文字上侧的朝向,默认为n北方。
自定义属性
可以在 Front Matter 中定义任意自定义属性,这些属性会被自动应用到所有卡牌行。
---
game_system: 龙与地下城 5e
author: DM_Name
version: 1.0
---
CSV 数据部分
基本格式
label,body,field1,field2
1,内容,值 1,值 2
必需列
label
每行的唯一标识,用于查找和修改卡牌。
- 可以是数字:
1,2,3 - 可以是文本:
card_001,npc_villager - 支持分组前缀:
forest_1,dungeon_1
body
卡牌的主要内容,支持 Markdown 格式。
label,body
1,"### 标题
**加粗文本**
- 列表项 1
- 列表项 2"
可选列
除 label 和 body 外,可以定义任意自定义列,列名在 Front Matter 的 fields 中定义。
label,body,name,type,cost,effect
1,完整内容,火球术,法术,3,造成 5d6 火焰伤害
变量语法
在 body 列或 Front Matter 中,可以使用 {{prop}} 语法引用其他列的值或 Front Matter 中的属性。
引用同行其他列
label,body,adj,noun
1,"**{{adj}}** 的{{noun}}",高大,战士
2,"{{adj}}的{{noun}}",矮小,法师
渲染后:
- 第 1 行:高大 的战士
- 第 2 行:矮小的法师
引用 Front Matter 属性
---
game_system: D&D 5e
author: DM_Name
---
label,body
1,"这是一个{{game_system}}冒险,由{{author}}创建"
渲染后:这是一个 D&D 5e 冒险,由 DM_Name 创建
随机引用(remix 模式)
在 :md-table 组件中,可以使用 remix 属性启用随机引用:
:md-table[./data.csv]{remix=true}
此时 {{prop}} 会从所有行中随机选择一行的值,而不是使用当前行的值。
分组支持
可以使用额外的列来对数据进行分组。
group,label,body
森林小径,1,狼群袭击
森林小径,2,荆棘陷阱
森林小径,3,迷路
塔楼楼梯,1,台阶坍塌
塔楼楼梯,2,落石
在 :md-table 组件中,可以使用 group 属性来筛选显示特定组的数据:
:md-table[./encounters.csv]{group="森林小径"}
特殊字符处理
包含逗号的值
使用双引号包裹:
label,body
1,"Hello, world"
包含双引号的值
使用两个双引号转义:
label,body
1,"他说:""你好"""
包含换行的值
使用双引号包裹,直接写入换行:
label,body
1,"### 标题
这是第一段
这是第二段"
包含 # 注释
CSV 解析器会将 # 开头的行视为注释,但如果 # 在双引号内则正常处理:
label,body
1,"# 这不是注释"
# 这是真正的注释
完整示例
示例 1:魔法物品卡牌组
---
fields:
- name: name
description: 物品名称
dataType: word
function: identify
- name: type
description: 物品类型
dataType: word
function: identify
examples: [武器,防具,饰品,消耗品]
- name: rarity
description: 稀有度
dataType: word
function: compare
examples: [普通,稀有,史诗,传说]
- name: cost
description: 价格
dataType: number
function: compare
- name: effect
description: 效果描述
dataType: paragraph
function: rule
deck:
size: 63x88
grid: 5x5
shape: rectangle
game_system: D&D 5e
---
label,body,name,type,rarity,cost,effect
1,"### 火球术卷轴
一张泛黄的羊皮纸,上面绘有火焰符文。",火球术卷轴,消耗品,稀有,150,"投掷后对 20 尺内所有生物造成 8d6 火焰伤害(敏捷豁免减半)"
2,"### 治疗药水
红色液体在玻璃瓶中翻滚,散发着温暖的光芒。",治疗药水,消耗品,普通,50,"饮用后恢复 2d4+2 点生命值"
3,"### +1 长剑
剑刃闪烁着微光,握柄包裹着精致的皮革。",+1 长剑,武器,稀有,300,"攻击和伤害检定 +1"
示例 2:随机遭遇表
---
fields:
- name: group
description: 遭遇地点分组
- name: title
description: 遭遇标题
- name: type
description: 遭遇类型
deck:
size: 54x86
grid: 4x6
---
group,label,body,title,type
森林小径,1,"### 狼群袭击
三只灰狼从灌木丛中扑出。
**交互**:战斗(3 只巨狼)或逃脱(敏捷检定 3/2)
**风险**:失败受到 d8 撕咬伤害",狼群袭击,战斗
森林小径,2,"### 荆棘陷阱
带刺藤蔓缠住你的双腿。
**交互**:挣脱(力量检定 3/2)
**风险**:失败受到 1 点体质损伤",荆棘陷阱,陷阱
森林小径,3,"### 迷路
浓雾弥漫,你失去了方向。
**交互**:寻找路径(感知检定 3/2)
**风险**:失败受到 1 点感知损伤",迷路,事件
塔楼楼梯,1,"### 台阶坍塌
脚下的石阶突然碎裂。
**交互**:保持平衡(敏捷检定 3/1)
**风险**:失败受到 1 点敏捷损伤",台阶坍塌,陷阱
示例 3:NPC 名录
---
fields:
- name: name
description: NPC 名称
- name: role
description: 角色定位
- name: location
description: 出现地点
deck:
size: 54x86
grid: 4x6
---
label,body,name,role,location
1,"### 老妇人玛拉
**类型**:信息提供者/商人
**位置**:村庄入口
**出售**:草药、治疗药水
**情报**:知道关于森林的警告",老妇人玛拉,商人,村庄入口
2,"### 护卫队长塞里克
**类型**:任务发布者
**位置**:酒馆二楼
**任务**:调查废弃庄园
**秘密**:知道血契的真相",塞里克,任务发布者,酒馆
与组件集成
:md-deck 组件
:md-deck[./magic-items.csv]{size="63x88" grid="5x5" roll=true}
roll=true:添加随机抽卡按钮
:md-table 组件
:md-table[./encounters.csv]{group="森林小径" remix=true}
group:筛选特定组的数据remix=true:启用随机引用模式
最佳实践
- 使用有意义的 label:便于后续查找和修改
- 在 Front Matter 中定义所有字段:便于工具理解和处理
- 使用
{{prop}}变量:减少重复内容,支持动态组合 - 合理使用分组:便于筛选和管理大量数据
- 保持 body 的 Markdown 格式一致:确保渲染效果统一
- 为字段添加
examples:帮助 AI 工具生成内容时参考