Gameplay-Mods
Ein Schema ist nicht nur eine KI, die für dich spielt – es kann auch ein Regelwerk sein: Du spielst selbst im Spielfenster, die Mod richtet den Start ein, schickt Gegnerwellen, verteilt Belohnungen, gibt dir Buttons und Auswahlkarten auf dem Bildschirm und entscheidet über Sieg und Niederlage. Von openwar3.Mod erben – eine Datei ist ein ganzes Spielprinzip.
KI-Schemata gibt es in zwei Arten: kind: bot ist eine KI, die für dich spielt; kind: mod ist ein Regelwerk – du spielst selbst im Spielfenster, und die Mod stellt die Aufgaben: wie der Start aussieht, wann nach Zeit oder Event Gegner erscheinen, welche Belohnungen es gibt, welche Buttons und Auswahlkarten du auf dem Bildschirm bekommst und wann du gewonnen hast.
Eine Mod nutzt ausschließlich vorhandene Fähigkeiten: Oberfläche & Eingabe (klickbare Buttons, Karten, Hotkeys, Klicks auf den Boden), Canvas (Panels, Fortschrittsbalken, Routen), JASS-Kanal (Einheiten erzeugen, Werte ändern, Gegenstände vergeben) und den Event-Stream (Tode, Stufenaufstiege, gewirkte Fähigkeiten, Chat).
Zwei Beispiele
In Farsight unter „KI-Schemata“ → „Eingebaut“ auswählbar:
| Mod | Spielprinzip | Genutzte Fähigkeiten |
|---|---|---|
Helden-Roguelike builtin/hero-roguelike | Du hast nur einen Paladin, und Welle um Welle rücken Gegner von allen Seiten an; bei jedem Stufenaufstieg wählst du in der Bildschirmmitte eine von drei Verstärkungen (das Spiel pausiert während der Wahl); überstehst du 10 Wellen, gewinnst du, stirbt der Held, verlierst du | g.ui.choice (klickbare Karten + Pause), Events hero.levelup / killed / spell.cast, Chat -help, Heldenwerte per JASS ändern, Gegenstände vergeben |
Endlose Verteidigung builtin/endless-defense | Gegner laufen vom gegenüberliegenden Startpunkt entlang der roten Linie am Boden auf dein Hauptgebäude zu; für jede abgewehrte Welle gibt es Gold; per Button auf dem Bildschirm oder mit F7 rufst du die nächste Welle früher, Belohnung ×1.5; F8 und dann Linksklick auf den Boden setzt einen kostenlosen Wachturm (Rechtsklick bricht ab) | g.ui.button, g.ui.hotkey, g.ui.mouse (Klicks auf den Boden abfangen), Canvas-Panel / Fortschrittsbalken / Route, Gegner erzeugen und Gold geben per JASS |
Beide Beispiele haben je etwa 150 Zeilen; der Code liegt in brains/examples/mod_hero_roguelike.py und brains/examples/mod_endless_defense.py.
python tools/play.py --bot brains/examples/mod_hero_roguelike.py --inst 9 # Spiel starten, die Mod übernimmt, du spielst im Spielfenster
Eine Mod schreiben
from openwar3 import Mod
class Survive(Mod):
name = "survive"
def on_start(self, g):
super().on_start(g) # Einzelspieler-Prüfung + Computergegner ruhigstellen
self.foe = self.wave_player(g) # ein leerer Slot als „Wellenspieler“: mit niemandem verbündet, keine Computer-KI
self.every(30, self.wave) # alle 30 Spielsekunden eine Welle (steht während der Pause)
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", "Hauptgebäude zerstört")
Mod bietet zusätzlich zu Bot:
| Methode / Attribut | Beschreibung |
|---|---|
on_start / on_tick / on_event / on_end | wie beim Bot; wenn du on_start / on_tick überschreibst, zuerst super() aufrufen |
every(Sekunden, fn, first=) / after(Sekunden, fn) | Timer nach Spielzeit, der Callback ist fn(g) |
finish(result, reason) | beendet die Partie ('win' / 'loss' / 'unknown'): Der Runner stoppt im nächsten Tick, in der Bildschirmmitte erscheint ein Ergebnis-Panel, und das Ergebnis des Schemas wird entsprechend erfasst |
wave_player(g) | erster leerer Spieler-Slot, als Wellenspieler gedacht |
spawn_ring(g, Spieler, Einheit, Anzahl, Mitte, Radius, attack_to=) | erzeugt Einheiten auf einem Kreis, auch Dutzende pro Welle ohne Ruckeln; gibt JASS-Handles zurück |
alive_of(g, Spieler) / attack_move_all(g, Spieler, Punkt) | lebende Einheiten eines Spielers / alle per Angriffsbewegung dorthin schicken (alle paar Sekunden aufrufen, dann verfolgen die Gegner dich) |
home(g) / hud(g, Titel, Zeilen) | Position deines Hauptgebäudes / Info-Panel oben rechts |
neutralize_ai = True | stellt den Computergegner beim Start ruhig: Seine Einheiten werden alle 5 Sekunden angehalten, Gold und Holz auf null gesetzt. Auf Melee-Karten gibt es immer einen Computergegner – wenn die Mod eigene Regeln macht, soll er nicht dazwischenfunken |
single_player_only = True | verweigert den Start, wenn weitere menschliche Spieler da sind (JASS, das die Welt verändert, würde bei anderen einen Desync auslösen) |
linger_s = 6 | wie viele Sekunden der Ergebnisbildschirm nach der Entscheidung stehen bleibt, bevor die Partie endet |
finish() gibt es auch auf Bot: Auch ein normaler Bot kann das Ende selbst verkünden.
Als Schema verpacken und teilen
In scheme.json "kind": "mod" eintragen und in der Einstiegsdatei eine Unterklasse von Mod definieren:
{"id": "survive", "name": "10 Wellen halten", "kind": "mod", "entry": "survive.py", "class": "Survive"}
Eine Mod läuft grundsätzlich nicht im Fair-Modus (sie ist der Schiedsrichter, der die Aufgaben stellt, und muss die ganze Karte sehen und die Welt verändern) und entscheidet Sieg und Niederlage nicht nach Melee-Regeln (das Ergebnis meldet finish); fair / judge im Manifest haben keine Wirkung. zip-Export, Import, Vertrauen und Ergebnisse funktionieren genau wie bei Bot-Schemata, siehe KI-Schemata. Auch eine Mod ist Code: Fremde Mods müssen vor dem ersten Start ebenfalls als vertrauenswürdig bestätigt werden.
Gemessen
2026-09-25, auf der Testinstanz:
- Helden-Roguelike: Die erste Welle erscheint, das Panel oben rechts läuft mit; Held auf Stufe 3 gebracht → Karten erscheinen in der Bildschirmmitte, die Spieluhr steht; zweimal eine Karte angeklickt → beide Verstärkungen wirken (Stärke 22 → 27), die Uhr läuft weiter.
- Endlose Verteidigung: Panel, Route am Boden und Buttons sind da; F8 + Klick auf den Boden → neben dem Hauptgebäude steht ein Turm mehr; Button geklickt, bevor die Welle erledigt ist → Hinweis „Diese Welle ist noch nicht erledigt“.
Grenzen
- Nur Einzelspieler: Einheiten erzeugen und Werte ändern läuft über den JASS-Kanal und führt im Multiplayer zu Desyncs. Das folgt aus dem Lockstep-Modell; Multiplayer-Spielprinzipien müssen auf einen Synchronisationskanal warten (siehe Roadmap).
- Eine Mod sieht die ganze Karte – sie stellt die Aufgaben, sie ist kein Spieler.
- Der Computergegner auf Melee-Karten wird nur „ruhiggestellt“, nicht entfernt (ein Entfernen würde nach Melee-Regeln einen Sieg auslösen).