# JASS-канал

> 1291 функцию JASS, доступную авторам карт, теперь можно вызывать по имени извне игры: создавать юнитов, менять свойства, эффекты, панели, диалоги, звук, камеру, туман войны… Четыре способа: консоль Farsight, командная строка, HTTP и Python.

Источник: https://war3ai.com/ru/docs/jass/

**Все native-функции JASS (их 1291)**, которыми авторы карт пользуются в скриптах карт, теперь можно вызывать по имени извне игры: создавать юнитов, менять свойства, рисовать эффекты, показывать панели и диалоги, играть звуки, двигать камеру, менять туман войны… Это путь к дальнейшей настройке игры под себя: помощники для RPG, [ИИ-компаньон](https://war3ai.com/ru/docs/companion/), собственные мини-режимы, инструменты отладки.

| Способ | Для чего | Где |
|---|---|---|
| **Страница «JASS-консоль» в Farsight** | Пробовать вручную, смотреть и править на ходу | Левая панель «Система → JASS-консоль»: пишете скрипт и нажимаете «Выполнить», справа — функции по категориям, щелчок вставляет функцию в скрипт |
| **Командная строка** | Пробовать вручную или запускать файл-скрипт снова и снова | `python -m openwar3 jass --inst 20` (интерактивно), `-e "код"`, `my_script.j`, `--list слово` |
| **HTTP** | Внешние программы на любом языке | `POST /api/instances/{n}/jass` и др. (см. ниже), бэкенд Farsight слушает только локальный адрес |
| **Python** | Схемы, компаньоны, инструменты | `g.jass.ЛюбаяФункция(...)`; частые визуальные эффекты и взаимодействие обёрнуты в `openwar3.visual` |

> **Внимание**
>
> Три ограничения, и все продиктованы механикой:
> 
> - Менять мир можно только в **одиночной игре** (против компьютера на вашей машине). Если ваш компьютер в одностороннем порядке создаёт объекты и меняет юнитов, в многопользовательской игре у остальных игроков начнётся рассинхронизация, — поэтому там пропускаются только функции для чтения (`Get*`, `Is*`, `Count*`…).
> - Только для ваших локальных инструментов: вызовы через подключение от имени игрока (`Game(player=N)`) или в честном режиме отклоняются.
> - Только для одиночных игр и игр по локальной сети, созданных вами.
> 
> Чтобы добавить что-то на экран в многопользовательской игре, используйте [холст](https://war3ai.com/ru/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` — для логики используйте `g.jass` в Python (это обычные вызовы функций) или оформите всё как [схему](https://war3ai.com/ru/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 | Скорость игры, пауза, время суток |
| Прочее | … | Группы юнитов и области, хранилище, скрипты компьютерного ИИ, преобразование типов и математика, ответы на события… |

На 2026-09-24 в реальной игре по одной вызваны и проверены глазами **94 функции**; остальные работают по тому же пути, просто их эффект не проверялся для каждой по отдельности.

> **Примечание**
>
> Функции категории «ответы на события» (`GetTriggerUnit`, `GetClickedButton`…) имеют значение только в момент срабатывания триггера; при вызове извне они возвращают 0 или пустое значение. Чтобы узнать, «случилось ли событие», используйте счётчики событий, описанные ниже.

## HTTP

Бэкенд Farsight (по умолчанию `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: гибель юнита, вход в область, получение урона, таймер… |

Ограничение: известно только, «сколько раз это произошло», но не «кто это был и что именно напечатал». Чтобы различать, кто это был, заведите по счётчику на каждый объект. Именно так подключены команды чата у [ИИ-компаньона](https://war3ai.com/ru/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/ru/docs/protocol/).
