JASS-Kanal
Die 1291 JASS-Funktionen, die Kartenautoren nutzen können, lassen sich jetzt von außerhalb des Spiels direkt per Name aufrufen: Einheiten erstellen, Eigenschaften ändern, Effekte, Panels, Dialoge, Sounds, Kamera, Nebel … Vier Wege: Farsight-Konsole, Kommandozeile, HTTP und Python.
Alle 1291 JASS-Natives, die Kartenautoren in Kartenskripten verwenden können, lassen sich jetzt von außerhalb des Spiels direkt per Name aufrufen: Einheiten erstellen, Eigenschaften ändern, Effekte zeichnen, Panels und Dialoge öffnen, Sounds abspielen, die Kamera bewegen, den Nebel ändern … Damit lässt sich das Spiel weiter anpassen – RPG-Helfer, KI-Begleiter, kleine eigene Spielmodi, Debug-Werkzeuge.
| Weg | Geeignet für | Einstieg |
|---|---|---|
| Farsight-Seite „JASS-Konsole“ | manuell ausprobieren, zuschauen und anpassen | Seitenleiste „System → JASS-Konsole“: Skript schreiben, auf Ausführen klicken; rechts Funktionen nach Kategorie nachschlagen, ein Klick fügt sie ins Skript ein |
| Kommandozeile | manuell ausprobieren oder als Skriptdatei immer wieder ausführen | python -m openwar3 jass --inst 20 (interaktiv), -e "Code", my_script.j, --list Stichwort |
| HTTP | externe Programme in jeder Sprache | POST /api/instances/{n}/jass usw. (siehe unten); das Farsight-Backend lauscht nur lokal |
| Python | Schemata, Begleiter und Werkzeuge schreiben | g.jass.BeliebigeFunktion(...); häufige Grafik- und Interaktionsfunktionen sind in openwar3.visual gekapselt |
Drei Grenzen, alle durch den Mechanismus bedingt:
- Nur in Einzelspieler-Partien (gegen den Computer auf deinem Rechner) lässt sich die Welt verändern. Legt dein Rechner einseitig Objekte an oder ändert Einheiten, geraten die anderen Spieler in Mehrspieler-Partien aus dem Takt (Desync) – dort sind nur lesende Funktionen erlaubt (
Get*,Is*,Count*…). - Nur für lokale Werkzeuge; Aufrufe über eine Spielerverbindung (
Game(player=N)) oder im Fair-Modus werden abgelehnt. - Nur für Offline-Spiele und selbst gehostete LAN-Spiele.
Um in Mehrspieler-Partien etwas aufs Spielbild zu bringen, nimm das Canvas: Die Runtime zeichnet es selbst, der Spielzustand bleibt unverändert.
Skriptsyntax
Konsole, Kommandozeile und HTTP verwenden dieselbe Skriptsprache. Eine Anweisung pro Zeile; JASS lässt sich direkt einfügen (call / set / local, true / false / null, Vier-Zeichen-Codes wie 'Hpal', //-Kommentare), Python-Schreibweise geht auch:
set h = hero() // eingebaut: eigener Haupt-Held
local texttag t = CreateTextTag()
call SetTextTagText(t, "|cffffcc00+128 Kritisch!|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("Erstellt:", u, "Heldenstufe", GetHeroLevel(h))
- Variablen bleiben erhalten: In derselben Instanz und derselben Partie kann der nächste Abschnitt die mit
setgesetzten Variablen weiterverwenden; bei einer neuen Partie werden sie automatisch geleert, du kannst sie auch manuell leeren. - Eingebaute Funktionen:
hero()eigener Haupt-Held,me()lokaler Spieler,unit('hfoo')sucht eine Einheit,unit_at(x, y),wait(Sekunden),print(...). Bei Einheiten lassen sich.x,.y,.hp,.hp_max,.mana,.type,.ownerund.levellesen; Grundrechenarten und Vergleiche werden unterstützt. - Nicht unterstützt werden
if,loopundfunction– für Logik nimmg.jassin Python (das sind ganz normale Funktionsaufrufe) oder schreib ein Schema. - Bei Fehlern erfährst du Zeile und Grund (Funktion existiert nicht, falsche Parameteranzahl, Variable nicht definiert …); Anweisungen vor dem Fehler sind bereits ausgeführt.
Parameter und Rückgabewerte:
| In der Signatur | Was du übergibst | Hinweise |
|---|---|---|
| Ganzzahl (integer) | Zahl; Vier-Zeichen-Codes wie 'Hpal' werden automatisch umgewandelt | |
| Gleitkommazahl (real) | Zahl | die Runtime wandelt sie ins Format der Engine um |
| Wahrheitswert (boolean) | true / false | |
| Zeichenkette (string) | "..." | chinesischer Text und die Farbcodes des Spiels werden unterstützt; Zeichenketten, die das Spiel speichert (schwebender Text, Panels, Buttons, Chat-Befehle), werden sofort kopiert – also sicher |
| Handle | ein Handle aus einer Variablen oder eine Einheit (etwa hero() wird automatisch in ein Handle umgewandelt) | |
| Funktion (code) | nur null | Von außen lässt sich keine JASS-Funktion übergeben; so etwas wie TimerStart(t, 60, false, null) funktioniert |
| Rückgabewert string | — | Die Engine liefert eine Nummer in der String-Tabelle, der Text lässt sich nicht zurücklesen. Für Einheitennamen g.map_data.name_of verwenden |
Kategorien
Die Funktionen sind nach ihrem Namen in Kategorien eingeteilt; die rechte Seite der Konsole und --list verwenden diese Einteilung:
| Kategorie | Anzahl | Beispiele |
|---|---|---|
| Grafikeffekte | 80 | schwebender Text, Blitzverbindungen, Spezialeffekte, Bodenbilder, Bodenmarkierungen, Einheiten einfärben / skalieren / Animation abspielen |
| Oberfläche & Panels | 146 | Multiboards, Ranglisten, Countdown-Fenster, Dialoge, Quests, Bildschirmtext, Pings auf der Minikarte, Porträt-Dialog, Vollbildfilter |
| Kamera | 44 | Kamerafelder, Schwenks, Kamerawackeln |
| Sound & Musik | 50 | Sounds erstellen und abspielen, Musik abspielen |
| Nebel & Sicht | 25 | Sichtbereiche, Nebel ein-/ausschalten |
| Gegenstände / Helden / Einheiten | 63 / 32 / 161 | Gegenstände erstellen, Heldenstufe setzen, Besitzer wechseln, Fähigkeiten hinzufügen |
| Spieler / Bündnisse / Ressourcen | 71 | Bündnisse setzen, Gold und Holz ändern |
| Trigger / Ereignisse / Timer | 62 | Trigger erstellen, Ereignisse registrieren, Timer |
| Gelände / Wetter / Zerstörbare | 45 | Wettereffekte, Gelände ändern, zerstörbare Objekte erstellen |
| Spielablauf | 57 | Spielgeschwindigkeit, Pause, Tageszeit |
| Sonstiges | … | Einheitengruppen und Regionen, Datenspeicherung, Computer-KI-Skripte, Typumwandlung und Mathematik, Ereignisantworten … |
Am 2026-09-24 wurden 94 davon einzeln im Live-Spiel aufgerufen und ihre Wirkung mit eigenen Augen geprüft; die übrigen laufen über denselben Weg, nur wurde ihre Wirkung nicht einzeln angesehen.
Funktionen der Kategorie „Ereignisantworten“ (GetTriggerUnit, GetClickedButton …) haben nur in dem Moment einen Wert, in dem ein Trigger ausgeführt wird; von außen aufgerufen liefern sie 0 oder nichts. Um zu erfahren, ob etwas passiert ist, nutze die Ereigniszähler weiter unten.
HTTP
Farsight-Backend (Standard 127.0.0.1:8866, lauscht nur lokal):
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": {...}}
-> bei Fehler: {"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 gemerkte Variablen löschen
Einheitenparameter schreibst du als {"unit": Adresse}; die Adresse ist das addr der Einheit im Snapshot. Gemessen: 60–90 ms pro Anfrage.
Python: g.jass und openwar3.visual
j = g.jass
t = j.CreateTextTag()
j.SetTextTagText(t, "Hallo", 0.024) # gleiche Parameterregeln wie im Skript; Einheiten- und Gegenstandsobjekte aus dem Snapshot lassen sich direkt übergeben
j.signature("CreateImage") # Signatur nachschlagen
openwar3.visual.Visual(g) verpackt erprobte, häufig genutzte Grafikeffekte in jeweils einen Aufruf (pro Tick einmal v.tick() aufrufen: Abgelaufenes wird entfernt, Linien und Kreise, die Einheiten folgen, werden nachgezogen; v.clear() entfernt alles):
| Methode | Effekt |
|---|---|
float_text(Text, Einheit oder Punkt, ...) | schwebender Text: Schadenszahlen, Hinweise über dem Kopf, auch mit chinesischem Text und Farben |
link(a, b, kind) | eine Linie zwischen zwei Einheiten, die ihnen folgt: Fessel / Geistverbindung / Lebensentzug / Heilwelle |
effect(Modell, Einheit oder Punkt, ...) | Effektmodell: über dem Kopf, unter den Füßen oder einmalig abgespielt (Explosion, Lichtsäule) |
ring(Einheit oder Punkt, Radius, color) | Bereichskreis am Boden: Zauberreichweite, Gefahrenzone, Sammelpunkt; kann einer Einheit folgen |
ping(Punkt, color) | Ping auf der Minikarte |
board(Titel, Zeilen...) | mehrzeiliges Panel oben rechts (mit Symbolen), Felder einzeln änderbar |
countdown(Titel, Sekunden) | Countdown-Fenster oben rechts, das Spiel zählt selbst herunter |
scene(Name, Text, portrait) | Porträt-Dialog: unten erscheint das Porträt einer sprechenden Einheit, auf dem Bildschirm der Untertitel „Name: Text“ |
screen_tint(color, alpha) | Vollbildfilter (Standard: roter Rand – Warnung bei niedrigen HP) |
sound(Pfad) / reveal(Punkt, Radius, Sekunden) / look(Einheit, ...) | Sound abspielen / Nebel in einem Bereich aufdecken / Einheit einfärben, vergrößern, Animation abspielen, aufblitzen lassen |
Interaktion: wissen, was der Spieler tut – ohne JASS-Funktionen zu schreiben
Um in JASS auf den Spieler zu reagieren, schreibt man Trigger-Funktionen – und von außen lässt sich keine Funktion übergeben. Die Lösung: einen leeren Trigger ohne Bedingungen und Aktionen anlegen, nur Ereignisse registrieren und zählen, wie oft er ausgeführt wurde. Im Test zählt auch ein leerer Trigger zuverlässig mit.
| Methode | Zweck |
|---|---|
chat_commands(["-follow", "-stay"]) → .poll() | Befehle, die der Spieler ins Chatfeld tippt (exakte Übereinstimmung oder Präfix) |
menu(Titel, [Buttons...]) → .clicked() | Button-Menü in der Bildschirmmitte: welcher Button geklickt wurde |
hotkeys(("left", "right", "up", "down", "esc")) → .poll() | wie oft die Pfeiltasten und Esc gedrückt wurden |
on("TriggerRegister...Event", Parameter...) → .poll() | wie oft ein beliebiges JASS-Ereignis eingetreten ist: Einheit stirbt, betritt eine Region, nimmt Schaden, Timer … |
Die Einschränkung: Du erfährst nur, „wie oft“ etwas passiert ist, nicht „wer, und was getippt wurde“. Um zu unterscheiden, wer es war, legst du für jedes Objekt einen eigenen Zähler an. Genau so sind die Chat-Befehle des KI-Begleiters angebunden.
Hinweise
- Was du erstellst, musst du selbst wieder löschen: Schwebender Text, Linien, Bodenbilder, Panels, Trigger … bleiben sonst für immer (
Visual.clear()löscht, was es selbst angelegt hat). Im Spiel gibt es gleichzeitig höchstens etwa 100 schwebende Texte. - BJ-Funktionen sind keine Natives:
CreateTextTagUnitBJund Co. werden im Kartenskript aus Natives zusammengesetzt und stehen hier nicht zur Verfügung – ruf die Natives so auf, wie es ihre Implementierung tut. - Manche Konstanten müssen erst umgewandelt werden: etwa
ConvertPlayerColor(1),ConvertFogState(4)(Werte siehe common.j). - Ein Aufruf dauert ca. 13 ms (inkl. Handle-Umrechnung); auf Protokollebene sind das die W3P-Opcodes 70–72, siehe W3P-Protokoll.