# JASS 通道

> 地图作者能用的 1291 个 JASS 函数，现在可以从游戏外面按名字直接调：造单位、改属性、特效、面板、对话框、声音、镜头、迷雾……远见控制台、命令行、HTTP、Python 四种用法。

来源: https://war3ai.com/docs/jass/

地图作者在地图脚本里能用的 **1291 个 JASS native**，现在都能从游戏外面按名字直接调用：造单位、改属性、画特效、弹面板和对话框、放声音、动镜头、改迷雾……拿来给游戏做进一步的自定义 —— RPG 辅助、[AI 玩伴](https://war3ai.com/docs/companion/)、自制小玩法、调试工具。

| 用法 | 适合 | 入口 |
|---|---|---|
| **远见「JASS 控制台」页** | 手动试、边看边改 | 左边栏「系统 → JASS 控制台」：写脚本点运行，右边按分类查函数，点一下插进脚本 |
| **命令行** | 手动试，或写成脚本文件反复跑 | `python -m openwar3 jass --inst 20`（交互）、`-e "代码"`、`my_script.j`、`--list 关键词` |
| **HTTP** | 任何语言的外部程序 | `POST /api/instances/{n}/jass` 等（见下文），远见后端只监听本机 |
| **Python** | 写方案、写玩伴、写工具 | `g.jass.任意函数(...)`；常用的画面和交互封装在 `openwar3.visual` |

> **注意**
>
> 三条边界，都是机制决定的：
> 
> - 只有**单人局**（和本机的电脑打）能改世界。本机单方面建对象、改单位会让多人局里其他玩家不同步 —— 多人局只放行只读的函数（`Get*`、`Is*`、`Count*`……）。
> - 只给本机自己的工具用；以玩家身份连接（`Game(player=N)`）或公平模式下调用会被拒绝。
> - 只用于单机、局域网自建的游戏。
> 
> 要在多人局里往画面上加东西，用 [画板](https://war3ai.com/docs/canvas/)：它是运行时自己画的，不改游戏状态。

## 脚本写法

控制台、命令行、HTTP 用的是同一套脚本。一行一句，**可以直接粘 JASS**（`call` / `set` / `local`、`true` / `false` / `null`、`'Hpal'` 四字码、`//` 注释），也可以写成 Python 的样子：

```text
set h = hero()                                   // 内置：我方主英雄
local texttag t = CreateTextTag()
call SetTextTagText(t, "|cffffcc00+128 暴击！|r", 0.024)
call SetTextTagPosUnit(t, h, 60)
call SetTextTagVelocity(t, 0, 0.03)
call SetTextTagPermanent(t, false)
call SetTextTagLifespan(t, 4)
call SetTextTagVisibility(t, true)
call PingMinimapEx(h.x, h.y + 300, 3, 255, 0, 0, false)
set u = CreateUnit(Player(0), 'hfoo', h.x + 200, h.y, 270)
print("造了", u, "英雄等级", GetHeroLevel(h))
```

- **变量一直记着**：同一个实例、同一局里，这一段 `set` 的变量下一段接着用；换局自动清空，也可以手动清。
- **内置函数**：`hero()` 我方主英雄、`me()` 本机玩家、`unit('hfoo')` 找一个单位、`unit_at(x, y)`、`wait(秒)`、`print(...)`。单位能读 `.x`、`.y`、`.hp`、`.hp_max`、`.mana`、`.type`、`.owner`、`.level`，支持四则运算和比较。
- **不支持** `if`、`loop`、`function` —— 要写逻辑，就用 Python 的 `g.jass`（它就是普通的函数调用），或者写成 [方案](https://war3ai.com/docs/schemes/)。
- 出错会告诉你第几行、为什么（没有这个函数、参数个数不对、变量没定义……）；出错之前的句子已经生效。

参数和返回值：

| 签名里 | 传什么 | 说明 |
|---|---|---|
| 整数 | 数字；`'Hpal'` 四字码自动转换 | |
| 实数 | 数字 | 运行时转成引擎要的格式 |
| 布尔 | `true` / `false` | |
| 字符串 | `"..."` | 支持中文和游戏的颜色码；会被游戏存起来的那些（浮动文字、面板、按钮、聊天命令）都是当场拷一份，安全 |
| 句柄 | 变量里的句柄，或者单位（`hero()` 这种会自动换成句柄） | |
| 函数（code） | 只能 `null` | 从外面给不出 JASS 函数；`TimerStart(t, 60, false, null)` 这种可以 |
| 返回字符串 | —— | 引擎返回的是字符串表编号，读不回文字。单位名字用 `g.map_data.name_of` |

## 分类

函数按名字分了类，控制台右边和 `--list` 都按这个分：

| 分类 | 个数 | 例子 |
|---|---|---|
| 画面效果 | 80 | 浮动文字、闪电连线、特效、地面贴图、地面印记、单位变色 / 缩放 / 播动作 |
| 界面面板 | 146 | 多行面板、排行榜、倒计时窗、对话框、任务、屏幕文字、小地图闪点、头像对白、全屏滤镜 |
| 镜头 | 44 | 镜头字段、平移、镜头抖动 |
| 声音音乐 | 50 | 创建和播放声音、放音乐 |
| 迷雾视野 | 25 | 可见区域、开关迷雾 |
| 物品 / 英雄 / 单位 | 63 / 32 / 161 | 造物品、设英雄等级、换主人、加技能 |
| 玩家 / 同盟 / 资源 | 71 | 设同盟、改金钱木材 |
| 触发器 / 事件 / 计时器 | 62 | 建触发器、注册事件、计时器 |
| 地形 / 天气 / 可破坏物 | 45 | 天气效果、改地形、造可破坏物 |
| 游戏流程 | 57 | 游戏速度、暂停、昼夜时间 |
| 其它 | …… | 单位组与区域、存储、电脑 AI 脚本、类型转换与数学、事件回应…… |

2026-09-24 逐个实机调用、亲眼看过效果的有 **94 个**；其余走的是同一条路，只是没有逐个看效果。

> **说明**
>
> 「事件回应」类函数（`GetTriggerUnit`、`GetClickedButton`……）只在触发器执行的那一刻有值，从外面调拿到的是 0 或空。想知道「发生了没有」，用下文的事件计数。

## HTTP

远见后端（默认 `127.0.0.1:8866`，只监听本机）：

```http
GET  /api/jass/natives?q=TextTag&cat=visual
POST /api/instances/20/jass        {"code": "set h = hero()\ncall PingMinimapEx(h.x, h.y, 3, 255, 0, 0, false)"}
     -> {"ok": true, "rows": [...], "printed": [...], "vars": {...}}
     -> 出错：{"ok": false, "error": "第 2 行：...", "line": 2}
POST /api/instances/20/jass/call   {"name": "SetUnitScale", "args": [{"unit": 599669636}, 1.4, 1.4, 1.4]}
POST /api/instances/20/jass/reset  清掉记住的变量
```

单位参数写 `{"unit": 地址}`，地址就是快照里单位的 `addr`。实测一次请求 60 ~ 90 ms。

## Python：g.jass 和 openwar3.visual

```python
j = g.jass
t = j.CreateTextTag()
j.SetTextTagText(t, "你好", 0.024)     # 参数规则和脚本一样；快照里的单位、物品对象可以直接传
j.signature("CreateImage")             # 查签名
```

`openwar3.visual.Visual(g)` 把实测过的常用画面效果封成一句话一个（每拍调一次 `v.tick()`：到期的删掉、跟着单位的线和圈挪过去；`v.clear()` 全删）：

| 方法 | 效果 |
|---|---|
| `float_text(文字, 单位或点, ...)` | 浮动文字：伤害数字、头顶提示，中文和颜色都行 |
| `link(a, b, kind)` | 两个单位之间一根线，跟着单位走：牵引 / 灵魂链 / 吸血 / 治疗波 |
| `effect(模型, 单位或点, ...)` | 特效模型：头顶、脚下，或者放一次（爆炸、光柱） |
| `ring(单位或点, 半径, color)` | 地上的范围圈：技能范围、危险区、集合点，可以跟随单位 |
| `ping(点, color)` | 小地图闪点 |
| `board(标题, 行...)` | 右上角多行面板（带图标），可以逐格改 |
| `countdown(标题, 秒)` | 右上角倒计时窗，游戏自己走秒 |
| `scene(名字, 话, portrait)` | 头像对白：底部头像换成会说话的单位，屏幕上出「名字：话」字幕 |
| `screen_tint(color, alpha)` | 全屏滤镜（默认四周泛红：残血警告） |
| `sound(路径)` / `reveal(点, 半径, 秒)` / `look(单位, ...)` | 放声音 / 驱散一片迷雾 / 单位变色、放大、播动作、闪一下 |

## 交互：不写 JASS 函数，也知道玩家做了什么

在 JASS 里响应玩家要写触发器函数，而从外面给不出函数。办法是：**建一个没有条件、没有动作的空触发器，只注册事件，然后数它执行了几次。** 实测空触发器照样计数。

| 方法 | 用途 |
|---|---|
| `chat_commands(["-follow", "-stay"])` → `.poll()` | 玩家在聊天框里打的命令（精确匹配，或按开头匹配） |
| `menu(标题, [按钮...])` → `.clicked()` | 屏幕中间的按钮菜单，点了哪一个 |
| `hotkeys(("left", "right", "up", "down", "esc"))` → `.poll()` | 方向键、Esc 按下了几次 |
| `on("TriggerRegister...Event", 参数...)` → `.poll()` | 任意 JASS 事件发生了几次：单位死亡、进入区域、受伤、计时器…… |

局限是只知道「发生了几次」，不知道「是谁、打了什么字」。要分清是谁，就给每个对象各建一个计数器。[AI 玩伴](https://war3ai.com/docs/companion/) 的聊天命令就是这样接上的。

## 注意

- **建出来的东西要自己删**：浮动文字、连线、贴图、面板、触发器……不删就一直在（`Visual.clear()` 会删它自己建的）。游戏里同时最多约 100 个浮动文字。
- **BJ 函数不是 native**：`CreateTextTagUnitBJ` 这类是地图脚本里用 native 拼出来的，这里没有 —— 照着它的实现调 native。
- **有些常量要先转换**：比如 `ConvertPlayerColor(1)`、`ConvertFogState(4)`（取值见 common.j）。
- 一次调用约 13 ms（含句柄换算）；协议层是 W3P 操作码 70 ~ 72，见 [W3P 协议](https://war3ai.com/docs/protocol/)。
