文档 玩法扩展

JASS 通道

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

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

用法适合入口
远见「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))或公平模式下调用会被拒绝。
  • 只用于单机、局域网自建的游戏。

要在多人局里往画面上加东西,用 画板:它是运行时自己画的,不改游戏状态。

脚本写法

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

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(它就是普通的函数调用),或者写成 方案。
  • 出错会告诉你第几行、为什么(没有这个函数、参数个数不对、变量没定义……);出错之前的句子已经生效。

参数和返回值:

签名里传什么说明
整数数字;'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,只监听本机):

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

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 玩伴 的聊天命令就是这样接上的。

注意

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