Docs Spielerweiterungen

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.

WegGeeignet fürEinstieg
Farsight-Seite „JASS-Konsole“manuell ausprobieren, zuschauen und anpassenSeitenleiste „System → JASS-Konsole“: Skript schreiben, auf Ausführen klicken; rechts Funktionen nach Kategorie nachschlagen, ein Klick fügt sie ins Skript ein
Kommandozeilemanuell ausprobieren oder als Skriptdatei immer wieder ausführenpython -m openwar3 jass --inst 20 (interaktiv), -e "Code", my_script.j, --list Stichwort
HTTPexterne Programme in jeder SprachePOST /api/instances/{n}/jass usw. (siehe unten); das Farsight-Backend lauscht nur lokal
PythonSchemata, Begleiter und Werkzeuge schreibeng.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 set gesetzten 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, .owner und .level lesen; Grundrechenarten und Vergleiche werden unterstützt.
  • Nicht unterstützt werden if, loop und function – für Logik nimm g.jass in 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 SignaturWas du übergibstHinweise
Ganzzahl (integer)Zahl; Vier-Zeichen-Codes wie 'Hpal' werden automatisch umgewandelt
Gleitkommazahl (real)Zahldie 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
Handleein Handle aus einer Variablen oder eine Einheit (etwa hero() wird automatisch in ein Handle umgewandelt)
Funktion (code)nur nullVon 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:

KategorieAnzahlBeispiele
Grafikeffekte80schwebender Text, Blitzverbindungen, Spezialeffekte, Bodenbilder, Bodenmarkierungen, Einheiten einfärben / skalieren / Animation abspielen
Oberfläche & Panels146Multiboards, Ranglisten, Countdown-Fenster, Dialoge, Quests, Bildschirmtext, Pings auf der Minikarte, Porträt-Dialog, Vollbildfilter
Kamera44Kamerafelder, Schwenks, Kamerawackeln
Sound & Musik50Sounds erstellen und abspielen, Musik abspielen
Nebel & Sicht25Sichtbereiche, Nebel ein-/ausschalten
Gegenstände / Helden / Einheiten63 / 32 / 161Gegenstände erstellen, Heldenstufe setzen, Besitzer wechseln, Fähigkeiten hinzufügen
Spieler / Bündnisse / Ressourcen71Bündnisse setzen, Gold und Holz ändern
Trigger / Ereignisse / Timer62Trigger erstellen, Ereignisse registrieren, Timer
Gelände / Wetter / Zerstörbare45Wettereffekte, Gelände ändern, zerstörbare Objekte erstellen
Spielablauf57Spielgeschwindigkeit, 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):

MethodeEffekt
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.

MethodeZweck
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: CreateTextTagUnitBJ und 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.