文档 玩法扩展
玩法模组
方案不只是一个替你打的 AI,也可以是一套规则:你自己在游戏窗口里玩,模组负责布置开局、刷怪、给奖励、在屏幕上给你按钮和选项卡、判胜负。继承 openwar3.Mod,一个文件就是一套玩法。
AI 方案 有两种:kind: bot 是一个 AI,替你打;kind: mod 是一套规则 —— 你自己在游戏窗口里玩,模组出题:开局怎么布置、按时间或事件刷怪、给什么奖励、屏幕上给你哪些按钮和选项卡、什么时候算赢。
模组用到的全是现成的能力:界面与输入(能点的按钮、卡片、热键、点地面)、画板(面板、进度条、路线)、JASS 通道(刷单位、改属性、给物品)、事件流(死亡、升级、放技能、聊天)。
两个示例
在远见的「AI 方案」→「内置」里就能选:
| 模组 | 玩法 | 用到的能力 |
|---|---|---|
英雄肉鸽 builtin/hero-roguelike | 你只有一个圣骑士,怪一波波从四面围上来;每升一级,屏幕中间三选一强化(选的时候游戏暂停);撑过 10 波就赢,英雄死了就输 | g.ui.choice(可点卡片 + 暂停)、hero.levelup / killed / spell.cast 事件、聊天 -help、JASS 改英雄属性、给物品 |
无尽守城 builtin/endless-defense | 怪从对面出生点沿地上的红线冲向主城;每守住一波给金子;点屏幕按钮或按 F7 提前叫下一波,奖励 ×1.5;按 F8 再左键点地面,放一座免费箭塔(右键取消) | g.ui.button、g.ui.hotkey、g.ui.mouse(抓地面点击)、画板面板 / 进度条 / 路线、JASS 刷怪和加金子 |
两个示例各 150 行左右,代码在 brains/examples/mod_hero_roguelike.py 和 brains/examples/mod_endless_defense.py。
python tools/play.py --bot brains/examples/mod_hero_roguelike.py --inst 9 # 起一局,模组接管,你在游戏窗口里玩
写一个模组
from openwar3 import Mod
class Survive(Mod):
name = "survive"
def on_start(self, g):
super().on_start(g) # 单人局检查 + 压住电脑对手
self.foe = self.wave_player(g) # 一个空槽玩家当「刷怪方」:和谁都不结盟、没有电脑 AI
self.every(30, self.wave) # 每 30 游戏秒一波(暂停时不走)
g.ui.hotkey("F7", lambda g, ev: self.wave(g))
def wave(self, g):
self.spawn_ring(g, self.foe, "ugho", 6, self.home(g), 1400, attack_to=self.home(g))
def on_event(self, g, ev):
if ev.kind == "unit.died" and ev.type == "htow":
self.finish("loss", "主城被推了")
Mod 在 Bot 的基础上多了这些:
| 方法 / 属性 | 说明 |
|---|---|
on_start / on_tick / on_event / on_end | 和 Bot 一样;覆盖 on_start / on_tick 时记得先调 super() |
every(秒, fn, first=) / after(秒, fn) | 按游戏时间走的定时器,回调是 fn(g) |
finish(result, reason) | 结束这一局('win' / 'loss' / 'unknown'):运行器下一拍停,屏幕中间画结果面板,方案战绩按它记 |
wave_player(g) | 第一个空槽玩家,拿来当刷怪方 |
spawn_ring(g, 玩家, 单位, 个数, 中心, 半径, attack_to=) | 在一圈上刷单位,一波几十个也不卡;返回 JASS 句柄 |
alive_of(g, 玩家) / attack_move_all(g, 玩家, 点) | 某个玩家的活单位 / 全部攻击移动过去(隔几秒调一次,怪就会追着走) |
home(g) / hud(g, 标题, 行) | 我方主城的位置 / 右上角的信息面板 |
neutralize_ai = True | 开局把电脑对手压住:它的单位每 5 秒暂停一遍,金木清零。对战图里总有一个电脑,模组自己定规则时不要它搅局 |
single_player_only = True | 有别的真人玩家就拒绝运行(改世界的 JASS 会让别人不同步) |
linger_s = 6 | 分出胜负后,在结果画面停几秒再结束 |
finish() 在 Bot 上也能用:普通 Bot 也可以自己宣布结束。
做成方案、分享
scheme.json 里写 "kind": "mod",入口文件里定义一个 Mod 的子类:
{"id": "survive", "name": "坚守 10 波", "kind": "mod", "entry": "survive.py", "class": "Survive"}
模组固定不走公平模式(它是出题的裁判,要看全图、改世界),也不按对战规则判胜负(胜负由 finish 报);说明书里写了 fair / judge 也不起作用。导出 zip、导入、信任、战绩和 Bot 方案完全一样,见 AI 方案。模组也是代码,别人的模组第一次运行前同样要确认信任。
实测
2026-09-25,演练实例上:
- 英雄肉鸽:第一波刷出来,右上角面板在走;把英雄提到 3 级 → 屏幕中间弹出卡片、游戏时钟停住;点两次卡片 → 两次强化生效(力量 22 → 27),时钟恢复。
- 无尽守城:面板、地上的路线、按钮都在;F8 + 点地面 → 主城边上多了一座防御塔;这一波还没清完就点按钮 → 提示「这一波还没清完」。
边界
- 只能单人局:刷单位、改属性走 JASS 通道,多人局里会不同步。这是锁步模型决定的,多人玩法要等同步通道(见 路线图)。
- 模组看全图 —— 它是出题的,不是玩家。
- 对战图里的电脑对手只是被「压住」,没有被移除(移除会触发对战规则的胜利判定)。