Suika3 标签参考
====================

## 索引

| 标签名 | 描述 |
|-----------------------------|--------------------------------------------------------------------|
| [anime](#anime) | 加载并执行一个动画定义文件 |
| [bg](#bg) | 以平滑渐变效果更换背景图片。 |
| [bgm](#bgm) | 播放背景音乐文件 （Ogg Vorbis 格式）。 |
| [callmacro](#callmacro) | 调用已定义的宏。 |
| [ch](#ch) | 显示或隐藏角色，支持详细的层级参数。 |
| [chapter](#chapter) | 设置章节名称。 |
| [choose](#choose) | 显示选项，并存储选择结果或跳转到指定标签。 |
| [click](#click) | 等待用户点击。 |
| [config](#config) | 设置游戏系统的配置值。 |
| [defmacro](#defmacro) | 开始定义一个宏。 |
| [else](#else) | if/elseif 分支的一部分，用于没有任何条件满足时的情况。 |
| [elseif](#elseif) | 在分支中指定额外的条件。  |
| [endif](#endif) | 结束条件分支。 |
| [endmacro](#endmacro) | 结束宏定义。 |
| [goto](#goto) | 跳转到指定的标记标签。 |
| [gui](#gui) | 从指定文件显示 GUI 界面。 |
| [if](#if) | 根据指定条件进行分支处理。 |
| [label](#label) | 定义跳转目标的标记。 |
| [layer](#layer) | 加载/卸载图片或设置特定图层的参数。 |
| [load](#load) | 加载 NovelML 文件，并可跳转到特定标记。 |
| [move](#move) | 在指定时间内对角色层级进行动画移动。 |
| [pencil](#pencil) | 在图层上绘制文本。 |
| [returnmacro](#returnmacro) | 从宏执行中返回。  |
| [se](#se) | 播放音效文件（Ogg Vorbis 格式）。 |
| [set](#set) | 设置变量值（所有变量均视为文本）。 |
| [skip](#skip) | 启用或禁用快进状态。 |
| [text](#text) | 在对话框中显示文本，可选择性地附带名字。 |
| [video](#video) | 播放视频文件（支持可跳过设置）。 |
| [volume](#volume) | 设置 BGM、SE 或音轨的音量。 |
| [wait](#wait) | 等待指定的秒数。 |

---

## `anime`

运行动画

`anime` 标签用于从文件中加载并执行动画定义。
它允许实现复杂的视觉效果、角色移动或循环场景动画，功能远超简单的转场。

### 基本用法

```
# 运行同步动画（等待完成）
[anime file="opening_effect.txt"]
# 运行异步循环动画
[anime file="sparkle.txt" async="true" register="my_loop"]
# 停止已注册的异步动画
[anime stop="true" register="my_loop"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|---------------|----------------|----------------------------------------------------|-------------------------------------------------------------------|
| `file` | 是 | 动画定义的文件名。 | *除非使用 `stop="true"`，否则此项为必填。 |
| `async` | 是 (`false`) | 是否异步运行动画。 | 如果为 `false`，脚本会等待动画结束后再继续。 |
| `register` | 是 | 用于标识此动画实例的唯一名称。 | 如果后续需要控制或停止异步动画，则必须填写。 |
| `stop` | 是 (`false`) | 如果设为 `true`，则停止已注册的动画。 | 需要配合 `register` 参数使用。 |
| `showsysbtn` | Yes (`true`) | 播放期间是否显示系统按钮。 | 仅对同步动画有效。 |
| `showmsgbox` | Yes (`true`) | 播放期间是否显示对话框。 | 仅对同步动画有效。 |
| `shownamebox` | Yes (`true`) | 播放期间是否显示名字框。 | 仅对同步动画有效。 |

### 贴士

**同步与异步**：
* **同步 (`async="false"`)**：非常适合用于过场动画，如果你想让玩家在任何文本或选择出现之前先观看动画。
* **异步 (`async="true"`)**：非常适合背景特效（如飘落的雪花或闪烁的灯光），这些特效应在故事推进的同时持续进行。

**管理实例**：
* 通过使用 `register` 参数，你可以给特定的动画打上标签。
* 当你使用 `stop="true"` 时，这就是你告诉引擎具体要停止哪一个动画的方法。

**界面控制**：
* 如果你的动画旨在占据全屏，并且你希望对话框暂时消失以获得更清爽的视觉效果，请使用 `showmsgbox="false"`。

---

## `bg`

更改背景

`bg` 标签用于以平滑的淡入淡出效果更改背景图像。
这是视觉小说中设置场景的主要方式。

### 基本用法

```
# 在 1.0 秒内过渡到 background.png
[bg file="background.png" time="1.0"]
# 淡入黑屏（移除背景）
[bg file="none" time="1.0"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|------------|----------------|-----------------------------------------------|------------------------------------------------------------------------------|
| `file` | 否 | 新背景图像的文件名。 | 设置为 `none` 可移除背景。 |
| `time` | 是 (`0`) | 淡入淡出效果的持续时间（秒）。 | 默认为 `0.0`（即时切换）。 |
| `method` | 是 (`normal`) | 淡入淡出的方法/样式。 | 可选 `normal`、`rule` 或 `melt`。 |
| `rule` | 是 | 特定过渡效果使用的规则图像文件。 | 当 `method` 设置为 `rule` 或 `melt` 时必须填写。 |
| `x` | 是 (`0`) | 背景图像的 X 轴偏移量。 | 支持绝对值（如 `100`）或相对值（如 `r100`）。 |
| `y` | 是 (`0`) | 背景图像的 Y 轴偏移量。 | 支持绝对值（如 `100`）或相对值（如 `r-100`）。 |
| `alpha` | 是 (`255`) | 背景图像的透明度值。 | `0` 到 `255`。 |
| `clear` | 是 (`false`) | 是否让角色消失。 | 如果为 `true`，所有角色都会消失。 |

### 过渡方法 (`method`)

您可以通过选择合适的过渡风格来营造不同的氛围：

| 类型 | 描述 |
|----------|--------------------------------------------------------------------------------------------------------------------------------------|
| `normal` | Alpha 混合。默认方法。在旧图像和新图像之间执行平滑的交叉淡入淡出。 |
| `rule` | 1-bit 通用过渡。使用灰度“规则”图像来确定切换顺序。 |
| `melt` | 8-bit 通用过渡。与 `rule` 类似，但在过渡边界处有柔和、模糊的边缘，产生“融化”效果。 |

对于 `rule` 和 `melt`，图像会根据规则图的灰度，从最暗区域到最亮区域逐像素切换。

### 贴士

**相对定位**:
* 如果您想从当前位置微调背景，请使用 `r` 前缀。
* 例如，`x="r50"` 会将图像从其当前 X 坐标向右移动 50 像素。

**什么是规则图像？**:
* 它是一个灰度图像，其中黑色区域最先过渡，白色区域最后过渡。
* 通过创建自定义规则图像，您可以实现水平擦除、圆形揭示甚至更具艺术感的图案效果！

---

## `bgm`

播放背景音乐

`bgm` 标签用于播放背景音乐曲目。
音乐是营造场景氛围的重要工具，它会自动循环播放，直到被停止或被更改。

### 基本用法

```
# 开始播放 BGM 曲目
[bgm file="field_theme.ogg"]
# 停止当前 BGM（使用 "none"）
[bgm file="none"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|---------------|------------------------------------|----------------------------------------|
| `file` | 否 | 要播放的音乐文件名。 | 设置为 `none` 可停止当前 BGM。 |
| `once` | 是 (`false`) | 不循环播放。 |                                        |

### 贴士

**所需格式**:
* 为了兼容性和性能，Suika3 要求 BGM 文件必须是 **Ogg Vorbis** 格式。
* 采样率“必须”是 **44,100Hz**。

**循环播放**:
* 背景音乐默认设计为循环播放，因此您无需担心在长对话场景中音乐突然结束。

**平滑过渡**:
* 如果在播放另一首曲目时调用 `[bgm]`，引擎通常会处理过渡。
* 要调整音乐音量，您需要使用 `[volume]` 标签。

**停止音乐**:
* 当场景结束或氛围变为寂静时，记得使用 `[bgm file="none"]` 让玩家的耳朵休息一下！

---

## `callmacro`

调用宏

`callmacro` 标签用于执行先前定义的宏。
它允许您触发特定的命令序列（例如角色入场或 UI 动画），从而在脚本中多次使用而无需重写原始代码。

### 基本用法

```
# 调用名为 "kaito_entrance" 的宏
[callmacro name="kaito_entrance"]
# 调用特定场景过渡的宏
[callmacro name="fade_to_white"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|-------------------------------------------|----------------------------------------------------|
| `name` | 否 | 要执行的宏的名称。 | 必须与 `[defmacro]` 标签定义的名称匹配。 |
| `file` | 是 | 定义宏的文件名。 | 省略此项将调用当前文件内的宏。 |

### 贴士

**效率**:
* 通过使用 `[callmacro]`，您可以保持主线剧情脚本的重点和可读性。
* 您将不再看到冗长的 10 行动画代码，取而代之的是一个清晰明了的指令。

**执行流程**:
* 当引擎遇到 `[callmacro]` 时，它会立即跳转到定义的宏，运行其中包含的所有标签，然后自动返回到 `[callmacro]` 标签之后的下一行继续执行。

**模块化设计**:
* 把宏想象成您游戏的“自定义标签”。
* 如果您决定更改角色入场的方式，只需在 `[defmacro]` 代码块中更新一次代码，所有的 `[callmacro]` 调用都会自动反映这一变化！

---

## `ch`

角色显示

`ch` 标签用于在各种图层上显示、隐藏或更新角色图像。
它允许对多个角色和背景的位置、缩放和旋转进行精细控制。

### 基本用法

```
# 在中央显示一个角色
[ch center="chara001.png" time="1.0"]
# 在特定位置显示多个角色
[ch left="chara002.png" right="chara003.png" time="0.5"]
# 隐藏特定角色
[ch center="none" time="1.0"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|-----------|----------------|----------------------------------------|-------------------------------------------------------|
| `time` | 是 (`0`) | 过渡持续时间（秒）。 | 影响此标签内的所有图层更改。  |
| `method` | 是 (`normal`) | 淡入淡出的方法/样式。 | `normal`、`rule` 或 `melt`。 |
| `rule` | 是 | 用于过渡的规则图像文件。 | 当 `method` 为 `rule` 或 `melt` 时必须填写。 |

#### 图层文件参数

指定文件名以将图像加载到图层上。设置为 `none` 以卸载（隐藏）图像。

| 参数 | 描述 |
|----------------|-------------------------------------------|
| `bg` | 背景图层。 |
| `back` | 后方-中央角色。 |
| `left` | 左侧角色。 |
| `left-center` | 左侧-中央角色。 |
| `center` | 中央角色。 |
| `right-center` | 右侧-中央角色。 |
| `right` | 右侧角色。 |
| `face` | 面部特写角色。 |

#### 图层参数后缀

上述每个图层（例如 `center`）都可以使用以下后缀进行自定义（例如 `center-x`、`center-rotate`）。

| 后缀 | 是否可省略 | 描述 | 备注 |
|-------------|---------------|----------------------------|---------------------------------------------------------------|
| `-x` | 是 (`0`) | X 轴坐标。 | 支持绝对值（如 `100`）或相对值（如 `r50`）。 |
| `-y` | 是 (`0`) | Y 轴坐标。 | 支持绝对值（如 `100`）或相对值（如 `r-50`）。 |
| `-a` | 是 (`255`) | Alpha值。（不透明度） | `0`（透明）到 `255`（不透明）。 |
| `-scale-x` | 是 (`1.0`) | X 轴缩放比例。 | `1.0` 为原始大小。支持 `r` 前缀。 |
| `-scale-y` | 是 (`1.0`) | Y 轴缩放比例。 | `1.0` 为原始大小。支持 `r` 前缀。 |
| `-center-x` | 是 (`0`) | 旋转中心的 X 轴。 | 旋转效果的支点。 |
| `-center-y` | 是 (`0`) | 旋转中心的 Y 轴。 | 旋转效果的支点。 |
| `-rotate` | 是 (`0`) | 旋转角度。 | 正值表示顺时针。支持 `r` 前缀。 |
| `-dim` | 是 (`false`) | 变暗状态。 | 如果为 `true`，该图层将以 50% 的亮度渲染（变暗）。 |

### 贴士

**批量更新**:
* 您可以在单个 `[ch]` 标签中同时更新多个角色和背景，以确保它们完美地同步动画。

**相对变换**:
* 与 `bg` 标签一样，所有数值参数都支持 `r` 前缀。
* 例如，`center-y="r-50"` 将使中央角色从当前位置向上跳跃 50 像素。

---

## `chapter`

设置章节名称

`chapter` 标签用于设置当前章节的名称。
该名称通常由游戏系统用于在存档/读档菜单或游戏界面上显示进度，帮助玩家追踪他们的游戏旅程。

### 基本用法

```
# 在故事片段开始时设置章节名称
[chapter name="Chapter 01: The Beginning"]
# 随着故事进展更新章节名称
[chapter name="Intermission: A Quiet Night"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|------------------------------------|------------------------------------------------------------|
| `name` | 否 | 要设置的章节名称。 | 此字符串将存储在游戏的系统变量中。 |

### 贴士

**存档数据可见性**:
* 在许多 Suika3 配置中，您在这里设置的字符串会显示在“存档”和“读档”的槽位上。
* 选择一个能帮助玩家确切回忆起故事进度的名称！

**一致性**:
* 一个良好的做法是在开启新场景或新章节的 `[label]` 之后立即调用 `[chapter]` 标签。

**更新名称**:
* 您可以随意地多次调用 `[chapter]`。
* 每次调用时，旧的章节名称都会被新的覆盖。

---

## `choose`

显示选项

`choose` 标签用于向玩家显示最多达 8 个的交互式按钮。
它会将选中项的文本存储在一个变量中。

### 基本用法

```
# 将选择结果存储在一个变量中
[choose
    text1="Red Pill"
    text2="Green Pill"
    text3="Blue Pill"
    name="user_choice"
    value1="red"
    value2="green"
    value3="blue"
]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|------------------|-----------|------------------------------------------------|--------------------------------------------------- |
| `text1` | 是 | 每个按钮上显示的文本。 | 通常至少需要一个选项。 |
| `text2` | 是 | 每个按钮上显示的文本。 | 通常至少需要一个选项。 |
| `text3` | 是 | 每个按钮上显示的文本。 | 通常至少需要一个选项。 |
| `text4` | 是 | 每个按钮上显示的文本。 | 通常至少需要一个选项。 |
| `text5` | 是 | 每个按钮上显示的文本。 | 通常至少需要一个选项。 |
| `text6` | 是 | 每个按钮上显示的文本。 | 通常至少需要一个选项。 |
| `text7` | 是 | 每个按钮上显示的文本。 | 通常至少需要一个选项。 |
| `text8` | 是 | 每个按钮上显示的文本。 | 通常至少需要一个选项。 |
| `text<N>-locale` | 是 | 每个按钮上显示的文本。（本地化） | 通常至少需要一个选项。 |
| `name` | 否 | 存储结果的变量名。 | 存储选中选项的文本。 |
| `value1` | 是 | 分配给结果变量的值。 | 通常至少需要一个选项。 |
| `value2` | 是 | 分配给结果变量的值。 | 通常至少需要一个选项。 |
| `value3` | 是 | 分配给结果变量的值。 | 通常至少需要一个选项。 |
| `value4` | 是 | 分配给结果变量的值。 | 通常至少需要一个选项。 |
| `value5` | 是 | 分配给结果变量的值。 | 通常至少需要一个选项。 |
| `value6` | 是 | 分配给结果变量的值。 | 通常至少需要一个选项。 |
| `value7` | 是 | 分配给结果变量的值。 | 通常至少需要一个选项。 |
| `value8` | 是 | 分配给结果变量的值。 | 通常至少需要一个选项。 |
| `time` | 是 (`0`) | 计时器（秒）。 | 如果为 `0`，则不启用计时器。 |

### 本地化

例如，如果用户的操作系统环境设置为日语，系统会优先使用 `text1-ja` 而不是 `text1`。

| 后缀 | 语言 |
|-------------|------------------------------------------|
| -en | 英语（回退/Fallback） |
| -en-us | 英语（美国） |
| -en-gb | 英语（英国） |
| -en-au | 英语（澳大利亚） |
| -en-nz | 英语（新西兰） |
| -fr | 法语（回退/Fallback） |
| -fr-fr | 法语（法国） |
| -fr-ca | 法语（加拿大） |
| -es | 西班牙语（西班牙，回退/Fallback） |
| -es-la | 西班牙语（拉丁美洲） |
| -de | 德语 |
| -it | 意大利语 |
| -ru | 俄语 |
| -el | 希腊语 |
| -zh | 中文（简体） |
| -zh-tw | 中文（繁体，台湾） |
| -ja | 日语 |
| (无后缀) | 回退（由开发者决定） |

对于包括所有区域在内的英语操作系统区域设置，`-en` 被用作默认回退。如果在标签中指定了更具体的变体（如 `-en-gb`）并且与用户区域最匹配，它将优先被使用。同样的机制也适用于西班牙语和法语。请注意，繁体中文不会回退到简体中文。

例如，如果用户区域设置为 `en-AU`，则应用以下优先级：
* 1. text1-en-au
* 2. text1-en
* 3. text1

以下语言目前尚不支持，但计划在未来支持。

| 后缀 | 语言 |
|-------------|------------------------------------------|
| -ko | 韩语 |
| -vi | 越南语 |
| -id | 印度尼西亚语 |
| -zh-hk | 繁体中文（香港） |
| -pt | 葡萄牙语（回退） |
| -pt-br | 葡萄牙语（巴西） |
| -pl | 波兰语 |
| -tr | 土耳其语 |
| -ta | 泰米尔语 |
| -te | 泰卢固语 |
| -kn | 卡纳达语 |
| -si | 僧伽罗语 |
| -ar | 阿拉伯语（从右向左书写） |
| -fa | 波斯语（从右向左书写） |

### 贴士

**分支逻辑**:
* 您可以使用 `[if]` 标签来检查已存储的值，并创建复杂的分支剧情。

```
[choose
  name="var1"
  text1="Go to school"
  text2="Go to hospital"
  value1="1"
  value2="2"]
[if lhs="${var1}" op="=" rhs="1"]
  # 学校剧情。
[else]
  # 医院剧情。
[endif]
```

**变量持久化**:
* 由于一切都是字符串，请记住即使是像 "100" 这样的数字也是作为文本存储的。
* Suika3 的逻辑标签（如 `if`）可以处理这些字符串进行比较。

---

## `set`

设置变量

`set` 标签用于给变量名赋值。
在 Suika3 中，**所有变量都被视为文本字符串**，但它们可以在其他标签（如 `[if]`）中进行数值比较。

### 基本用法

```
# 将一个简单的字符串赋值给变量
[set name="player_name" value="Kaito"]
# 设置一个类似数字的值（作为字符串存储）
[set name="health" value="100"]
# 通过将变量设置为空字符串来清空它
[set name="flag_event_01" value=""]
# 给 var1 加 1。
[set name="var1" value1="${var1}" op="+" value2="1"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|---------------|---------------------------------------------|---------------------------------------------------------------------|
| `name` | 否 | 变量的唯一名称。 | 请使用字母数字和下划线来获得最佳的兼容性。 |
| `value` | 是 | 存储在变量中的内容。 | 记住：一切都是作为字符串存储的！ |
| `value1` | 是 | 运算符的操作数 1。 |                                                                     |
| `value2` | 是 | 运算符的操作数 2。 |                                                                     |
| `op` | 是 | 运算符。The opcode. (`+`, `-`, `*`, `/`, `//`, `%`) |                                                                     |
| `global` | 是 (`false`) | 将标志设为全局。 | 全局变量用于成就标志，例如“观看结局1”。 |

### 贴士

**字符串处理**:
* 由于 Suika3 将一切视为文本，`value="100"` 和 `value="May"` 在内部处理方式是一样的。
* 您可以使用 `${variable_name}` 语法在其他标签（如 `text` 或 `if`）中引用这些变量。

**标志管理**:
* 对于游戏标志（如“已遇见主角”），使用 `"true"` 和 `"false"` 或 `"1"` 和 `"0"` 是常见的做法。
* 一致性是关键！如果您开始使用 `"1"`，请坚持使用它，以免您的 `[if]` 检查出现混乱。

**变量命名**:
* 避免在变量名中使用空格或特殊符号。`my_variable` 比 `my variable!` 安全得多。

---

## `click`

等待点击

`click` 标签会暂停脚本的执行，并等待玩家点击鼠标或按下按键。
它通常用于在视觉变化之间或重大过渡之前制造停顿。

### 基本用法

```
# 更改背景，然后等待玩家点击
[bg file="sunset.png" time="1.0"]
[click]
# 点击后，显示角色
[ch center="chara01.png" time="1.0"]
```

### 参数

此标签不接受任何参数。

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|-------------|-----------------|
| - | - | - | - |

### 贴士

**时机与节奏**:
* 当您希望玩家在对话继续之前有时间看一眼新背景或特定的角色表情时，请使用 `[click]`。
* 与 `[text]` 标签（在显示消息后自动等待点击）不同，`[click]` 用于非对话序列期间的手动流程控制。

**视觉反馈**:
* 当脚本遇到 `[click]` 标签时，游戏画面将保持静止。请确保之前的任何动画（如 `[bg]` 或 `[ch]`）都设置了 `time`，否则画面可能会感觉突然静止，显得生硬。

**关于定时等待**
* 如果需要定时等待，请使用 `[wait]` 标签。

---

## `goto`

跳转到标记

`goto` 标签会立即将 NovelML 的执行移动到指定的标记。
它是控制故事流向的有用工具，允许您跳过某些部分或循环回到之前的部分。

请注意，小的分支应该通过 `[if]` 来实现。

### 基本用法

```
# 跳转到早晨场景的开头
[goto name="morning_start"]
# ... 脚本的这部分将被跳过 ...
[label name="morning_start"]
[text text="The sun rises over the horizon."]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|-----------------------------------|-----------------------------------------------|
| `name` | 否 | 要跳转的目标标记名称。 | 必须与 `[label]` 标签定义的名称匹配。 |

### 贴士

**无条件跳转**:
* 与 `[if]` 不同，只要引擎遇到 `[goto]` 标签，它“总会”跳转到目标标记。

**流程管理**:
* 在分支路径的末尾使用 `[goto]` 将故事带回到“公共”路线。
* 当与其他逻辑结合使用时，它也非常适合创建循环（例如“返回标题”序列）。

**跨文件跳转？**:
* 请记住，`[goto]` 通常在当前脚本文件内工作。
* 如果您想跳转到完全不同的文件，您需要查看 `[load]` 标签！

---

## `defmacro`

定义宏

`defmacro` 标签开始定义一个宏。
宏允许您将多个标签和命令组合成一个命名的代码块，该代码块可以使用 `[callmacro]` 标签在脚本中重复使用。

### 基本用法

```
# 为特定角色的入场定义一个宏
[defmacro name="enter_kaito"]
    [ch center="kaito_smile.png" time="0.5"]
    [text name="Kaito" text="Hey!Did I keep you waiting?"]
[endmacro]
# 在脚本后面，用一行代码调用它
[callmacro name="enter_kaito"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|---------------------------------|---------------------------------------------------|
| `name` | 否 | 此宏的唯一名称。 | 用于在之后的调用中识别宏。 |

### 贴士

**结束定义**:
* 每个 `[defmacro]` 必须与一个 `[endmacro]` 标签配对，以标记定义的结束。

**代码复用性**:
* 宏非常适合重复性的序列，例如特定的 UI 过渡、特定角色的视觉设置，或复杂的视听组合。

**组织管理**:
* 常见的做法是将所有的宏定义在主脚本文件的最开始，或者一个您在开始时加载的单独文件中。

**嵌套与逻辑**:
* 您可以在宏中包含几乎所有其他标签，包括 `[if]` 语句，甚至 `[returnmacro]`，以便根据特定条件提前退出宏。

---

## `gui`

显示图形用户界面

`gui` 标签用于从指定文件加载并显示图形用户界面定义。
它用于显示菜单、标题画面或自定义交互面板。

### 基本用法

```
# 显示主菜单界面
[gui file="main_menu.txt"]
# 显示自定义的存档/读档界面
[gui file="save_screen.txt"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|---------------------------------------------|-----------------------------------------------------|
| `file` | 否 | 要加载的 GUI 定义文件名。 | 该文件必须存在于项目的 GUI 目录中。 |

### 贴士

**GUI 定义**:
* `file` 参数指向一个文本文件，该文件定义了界面的布局、按钮和动作。
* 这些文件指定了图片的放置位置，以及当用户与它们交互时（比如跳转到某个标签或退出游戏）会发生什么。

**在流程中的使用**:
* 通常，`[gui]` 标签用于图形菜单，例如标题画面。

**自定义**:
* 由于 GUI 是在外部文件中定义的，您可以为游戏创建多种外观，只需通过此标签调用不同的文件即可在它们之间切换。

---

## `label`

定义标签

`label` 标签在脚本中定义一个特定的点，该点可以被 `[goto]` 或 `[load]` 等跳转命令作为目标。
它充当故事导航的书签。

### 基本用法

```
# 为新章节的开始定义一个标记
[label name="chapter_01_start"]
# 使用跳转命令到达此标记
[goto name="chapter_01_start"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|---------------------------------|--------------------------------------------------------|
| `name` | 否 | 此标记的唯一名称。 | 区分大小写。避免使用空格或特殊符号。 |

### 贴士

**导航控制**:
* 标记对于创建分支路径非常有用。
* 例如，您可以在故事的一个长跳转部分的开头放置一个 `label`。

**唯一命名**:
* 单个脚本文件中的每个标记名称必须是唯一的。
* 如果您有两个同名的标记，引擎可能不知道跳到哪里，这对任何人来说都不好玩！

**组织管理**:
* 使用描述性的名称（如 `label_evening_park`）而不是 `label1` 是一个好习惯。
* 这让您（和我！）稍后阅读脚本时更容易理解发生了什么。

---

## `text`

显示文本

`text` 标签在消息框中显示一条消息。
它可以显示主要对话或旁白，并可选择在姓名框中显示角色的名字。

### 基本用法

```
# 旁白风格（不显示名字）
[text text="The wind was howling through the trees."]
# 角色对话
[text name="Keith" text="I've been waiting for you here in the small room."]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|------------------|-----------|--------------------------------------------------|--------------------------------------------------|
| `text` | 否 | 要显示的消息内容。 |                                                  |
| `text-<locale>` | 是 | 要显示的消息内容。（本地化） |                                                  |
| `voice` | 是 | 语音文件。 |                                                  |
| `voice-<locale>` | 是 | 语音文件。（本地化） |                                                  |
| `name` | 是 | 要在姓名框中显示的角色名字。 | 如果省略，姓名框通常会被隐藏。 |
| `action` | 是 | 用于 NVL 模式和手动显示/隐藏。 |                                                  |
| `space` | 是 | 用于 NVL 模式。 |                                                  |

### 本地化

例如，如果用户的操作系统环境设置为日语，系统会优先使用 `text-ja` 而不是 `text`。

| 后缀 | 语言 |
|-------------|------------------------------------------|
| -en | 英语（回退/Fallback） |
| -en-us | 英语（美国） |
| -en-gb | 英语（英国） |
| -en-au | 英语（澳大利亚） |
| -en-nz | 英语（新西兰） |
| -fr | 法语（回退/Fallback） |
| -fr-fr | 法语（法国） |
| -fr-ca | 法语（加拿大） |
| -es | 西班牙语（西班牙，回退/Fallback） |
| -es-es | 西班牙语（西班牙，回退/Fallback） |
| -es-la | 西班牙语（拉丁美洲） |
| -de | 德语 |
| -it | 意大利语 |
| -ru | 俄语 |
| -el | 希腊语 |
| -zh-cn | 中文（简体） |
| -zh-tw | 中文（繁体，台湾） |
| -ja | 日语 |
| (无后缀) | 回退（由开发者决定） |

对于包括所有区域在内的英语操作系统区域设置，`-en` 被用作默认回退。如果在标签中指定了更具体的变体（如 `-en-gb`）并且与用户区域最匹配，它将优先被使用。同样的机制也适用于西班牙语和法语。请注意，繁体中文不会回退到简体中文。

例如，如果用户区域设置为 `en-GB`，则应用以下优先级：
* 1. text-en-gb
* 2. text-en
* 3. text

以下语言目前尚不支持，但计划在未来支持。

| 后缀 | 语言 |
|-------------|------------------------------------------|
| -ko | 韩语 |
| -vi | 越南语 |
| -id | 印度尼西亚语 |
| -zh-hk | 繁体中文（香港） |
| -pt | 葡萄牙语（回退） |
| -pt-br | 葡萄牙语（巴西） |
| -pl | 波兰语 |
| -tr | 土耳其语 |
| -ta | 泰米尔语 |
| -te | 泰卢固语 |
| -kn | 卡纳达语 |
| -si | 僧伽罗语 |
| -ar | 阿拉伯语（从右向左书写） |
| -fa | 波斯语（从右向左书写） |

### 行为

您可以在 `text` 标签中使用特殊参数。

```
# 清空消息框。
[text action="clear"]
# 清空消息框并显示它。
[text action="new"]
# 显示消息框。
[text action="show"]
# 隐藏消息框。
[text action="hide"]
```

### NVL 模式

您可以通过设置一些配置来进入 NVL 模式（即全屏小说模式）。

```
[text action="hide"]
[wait time="0.3"] # 等待消息框隐藏。
[config name="game.novel" value="true"]
[config name="msgbox.image" value="system/message/msgbox-nvl.png"]
[config name="msgbox.x" value="0"]
[config name="msgbox.y" value="0"]
[config name="msgbox.margin.line" value="60"]
[config name="namebox.enable" value="false"]
[config name="choose.box1.idle" value="system/choose/nvl.png"]
[config name="choose.box1.hover" value="system/choose/nvl.png"]
[config name="choose.box1.idle_anime" value="system/choose/idle-nvl.anime"]
[config name="choose.box1.hover_anime" value="system/choose/hover-nvl.anime"]
[config name="choose.box2.idle" value="system/choose/nvl.png"]
[config name="choose.box2.hover" value="system/choose/nvl.png"]
[config name="choose.box2.idle_anime" value="system/choose/idle-nvl.anime"]
[config name="choose.box2.hover_anime" value="system/choose/hover-nvl.anime"]
[config name="choose.box3.idle" value="system/choose/nvl.png"]
[config name="choose.box3.hover" value="system/choose/nvl.png"]
[config name="choose.box3.idle_anime" value="system/choose/idle-nvl.anime"]
[config name="choose.box3.hover_anime" value="system/choose/hover-nvl.anime"]
[config name="click.move" value="true"]
[text action="clear"]
```

您可以通过重置配置回到 ADV 模式（即文字冒险模式）。

```
[text action="hide"]
[wait time="0.3"] # 等待消息框隐藏。
[config name="game.novel" value="false"]
[config name="msgbox.image" value="system/message/msgbox.png"]
[config name="msgbox.x" value="0"]
[config name="msgbox.y" value="520"]
[config name="msgbox.margin.line" value="40"]
[config name="namebox.enable" value="true"]
[config name="choose.box1.idle" value="system/choose/idle.png"]
[config name="choose.box1.hover" value="system/choose/hover.png"]
[config name="choose.box1.idle_anime" value="system/choose/idle.anime"]
[config name="choose.box1.hover_anime" value="system/choose/hover.anime"]
[config name="choose.box2.idle" value="system/choose/idle.png"]
[config name="choose.box2.hover" value="system/choose/hover.png"]
[config name="choose.box2.idle_anime" value="system/choose/idle.anime"]
[config name="choose.box2.hover_anime" value="system/choose/hover.anime"]
[config name="choose.box3.idle" value="system/choose/idle.png"]
[config name="choose.box3.hover" value="system/choose/hover.png"]
[config name="choose.box3.idle_anime" value="system/choose/idle.anime"]
[config name="choose.box3.hover_anime" value="system/choose/hover.anime"]
[config name="click.move" value="false"]
```

在 NVL 模式下，您可以这样控制文本消息：

```
# 新的页面。
[text action="clear"]
[text text="Hello, this is NVL mode test."]
[text text="NVL mode has a fullscreen-styled message box."]
[text text="By default, each text tag will do a line feed."]
[text text="To continue a paragraph,"]
[text text="specify the space parameter." space=" "]
# 新的页面。
[text action="clear"]
[text text="Please clear the message box explicitly."]
```

### 语音

如果当前语言是 `en-us`，语音文件将按以下顺序解析：

1. `voice-en-us` 参数
2. `voice/en-us/` + `voice` 参数
3. `voice-en` 参数
4. `voice/en/` + `voice` 参数
5. `voice` 参数

如果当前语言是 `ja`，语音文件将按以下顺序解析：

1. `voice-ja` 参数
2. `voice/ja/` + `voice` 参数
3. `voice` 参数

### 贴士

**自动等待**:
* 与其他标签不同，`text` 标签在消息完全显示后会自动等待玩家点击。
* 您不需要在每一行对话后都添加 `[click]` 标签！

**使用变量**:
* 您可以使用 `${variable_name}` 语法在文本中包含变量。
* 示例：`[text text="你好，${player_name}！"]` 将使用该变量中存储的任何名字来问候玩家。

**换行**:
* 检查您的项目配置，了解单行文本的最大长度。
* 如果您的文本太长，它可能会溢出消息框，所以请留意您的 `text` 参数的长度！

---

## `if`

条件分支

`if` 标签允许 NovelML 根据特定条件进行分支。
通过比较变量或值，您可以创建独特的叙事路径，或对玩家之前的选择做出反应。

### 基本用法

```
# 检查变量是否等于某个值
[if lhs="${points}" op="==" rhs="100"]
    [text text="Perfect score!You're amazing."]
[elseif lhs="${points}" op=">=" rhs="80"]
    [text text="Great job!You passed."]
[else]
    [text text="Better luck next time."]
[endif]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|----------------------------------------|------------------------------------------------|
| `lhs` | 否 | 条件的左侧。 | 通常是像 `${var_name}` 这样的变量。 |
| `op` | 否 | 用于比较的运算符。 | 参见下方的“运算符”表。 |
| `rhs` | 否 | 条件的右侧。 | 要比较的值或变量。 |

### 比较运算符 (`op`)

您可以使用这些运算符来定义两边的比较方式：

| 运算符 | 描述 |
|------------|----------------------------|
| `===` | 相等（字符串比较） |
| `==` | 相等（数值比较） |
| `>` | 大于（数值） |
| `>=` | 大于等于（数值） |
| `<` | 小于（数值） |
| `<=` | 小于等于（数值） |

### 贴士

**结束代码块**:
* 每个 `[if]` 代码块“必须”以 `[endif]` 标签结束。
* 如果您忘记了它，引擎可能会搞不清楚条件在哪里结束！

**变量语法**:
* 当使用变量作为 `lhs` 时，请务必用 `${}` 包裹它。
* 例如，使用 `lhs="${flag_01}"` 而不是 `lhs="flag_01"`。

**处理字符串与数字**:
* Suika3 将变量值视为字符串，但这些运算符允许您执行数值风格的比较。
* 只要保持值的一致性即可（例如，用 "1" 代表真，用 "0" 代表假）。

**多重分支**:
* 您可以在 `[if]` 和 `[endif]` 之间使用任意数量的 `[elseif]` 标签，以检查多个特定条件。

---

## `elseif`

附加条件分支

`elseif` 标签在 `[if]` 代码块内指定了一个附加条件。
只有在前面的 `[if]` 和任何先前的 `[elseif]` 条件都为假（false）时，才会对它进行求值。

### 基本用法

```
[if lhs="${rank}" op="==" rhs="A"]
    [text text="Excellent!You're a pro."]
[elseif lhs="${rank}" op="==" rhs="B"]
    [text text="Good job!Keep it up."]
[elseif lhs="${rank}" op="==" rhs="C"]
    [text text="Not bad, but you can do better."]
[else]
    [text text="Don't give up!Try again."]
[endif]
```

### 参数

与 `[if]` 相同。另请参阅 [if](#if)。

### 贴士

**顺序求值**:
* 引擎会自上而下检查条件。
* 一旦满足某个 `[if]` 或 `[elseif]` 条件，就会执行其代码块，并跳过分支的其余部分（包括其他 `[elseif]` 和 `[else]`）。

**放置位置**:
* `[elseif]` 必须始终放在 `[if]` 标签和 `[else]` 或 `[endif]` 标签之间。
* 您可以根据需要使用任意数量的 `[elseif]` 标签来覆盖所有情况！

**效率**:
* 如果您有很多检查同一个变量的条件，使用多个 `[elseif]` 标签比将多个 `[if]` 代码块相互嵌套要清晰和高效得多。

---

## `else`

默认条件分支

`else` 标签定义了一个代码块，如果前面的 `[if]` 或 `[elseif]` 条件都不满足，则执行该代码块。
它充当分支逻辑的“默认”路径。

### 基本用法

```
[if lhs="${weather}" op="==" rhs="sunny"]
    [text text="It's a beautiful day!"]
[elseif lhs="${weather}" op="==" rhs="rainy"]
    [text text="I should bring an umbrella."]
[else]
    # 如果不是晴天也不是雨天（比如多云或下雪），则运行此代码
    [text text="The sky looks interesting today."]
[endif]
```

### 参数

此标签不接受任何参数。

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|-------------|-------|
| - | - | - | - |

### 贴士

**最终捕获**:
* 使用 `[else]` 来处理您在 `[if]` 或 `[elseif]` 检查中没有明确涵盖的任何情况。
* 它确保游戏始终有一条有效的路径可走。

**放置位置**:
* `[else]` 必须放在所有 `[elseif]` 标签之后（如果有的话），并紧挨着 `[endif]` 标签之前。
* 每个 `[if]` 代码块只能有一个 `[else]`。

**可选性质**:
* 您*不一定*必须包含 `[else]` 代码块。
* 如果没有满足任何条件且没有 `[else]`，引擎将简单地跳过所有内容并在 `[endif]` 之后继续执行。

---

## `endif`

结束条件分支

`endif` 标签标记由 `[if]` 标签开始的条件代码块的结束。
它告诉引擎在分支逻辑完成后恢复正常的脚本执行。

### 基本用法

```
[if lhs="${love_points}" op=">=" rhs="50"]
    [text text="She gives you a warm smile."]
[else]
    [text text="She greets you politely."]
[endif]
# 无论上面的结果如何，脚本执行都会在这里继续
[text text="The day continues..."]
```

### 参数

此标签不接受任何参数。

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|-------------|-------|
| - | - | - | - |

### 贴士

**强制闭合**:
* 每个 `[if]` 标签都必须有一个对应的 `[endif]`。
* 把它们想象成一对括号，用来保持叙事逻辑的条理性。

**放置位置**:
* 始终将 `[endif]` 放在条件序列的最后，紧跟在任何 `[elseif]` 或 `[else]` 代码块之后。

**嵌套**:
* 如果您在一个 `[if]` 里面放了另一个 `[if]`，请确保每个都有自己的 `[endif]`。
* 正确的嵌套是实现复杂且无错误的叙事标志的秘诀！

---

## `load`

加载脚本文件

`load` 标签将当前脚本切换到另一个 NovelML 文件。
它主要用于将大型故事组织成多个章节，或在不同游戏部分（如标题画面和主线故事）之间进行过渡。

### 基本用法

```
# 加载 scene02.novel 并从开头开始
[load file="scene02.novel"]
# 加载 scene02.novel 并直接跳转到特定标签
[load file="scene02.novel" label="chapter2_start"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|--------------------------------------------------|---------------------------------------------------------|
| `file` | 否 | 要加载的 NovelML 脚本文件名。 | 必须是项目脚本目录中的有效文件。 |
| `label` | 是 | 要跳转到的新文件中的目标标签。 | 如果省略，脚本将从第一行开始。 |

### 贴士

**项目组织管理**:
* 不要将整个游戏写在一个巨大的文件中，使用 `[load]` 将其分解为易于管理的块，如 `chapter1.novel`、`chapter2.novel` 等。

**即时过渡**:
* 当引擎遇到 `[load]` 标签时，它会立即停止执行当前的 NovelML 文件并切换到新文件。
* 原始文件中放在 `[load]` 之后的任何命令都不会被执行。

**全局标志**:
* 不用担心您的变量——您使用 `[set]` 标签设置的任何值即使在加载新脚本文件后也会保留！

---

## `se`

播放音效

`se` 标签用于播放音效（SE）。
音效用于短促的音频提示，如敲门声、脚步声或 UI 反馈，为您的场景增添一层沉浸感和真实感。

### 基本用法

```
# 播放一次音效
[se file="door_open.ogg"]
# 停止所有当前正在播放的音效
[se file="none"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|---------------|-------------------------------------------|----------------------------------------------|
| `file` | 否 | 要播放的音效文件名。 | 设置为`none` 以停止音效播放。 |
| `loop`: | 是 (`false`) | 是否循环播放音效。 |                                              |

### 贴士

**所需格式**:
* 像背景音乐（BGM）一样，Suika3 要求 SE 文件必须是 **Ogg Vorbis** 格式。
* 采样率“必须”是 **44,100Hz**，以确保高保真度和兼容性。

**声音分层**:
* 音效通常可以在背景音乐运行时播放。
* 它们占用自己的音轨，因此不会打断您的音乐。

**音量控制**:
* 要调整音效的响度而不改变背景音乐音量，请使用带有 `track="se"` 的 `[volume]` 标签。

**用于环境音**:
* 虽然 SE 通常用于短促的声音，但您也可以将其用于循环的环境音（如风声或雨声）。
* 加载存档文件时，循环的音效会被恢复。

---

## `volume`

设置音频音量

`volume` 标签用于设置特定音频轨道的音量。
它非常适合确保背景音乐不会盖过重要的音效或角色语音。

### 基本用法

```
# 将背景音乐音量设置为 50%
[volume track="bgm" volume="0.5"]
# 将音效音量设置为最大
[volume track="se" volume="1.0"]
# 语音静音
[volume track="voice" volume="0.0"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|---------------------------------------|-------------------------------------------|
| `track` | 否 | 要调整的音频轨道。 | 参见下方的“轨道”表。 |
| `volume` | 否 | 从 `0.0` 到 `1.0` 的音量级别。 | `0.0` 为静音，`1.0` 为最大音量。 |
| `time` | 是 (`0`) | 淡入淡出时间（秒）。 | `0` 表示即时变化。 |
### 轨道类型 (`track`)

Suika3 将音频分为三个主要轨道：

| 轨道名称 | 描述 |
|------------|----------------------------------|
| `bgm` | 背景音乐。 |
| `se` | 音效和系统声音。 |
| `voice` | 角色语音文件。 |

### 贴士

**即时变化**:
* 当 `time` 大于 `0` 时，音量变化会逐渐发生。
* `time="0"` 意味着即时变化。

**默认级别**:
* 在游戏开始时（例如在 `start` 标记中）设置您首选的音量级别是个好主意，这样玩家从一开始就能获得一致的体验。

---

## `skip`

设置跳过状态

`skip` 标签用于启用或禁用游戏内的跳过功能。
它对于防止玩家跳过重要的过场动画，或确保某些场景以预期的节奏体验非常有用。

### 基本用法

```
# 启用跳过功能
[skip enable="true"]
# 在关键场景中禁用跳过功能
[skip enable="false"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|----------------------------------------------|-------------------------------------------------------|
| `enable` | 否 | 跳过功能是否启用。 | 设置为 `true` 允许跳过，`false` 阻止跳过。 |

### 贴士

**过场控制**:
* 通常在启动时的标题 Logo 之前禁用跳过功能。

**恢复设置**:
* 关键场景结束后，别忘了设置 `[skip enable="true"]`。
* 玩家通常很感激能够自由跳过他们已经看过的文本。

**系统行为**:
* 此标签控制引擎的整体“跳过”状态。
* 即使玩家按下跳过热键，如果 `enable` 设置为 `false`，引擎也会忽略它。

---

## `config`

设置配置值

`config` 标签允许您直接从标记语言修改游戏系统的配置设置。
它对于动态调整游戏 UI 至关重要，例如移动消息框或即时更改系统级别的参数。

### 基本用法

```
# 更改消息框的位置
[config name="msgbox.x" value="100"]
[config name="msgbox.y" value="200"]
# 更新特定的系统设置
[config name="msgbox.font.size" value="24"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|----------------------------------------------------|----------------------------------------------------------|
| `name` | 否 | 要更改的配置参数名称。 | 请参阅系统的配置列表以获取有效名称。 |
| `value` | 否 | 分配给参数的新值。 | 值作为字符串处理，但可能代表数字。 |

### 贴士

**UI 自定义**:
* 您可以使用 `[config]` 在特定场景中重新定位消息框，以营造更具电影感的氛围。

**动态调整**:
* 由于可以在脚本的任何位置调用此标签，您可以随着故事的进展改变游戏的“外观和感觉”。
* 例如，为“倒叙”序列切换 UI。

**参数名称**:
* 小心 `name` 参数！
* 它必须与您的 Suika3 项目设置中定义的内部配置键名完全匹配。
* 另请参阅 [配置完整列表](config.md)

---

## `layer`

直接图层操作

`layer` 标签允许对特定的图像和文本图层进行直接控制。
虽然像 `[bg]` 和 `[ch]` 这样的标签对于标准场景来说更容易上手，但 `[layer]` 赋予了您独立修改任何单个图层的位置、缩放和旋转的精度。

### 基本用法

```
# 直接将图像加载到中央角色图层 (chc)
[layer name="chc" file="heroine_smile.png"]
# 仅调整背景 (bg) 的位置和透明度
[layer name="bg" x="100" y="100" alpha="128"]
# 旋转面部图层
[layer name="chf" rotate="45.0" center-x="100" center-y="100"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|-----------|-------------|--------------------------------------|------------------------------------|
| `name` | 否 | 目标图层名称。 | 参见下方的“图层名称”表。 |
| `file` | 是 | 要加载到图层上的文件名。 | 使用 `none` 清除图层。 |
| `x` | 是 (`0`) | 图层的 X 轴位置。 |                                    |
| `y` | 是 (`0`) | 图层的 Y 轴位置。 |                                    |
| `alpha` | 是 (`255`) | 图层的不透明度级别。 | `0` 到 `255`。 |
| `scale-x` | 是 (`1.0`) | X 轴缩放比例。 | `1.0` 为原始大小。 |
| `scale-y` | 是 (`1.0`) | Y 轴缩放比例。 | `1.0` 为原始大小。 |
| `center-x` | 是 (`0`) | 旋转中心 (X)。 | 旋转的支点。 |
| `center-y` | 是 (`0`) | 旋转中心 (Y)。 | 旋转的支点。 |
| `rotate` | 是 (`0.0`) | 旋转角度。 | 正值表示顺时针。 |

### 常见图层名称 (`name`)

Suika3 拥有丰富的预定义图层集合。

以下是图层的完整列表：

| 图层名称 | 描述 |
|-----------------|-----------------------------------------|
| bg | 背景图像 |
| bg2 | 背景图像 2 |
| efb1 | 背景特效 1 |
| efb2 | 背景特效 2 |
| efb3 | 背景特效 3 |
| efb4 | 背景特效 4 |
| chb | 后方-中央角色 |
| chb-eye | 后方-中央角色的眼睛 |
| chb-lip | 后方-中央角色的嘴唇 |
| chb-fo | 正在淡出的后方-中央角色 |
| chl | 左侧角色 |
| chl-eye | 左侧角色的眼睛 |
| chl-lip | 左侧角色的嘴唇 |
| chl-fo | 正在淡出的左侧角色 |
| chlc | 左侧-中央角色 |
| chlc-eye | 左侧-中央角色的眼睛 |
| chlc-lip | 左侧-中央角色的嘴唇 |
| chlc-fo | 正在淡出的左侧-中央角色 |
| chr | 右侧角色 |
| chr-eye | 右侧角色的眼睛 |
| chr-lip | 右侧角色的嘴唇 |
| chr-fo | 正在淡出的右侧角色 |
| chrc | 右侧-中央角色 |
| chrc-eye | 右侧-中央角色的眼睛 |
| chrc-lip | 右侧-中央角色的嘴唇 |
| chrc-fo | 正在淡出的右侧-中央角色 |
| chc | 中央角色 |
| chc-eye | 中央角色的眼睛 |
| chc-lip | 中央角色的嘴唇 |
| chc-fo | 正在淡出的中央角色 |
| msgbox | 消息框（对 `[layer]` 不可见） |
| namebox | 姓名框（对 `[layer]` 不可见） |
| click | 点击动画（对 `[layer]` 不可见） |
| eff1 | 前景特效 1 |
| eff2 | 前景特效 2 |
| eff3 | 前景特效 3 |
| eff4 | 前景特效 4 |
| chf | 面部特写角色 |
| chf-eye | 面部特写角色的眼睛 |
| chf-lip | 面部特写角色的嘴唇 |
| chf-fo | 正在淡出的面部特写角色 |
| text1 | 文本图层 1 |
| text2 | 文本图层 2 |
| text3 | 文本图层 3 |
| text4 | 文本图层 4 |
| text5 | 文本图层 5 |
| text6 | 文本图层 6 |
| text7 | 文本图层 7 |
| text8 | 文本图层 8 |
| gui1 | GUI 按钮 1（对 `[layer]` 不可见） |
| gui2 | GUI 按钮 2（对 `[layer]` 不可见） |
| gui3 | GUI 按钮 3（对 `[layer]` 不可见） |
| gui4 | GUI 按钮 4（对 `[layer]` 不可见） |
| gui5 | GUI 按钮 5（对 `[layer]` 不可见） |
| gui6 | GUI 按钮 6（对 `[layer]` 不可见） |
| gui7 | GUI 按钮 7（对 `[layer]` 不可见） |
| gui8 | GUI 按钮 8（对 `[layer]` 不可见） |
| gui9 | GUI 按钮 9（对 `[layer]` 不可见） |
| gui10 | GUI 按钮 10（对 `[layer]` 不可见） |
| gui11 | GUI 按钮 11（对 `[layer]` 不可见） |
| gui12 | GUI 按钮 12（对 `[layer]` 不可见） |
| gui13 | GUI 按钮 13（对 `[layer]` 不可见） |
| gui14 | GUI 按钮 14（对 `[layer]` 不可见） |
| gui15 | GUI 按钮 15（对 `[layer]` 不可见） |
| gui16 | GUI 按钮 16（对 `[layer]` 不可见） |
| gui17 | GUI 按钮 17（对 `[layer]` 不可见） |
| gui18 | GUI 按钮 18（对 `[layer]` 不可见） |
| gui19 | GUI 按钮 19（对 `[layer]` 不可见） |
| gui20 | GUI 按钮 20（对 `[layer]` 不可见） |
| gui21 | GUI 按钮 21（对 `[layer]` 不可见） |
| gui22 | GUI 按钮 22（对 `[layer]` 不可见） |
| gui23 | GUI 按钮 23（对 `[layer]` 不可见） |
| gui24 | GUI 按钮 24（对 `[layer]` 不可见） |
| gui25 | GUI 按钮 25（对 `[layer]` 不可见） |
| gui26 | GUI 按钮 26（对 `[layer]` 不可见） |
| gui27 | GUI 按钮 27（对 `[layer]` 不可见） |
| gui28 | GUI 按钮 28（对 `[layer]` 不可见） |
| gui29 | GUI 按钮 29（对 `[layer]` 不可见） |
| gui30 | GUI 按钮 30（对 `[layer]` 不可见） |
| gui31 | GUI 按钮 31（对 `[layer]` 不可见） |
| gui32 | GUI 按钮 32（对 `[layer]` 不可见） |

### 贴士

**精确控制**:
* 当您想手动将图像加载到图层时，请使用 `[layer]`，特别是当您在使用没有专用标签的自定义特效图层（如 `eff1` 等）时。

**即时更新**:
* 与 `[ch]` 或 `[bg]` 不同，`layer` 标签通常会即时更新屏幕。
* 如果您想随时间动画化这些更改，您应该改用 `[move]` 标签！

**图层层级**:
* 请记住图层是堆叠的。
* 例如，`chf`（面部特写角色）总是渲染在 `chc`（中央角色）的前面。
* 理解这种“Z轴顺序”是实现复杂视觉构图的关键。

---

## `move`

图层动画

`move` 标签用于在设定的持续时间内对特定图层进行动画处理。
它非常适合创建滑动效果、角色放大特写，或者旋转屏幕元素，为您的场景增添动态活力。

### 基本用法

```
# 在 2.0 秒内将中央角色移动到新位置
[move time="2.0" center-x="150" center-y="100"]
# 相对移动：将背景向右轻推 50 像素
[move time="1.0" bg-x="r50"]
# 在旋转的同时逐渐淡出图层
[move time="3.0" face-alpha="0" face-rotate="r360"]
```

### 参数

**通用参数：**

| 参数 | 是否可省略 | 描述 | 备注 |
|------------------|---------------|-------------------------------------------|--------------------------------------------|
| `name` | 否 | 要制作动画的目标图层。 | 参见下方的“可移动图层”表。 |
| `time` | 否 | 动画持续时间（秒）。 | 支持小数值（如 `0.5`）。 |
| `async` | 是 (`false`) | 如果为 `true`，则进行非阻塞动画。 |                                            |
| `accel` | 是 (`normal`) | 加速度类型。 | 可选值之一 |
| (图层)-(后缀) | 是 |                                           |                                            |

**(图层)：**

| 参数 | 描述 |
|----------------|-------------------------------------------|
| `bg` | 背景图层。 |
| `bg2` | 背景图层2。 |
| `back` | 后方-中央角色。 |
| `left` | 左侧角色。 |
| `right` | 右侧角色。 |
| `center` | 中央角色。 |
| `left-center` | 左侧-中央角色。 |
| `right-center` | Intermediate character. |
| `face` | 面部特写角色。 |

**(后缀)：**

| 后缀 | 是否可省略 | 描述 | 备注 |
|-------------|---------------|----------------------------|---------------------------------------------------------------|
| `-x` | 是 (`0`) | X 轴坐标。 | 支持绝对值（如 `100`）或相对值（如 `r50`）。 |
| `-y` | 是 (`0`) | Y 轴坐标。 | 支持绝对值（如 `100`）或相对值（如 `r-50`）。 |
| `-a` | 是 (`255`) | Alpha值。（不透明度） | `0`（透明）到 `255`（不透明）。 |
| `-scale-x` | 是 (`1.0`) | X 轴缩放比例。 | `1.0` 为原始大小。支持 `r` 前缀。 |
| `-scale-y` | 是 (`1.0`) | Y 轴缩放比例。 | `1.0` 为原始大小。支持 `r` 前缀。 |
| `-center-x` | 是 (`0`) | 旋转中心的 X 轴。 | 旋转效果的支点。 |
| `-center-y` | 是 (`0`) | 旋转中心的 Y 轴。 | 旋转效果的支点。 |
| `-rotate` | 是 (`0`) | 旋转角度。 | 正值表示顺时针。支持 `r` 前缀。 |
| `-dim` | 是 (`false`) | 变暗状态。 | 如果为 `true`，该图层将以 50% 的亮度渲染（变暗）。 |

### 贴士

**非阻塞动画 (`async="true"`)：**
* 脚本在启动 `[move]` 后会立即继续执行下一条命令。
* 如果您希望脚本等待动画完成，请在其后跟随一个具有相同 `time` 值的 `[wait]` 标签。

**相对变换**:
* 使用 `r` 前缀（例如 `x="r100"`）对于重复性动作非常有用，比如让角色“跳跃”或“摇晃”，而无需计算绝对坐标。

**视觉润色**:
* 将 `scale-x` 和 `scale-y` 与 `move` 结合使用，可以在角色的脸上创建“放大”效果，以实现戏剧性的特写镜头！

---

## `pencil`

绘图

在图层上绘制文本。

### 基本用法

```
[pencil layer="bg" font-size="30" text="Hello, World!"]
```

### 参数

| 参数 | 是否可省略 | 描述 |
|---------------|------------------|--------------------------|
| text | 否 | 要绘制的文本。 |
| layer | 是 (`text1`) | 图层名称。 |
| font-type | 是 (`0`) | 字体类型的选择。（0-3） |
| font-size | 是 (`16`) | 字体大小。 |
| color | 是 (`#000000`) | 字体颜色。 |
| outline-width | 是 (`0`) | 字体轮廓宽度。 |
| outline-color | 是 (`#ffffff`) | 字体轮廓颜色。 |
| line-margin | 是 | 行间距。 |
| char-margin | 是 (`0`) | 字符间距。 |
| x | 是 (`0`) | 绘制区域 X 轴位置。 |
| y | 是 (`0`) | 绘制区域 Y 轴位置。 |
| width | 是 | 绘制区域宽度。 |
| height | 是 | 绘制区域高度。 |

## 支持的图层名称

| 图层名称 | 描述 |
|-----------------|-----------------------------------------|
| bg | 背景图像 |
| bg2 | 背景图像 2 |
| efb1 | 背景特效 1 |
| efb2 | 背景特效 2 |
| efb3 | 背景特效 3 |
| efb4 | 背景特效 4 |
| chb | 后方-中央角色 |
| chl | 左侧角色 |
| chlc | 左侧-中央角色 |
| chr | 右侧角色 |
| chrc | 右侧-中央角色 |
| chc | 中央角色 |
| eff1 | 前景特效 1 |
| eff2 | 前景特效 2 |
| eff3 | 前景特效 3 |
| eff4 | 前景特效 4 |
| chf | 面部特写角色 |
| text1 | 文本图层 1 |
| text2 | 文本图层 2 |
| text3 | 文本图层 3 |
| text4 | 文本图层 4 |
| text5 | 文本图层 5 |
| text6 | 文本图层 6 |
| text7 | 文本图层 7 |
| text8 | 文本图层 8 |

---

## `returnmacro`

从宏返回

`returnmacro` 标签会立即退出当前宏，并将脚本执行权返回给原始 `[callmacro]` 标签之后的那一行。
当需要在 `[if]` 代码块内根据特定条件提前终止宏时，它特别有用。

### 基本用法

```
[defmacro name="check_item"]
    [if lhs="${has_key}" op="==" rhs="false"]
        [text text="The door is locked."]
        [returnmacro]
    [endif]
    # 只有当 has_key 为 true 时，这部分才会运行
    [text text="You unlocked the door with the key!"]
[endmacro]
```

### 参数

此标签不接受任何参数。

| 参数 | 是否可省略 | 描述 | 备注 |
|----------|-----------|-------------|-------|
| - | - | - | - |

### 贴士

**提前退出**:
* 在 `[if]` 代码块内使用 `[returnmacro]`，以便在满足特定条件时跳过宏的其余命令。
* 这能让您的宏更加灵活和强大！

**隐式返回**:
* 您实际上不需要在每个宏的最后都加上 `[returnmacro]`。
* 一旦引擎遇到 `[endmacro]` 标签，它就会自动返回到主脚本。

**流程控制**:
* 请记住，此标签仅退出*当前*宏。它不会停止整个游戏或跳转到不同的标签——它只是将您送回调用宏的地方。

---

## `video`

播放视频

`video` 标签在屏幕上播放视频文件。
它非常适合开场电影、过场动画，或者那些最好以全动态视频形式呈现的高冲击力视觉特效。

### 基本用法

```
# 播放开场电影（不可跳过）
[video file="opening.mp4"]
# 播放玩家可以点击跳过的短过场动画。
[video file="cutscene01.mp4" skippable="true"]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|-------------|---------------|-------------------------------------------------------|---------------------------------------------------------------|
| `file` | 否 | 要播放的视频文件名。 | 文件必须是支持的格式（如 .mp4）。 |
| `skippable` | 是 (`false`) | 玩家是否可以通过点击跳过视频。 | 设置为 `false` 强制玩家观看完整视频。 |

### 贴士

**文件支持**:
* 确保您的视频文件是 .mp4 (H.264 + AAC) 格式。
* 如果您想支持 32 位 Windows，请准备一个 .wmv 文件与 .mp4 文件并列，然后去掉扩展名，例如 `[video file="opening"]`。

**过渡处理**:
* 视频播放完毕（或被跳过）后，引擎会自动继续执行脚本中的下一条命令。
* 在 `[video]` 标签后面接一个 `[bg]` 标签通常是个好主意，以确保电影结束后屏幕显示完全符合您的预期。

**视频中的音频**：
* 大多数视频文件都包含自己的音轨。
* 请记住，这个音频会与您正在运行的任何 `[bgm]` 一起播放。
* 在播放有声音的视频之前，您可能想用 `[bgm file="none"]` 停止背景音乐！

---

## `wait`

等待时间

`wait` 标签会暂停 NovelML 执行指定的时长。
它对于控制视觉过渡的节奏、制造戏剧性停顿或不需玩家输入的情况下的定时特效至关重要。

### 基本用法

```
# 在下一条命令之前暂停 1.5 秒
[wait time="1.5"]
# 在角色变化之间制造短暂的停顿
[ch center="chara01_surprised.png" time="0.5"]
[wait time="1.0"]
[text text="She couldn't believe her eyes."]
```

### 参数

| 参数 | 是否可省略 | 描述 | 备注 |
|---------------|---------------|--------------------------------|----------------------------------------|
| `time` | 否 | 等待的秒数。 | 支持小数值（如 `0.5`）。 |
| `hidemsgbox` | 是 (`false`) | 强制隐藏消息框。 |                                        |
| `hidenamebox` | 是 (`false`) | 强制隐藏姓名框。 |                                        |

### 贴士

**非交互式暂停**:
* 与等待玩家行动的 `[click]` 不同，`[wait]` 时间一到就会自动继续。
* 这非常适合“自动播放”片段或定时的视觉序列。

**与动画结合**:
* 如果您使用带有 `time` 参数的 `[ch]` 或 `[bg]` 标签，引擎会立即移动到下一条命令，同时播放动画。
* 如果您希望脚本在动画完成后停止（或者为了戏剧效果停顿更久），请在动画后使用 `[wait]`。

**用户体验**:
* 注意不要让 `[wait]` 的时间太长（比如超过 3 秒）而没有视觉理由，否则玩家可能会以为游戏死机了！

