Игровые моды
Схема — это не только ИИ, который играет за вас, но и набор правил: вы сами играете в окне игры, а мод расставляет всё на старте, выпускает волны врагов, выдаёт награды, показывает вам на экране кнопки и карточки выбора и определяет исход. Унаследуйте openwar3.Mod — один файл, один геймплей.
ИИ-схемы бывают двух видов: kind: bot — это ИИ, который играет за вас; kind: mod — это набор правил: вы сами играете в окне игры, а мод ставит задачи — как всё расставить на старте, когда выпускать волны врагов (по времени или по событиям), какие давать награды, какие кнопки и карточки показать вам на экране, когда засчитать победу.
Мод использует только готовые возможности: интерфейс и ввод (кнопки, карточки, горячие клавиши, клики по земле), холст (панели, полоски прогресса, маршруты), JASS-канал (создание юнитов, изменение характеристик, выдача предметов), поток событий (гибель, повышение уровня, применение способностей, чат).
Два примера
Выбираются в Farsight: «ИИ-схемы» → «Встроенные»:
| Мод | Как играть | Что использует |
|---|---|---|
Рогалик с героем 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) # пустой слот как «игрок волн»: ни с кем не в союзе, без компьютерного ИИ
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: обычный бот тоже может сам объявить конец матча.
Оформить как схему и поделиться
В scheme.json укажите "kind": "mod", а в файле входа определите подкласс Mod:
{"id": "survive", "name": "Продержаться 10 волн", "kind": "mod", "entry": "survive.py", "class": "Survive"}
Мод всегда работает без честного режима (он судья, который ставит задачи: ему нужно видеть всю карту и менять мир) и не определяет исход по правилам обычного матча (исход сообщает finish); fair / judge в манифесте на него не действуют. Экспорт в zip, импорт, доверие и результаты — точно так же, как у схем-ботов, см. ИИ-схемы. Мод — тоже код, поэтому перед первым запуском чужого мода нужно так же подтвердить доверие.
Замеры
2026-09-25, тестовый экземпляр:
- Рогалик с героем: появилась первая волна, панель в правом верхнем углу обновляется; герой доведён до 3-го уровня → посреди экрана появились карточки, игровые часы остановились; два клика по карточкам → оба улучшения применились (сила 22 → 27), часы снова пошли.
- Бесконечная оборона: панель, маршрут на земле и кнопка на месте; F8 + клик по земле → рядом с ратушей появилась сторожевая башня; нажатие кнопки, пока волна ещё не зачищена → подсказка «Эта волна ещё не зачищена».
Ограничения
- Только одиночная игра: создание юнитов и изменение характеристик идут через JASS-канал, а в многопользовательской игре это вызывает рассинхронизацию. Так устроена модель lockstep; многопользовательским режимам придётся дождаться канала синхронизации (см. дорожную карту).
- Мод видит всю карту — он ставит задачи, а не играет.
- Компьютерный противник на картах для обычных матчей только «нейтрализован», но не удалён (удаление запустило бы проверку победы по правилам обычного матча).