# JASS channel

> The 1291 JASS functions available to map makers can now be called by name from outside the game: create units, change properties, effects, boards, dialogs, sound, camera, fog… Four ways to use it: the Farsight console, the command line, HTTP and Python.

Source: https://war3ai.com/en/docs/jass/

The **1291 JASS natives** that map makers can use in map scripts can now all be called by name from outside the game: create units, change properties, draw effects, pop up boards and dialogs, play sounds, move the camera, change the fog… Use them to customize the game further — RPG helpers, an [AI companion](https://war3ai.com/en/docs/companion/), homemade mini-games, debugging tools.

| Usage | Good for | Where |
|---|---|---|
| **Farsight "JASS console" page** | Trying things by hand, tweaking as you watch | Sidebar "System → JASS console": write a script and click Run; the right side lists functions by category, click one to insert it into the script |
| **Command line** | Trying things by hand, or saving a script file to run again and again | `python -m openwar3 jass --inst 20` (interactive), `-e "code"`, `my_script.j`, `--list keyword` |
| **HTTP** | External programs in any language | `POST /api/instances/{n}/jass` and others (see below); the Farsight backend listens only on the local machine |
| **Python** | Writing schemes, companions and tools | `g.jass.AnyFunction(...)`; common visuals and interactions are wrapped in `openwar3.visual` |

> **Warning**
>
> Three boundaries, all dictated by how it works:
> 
> - Only **single-player games** (against the computer on your machine) can change the world. Creating objects or changing units unilaterally on your machine would desync the other players in a multiplayer game — so in multiplayer games only read-only functions (`Get*`, `Is*`, `Count*`…) are allowed.
> - It's only for your machine's own tools; calls made while connected as a player (`Game(player=N)`) or in fair mode are rejected.
> - Only for single-player and self-hosted LAN games.
> 
> To add things to the screen in a multiplayer game, use the [canvas](https://war3ai.com/en/docs/canvas/): the runtime draws it itself, and it doesn't change game state.

## Script syntax

The console, the command line and HTTP all use the same scripts. One statement per line; **you can paste JASS directly** (`call` / `set` / `local`, `true` / `false` / `null`, `'Hpal'` four-character codes, `//` comments), or write it Python-style:

```text
set h = hero()                                   // built-in: our main hero
local texttag t = CreateTextTag()
call SetTextTagText(t, "|cffffcc00+128 Critical!|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("created", u, "hero level", GetHeroLevel(h))
```

- **Variables persist**: within the same instance and the same game, variables you `set` in one snippet can be used in the next; they're cleared automatically when a new game starts, and you can also clear them manually.
- **Built-in functions**: `hero()` our main hero, `me()` the local player, `unit('hfoo')` finds a unit, `unit_at(x, y)`, `wait(seconds)`, `print(...)`. Units expose `.x`, `.y`, `.hp`, `.hp_max`, `.mana`, `.type`, `.owner` and `.level`, and arithmetic and comparisons are supported.
- **Not supported**: `if`, `loop`, `function` — for logic, use Python's `g.jass` (it's just ordinary function calls), or write a [scheme](https://war3ai.com/en/docs/schemes/).
- Errors tell you which line failed and why (no such function, wrong number of arguments, undefined variable…); statements before the error have already taken effect.

Arguments and return values:

| In the signature | What to pass | Notes |
|---|---|---|
| integer | A number; `'Hpal'` four-character codes are converted automatically | |
| real | A number | The runtime converts it to the format the engine expects |
| boolean | `true` / `false` | |
| string | `"..."` | Chinese text and the game's color codes are supported; strings the game keeps (floating text, boards, buttons, chat commands) are copied on the spot, so it's safe |
| handle | A handle held in a variable, or a unit (things like `hero()` are converted to handles automatically) | |
| function (code) | Only `null` | A JASS function can't be passed in from outside; something like `TimerStart(t, 60, false, null)` works |
| string return value | — | The engine returns a string table index, so the text can't be read back. For unit names, use `g.map_data.name_of` |

## Categories

Functions are grouped into categories by name; the console's right panel and `--list` both use these:

| Category | Count | Examples |
|---|---|---|
| Visual effects | 80 | Floating text, lightning links, special effects, ground images, ground splats, unit tint / scale / animations |
| Interface and boards | 146 | Multiboards, leaderboards, timer windows, dialogs, quests, on-screen text, minimap pings, portrait dialogue, full-screen filters |
| Camera | 44 | Camera fields, panning, camera shake |
| Sound and music | 50 | Creating and playing sounds, playing music |
| Fog and vision | 25 | Visibility modifiers, toggling fog of war |
| Item / hero / unit | 63 / 32 / 161 | Create items, set hero level, change owner, add abilities |
| Player / alliance / resources | 71 | Set alliances, change gold and lumber |
| Trigger / event / timer | 62 | Create triggers, register events, timers |
| Terrain / weather / destructable | 45 | Weather effects, changing terrain, creating destructables |
| Game flow | 57 | Game speed, pause, time of day |
| Other | … | Unit groups and regions, storage, computer AI scripts, type conversion and math, event responses… |

On 2026-09-24, **94** of them were called one by one in a live game and their effects checked by eye; the rest go through the same path, just without each effect being checked individually.

> **Note**
>
> Event response functions (`GetTriggerUnit`, `GetClickedButton`…) only have a value at the moment a trigger runs; called from outside, they return 0 or null. To find out whether something happened, use the event counters described below.

## HTTP

Farsight backend (default `127.0.0.1:8866`, listens only on the local machine):

```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": {...}}
     -> on error: {"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  clear the remembered variables
```

For a unit argument, write `{"unit": addr}`, where `addr` is the unit's `addr` in the snapshot. Measured at 60–90 ms per request.

## Python: g.jass and openwar3.visual

```python
j = g.jass
t = j.CreateTextTag()
j.SetTextTagText(t, "Hello", 0.024)    # same argument rules as scripts; unit and item objects from the snapshot can be passed directly
j.signature("CreateImage")             # look up a signature
```

`openwar3.visual.Visual(g)` wraps the tested, commonly used visual effects into one-liners (call `v.tick()` once per tick: it removes expired effects and moves the lines and circles that follow units; `v.clear()` removes everything):

| Method | Effect |
|---|---|
| `float_text(text, unit_or_point, ...)` | Floating text: damage numbers, overhead hints; Chinese text and colors both work |
| `link(a, b, kind)` | A line between two units that follows them: magic leash / spirit link / life drain / healing wave |
| `effect(model, unit_or_point, ...)` | Special effect model: overhead, at the feet, or played once (explosion, pillar of light) |
| `ring(unit_or_point, radius, color)` | Range circle on the ground: ability range, danger zone, rally point; can follow a unit |
| `ping(point, color)` | Minimap ping |
| `board(title, rows...)` | Multi-row board in the top-right corner (with icons); cells can be updated one by one |
| `countdown(title, seconds)` | Timer window in the top-right corner; the game counts down the seconds itself |
| `scene(name, line, portrait)` | Portrait dialogue: the portrait at the bottom switches to a talking unit, and a "Name: line" subtitle appears on screen |
| `screen_tint(color, alpha)` | Full-screen filter (by default a red glow around the edges: a low-health warning) |
| `sound(path)` / `reveal(point, radius, seconds)` / `look(unit, ...)` | Play a sound / clear the fog over an area / tint, scale, animate or flash a unit |

## Interaction: knowing what the player did without writing JASS functions

Responding to the player in JASS means writing trigger functions, and a function can't be passed in from outside. The workaround: **create an empty trigger with no conditions and no actions, register only the event, and count how many times it has run.** Testing confirmed that an empty trigger still counts.

| Method | Use |
|---|---|
| `chat_commands(["-follow", "-stay"])` → `.poll()` | Commands the player types in the chat box (exact match, or prefix match) |
| `menu(title, [buttons...])` → `.clicked()` | A button menu in the middle of the screen, and which button was clicked |
| `hotkeys(("left", "right", "up", "down", "esc"))` → `.poll()` | How many times the arrow keys and Esc were pressed |
| `on("TriggerRegister...Event", args...)` → `.poll()` | How many times any JASS event happened: unit death, entering a region, taking damage, timers… |

The limitation is that you only know how many times something happened, not who did it or what they typed. To tell who, create a separate counter for each object. That's how the [AI companion](https://war3ai.com/en/docs/companion/)'s chat commands are wired up.

## Caveats

- **Clean up what you create**: floating text, links, images, boards, triggers… stay around until removed (`Visual.clear()` removes the ones it created). The game can show at most about 100 floating texts at once.
- **BJ functions aren't natives**: functions like `CreateTextTagUnitBJ` are built out of natives in the map script and aren't available here — call the natives the way their implementation does.
- **Some constants need converting first**: e.g. `ConvertPlayerColor(1)`, `ConvertFogState(4)` (see common.j for the values).
- One call takes about 13 ms (including handle conversion); at the protocol level these are W3P opcodes 70–72; see [W3P protocol](https://war3ai.com/en/docs/protocol/).
