Einen Mutator machen
Ein kleines .oamut über dem Grundspiel oder jedem Mod: der Ordner, das Manifest, der Plan, den mutate zurückgibt, Optionen, die Sandbox und die Reihenfolge eines Stapels.
Dieses Kapitel fasst docs/mutators/authoring.md und docs/mutators/oamut-standard.md zusammen.
Was ein Mutator ist
Ein Mutator ist ein kleines .oamut-Paket, geschichtet über das Grundspiel oder jeden Mod. Er ändert ein Match. Die Bibliothek installiert ihn in den Ordner Mutators unter der Kennung des Manifests, und das Installieren schaltet ihn nicht ein. Der Spieler schaltet ihn für ein Gefecht, einen Gefechtsraum oder eine Kampagne ein. works-with sagt, zu welchen Mods er passt, und ein Stern meint jeden Mod und das Grundspiel.
Das Paket
Oben im Ordner liegt oamut.yaml. Das Einstiegsskript liegt daneben: mutator.lua, außer entry nennt ein anderes, und nie unter files/, rules/ oder lua/. lua/ hält weiteren Lua-Quelltext, die einzigen Dateien, die require liest. files/ hält die Bytes, die die Schicht files hinzufügen darf. rules/ hält Regeldateien, deren Name auf .sm endet. Ein Icon ist das PNG, das das Manifest nennt. Eine Notiz, deren Name auf .md oder .txt endet, wird für Menschen mitgenommen, und das Spiel lädt sie nicht. Eine Datei außerhalb dieser Liste wird abgelehnt. Der Vergleich ignoriert die Großschreibung von ASCII-Buchstaben.
my-mutator.oamutdie Datei, die ein Spieler bekommt├─ oamut.yamlerforderlich das Manifest├─ mutator.luadas Einstiegsskript, mutate(ctx)├─ lua/optional; Lua-Module, die einzigen Dateien, die require liest├─ files/optional; Modelle, Skripte und andere Bytes├─ rules/optional; .sm-Regeldateien├─ icon.pngoptional; das PNG, das icon nennt└─ README.mdeine Notiz; das Spiel lädt sie nichtDas Manifest
Striktes YAML, dieselben Regeln wie ein Mod-Profil: ein Dokument, eine Abbildung auf oberster Ebene, keine Anker und keine Blockskalare. Die Datei beginnt mit oamut als Ganzzahl 1. Ein Schlüssel, den der Standard nicht aufführt, wird abgelehnt. Setze einen Wert in Anführungszeichen, der mit einem Größer-als-Zeichen beginnt, und auch einen Stern, sonst liest der Leser etwas anderes. requires.engine steht deshalb in Anführungszeichen. Eine Version auch: eine nackte Zahl wird abgelehnt.
| Schlüssel | Pflicht | Wirkung |
|---|---|---|
oamut | ja | Das Format. Die Ganzzahl 1. 1.0 und eine 1 in Anführungszeichen werden abgelehnt. |
id | ja | Kebab-Schreibweise in Kleinbuchstaben, 1 bis 64 Bytes. Kein Bindestrich am Anfang, am Ende oder doppelt. Der Name des Installationsordners. |
name | ja | 1 bis 64 Bytes, kein Steuerzeichen. Der Name, den Spieler sehen. |
version | ja | In Anführungszeichen, höchstens 32 Bytes. Ein bis drei Teile, mit einem Punkt verbunden, jeder eine Zahl von 0 bis 65535 ohne führende Null. |
author | ja | Eine Abbildung. name ist Pflicht, 1 bis 128 Bytes. email ist optional. |
description | nein | Optional, 1 bis 2.000 Bytes. Ein Zeilenumbruch ist erlaubt. Die erste Zeile, auf 200 Bytes gekürzt, ist die Zusammenfassung, die der Katalog zeigt. |
homepage | nein | Optional, 1 bis 256 Bytes. Eine http- oder https-Adresse. |
icon | nein | Optional. Der Paketpfad eines quadratischen PNG, endend auf .png. Der Installer prüft das Bild. |
tags | ja | Eine bis vier Kennungen, keine wiederholt. Die acht, die die Bibliothek zeichnet, stehen unten. |
works-with | ja | Eine bis 32 Bedingungen, keine Kennung doppelt. Ein Stern meint jeden Mod und das Grundspiel und ist dann der einzige Eintrag. ta-3.1c meint das Grundspiel ohne Mod. Jede andere Kennung ist ein Mod, mit optionalem Versionsbereich. |
requires | nein | Optional. Nur engine und mutators. engine ist ein Bereich in Anführungszeichen gegen diesen Build. mutators nennt Pakete, die an sein müssen; sie gelten vor diesem, in der geschriebenen Reihenfolge. |
conflicts-with | nein | Optional. Mutatoren, neben denen dieser nicht laufen will. Eine Kennung hier ist keine, die requires.mutators nennt, und nicht die eigene Kennung. |
layers | ja | Ein bis neun Namen, keiner wiederholt: files, units, weapons, features, sides, tables, menus, maps und hacks. Ein Plan darf nur eine Schicht schreiben, die hier genannt ist. |
clashes | nein | Optional, add oder replace: was dieser Mutator mit einer Einheit oder Waffe macht, deren Name schon im Spiel ist. Zuerst gilt die Wahl des Spielers, dann dieser Schlüssel, dann die Einstellung mutators.clash-default, die ohne Wert replace ist. |
options | nein | Optional, höchstens 16. Einstellungen, die der Spieler vor dem Match wählt. ctx.options liest sie. |
strings | nein | Optional, höchstens 16 Sprachkennungen. Übersetzungen des Namens, der Beschreibung und der Options-Beschriftungen. |
entry | nein | Optional. Das Einstiegsskript, ein Paketpfad, der auf .lua endet und nicht unter files/, rules/ oder lua/ liegt. Fehlt der Schlüssel, ist es mutator.lua. |
legacy | nein | Optional, 1 bis 16 Einträge von TA:-Mutation-Mutatoren, die dieses Paket ersetzt. Jeder Eintrag ist name, prefix, compatibility und files. Eine nackte Abbildung wird abgelehnt. |
Die acht Tags
Der Leser nimmt jedes Tag in Kebab-Schreibweise und Kleinbuchstaben an, 1 bis 32 Bytes, höchstens vier. Die Bibliothek zeichnet für diese acht Kennungen ein Icon und eine übersetzte Beschriftung, genau so geschrieben. Jede andere Kennung wird gezeigt, wie sie geschrieben wurde, ohne eigenes Icon. Nennt das Manifest kein Icon, nimmt das Badge das Icon des ersten Tags, wenn diese Kennung eine der acht ist.
| Schlüssel | Wirkung |
|---|---|
statistics | Werte |
economy | Wirtschaft |
commanders | Kommandanten |
new-units | Neue Einheiten |
disable | Verbote |
gameplay | Spielweise |
ai | KI |
maps | Karten |
Der Plan
Der Einstieg definiert mutate. Die Engine ruft mutate(ctx) einmal auf, in der Planphase, und dieser Aufruf ändert das Spiel nicht von selbst. mutate gibt eine Tabelle zurück. Eine leere Tabelle ändert nichts. Ein Schlüssel, den die Engine nicht kennt, wird abgelehnt.
files ist eine Tabelle aus add und mask. Jedes ist eine Liste von Text, und jedes darf fehlen. add nennt Ordner im Paket, der Reihe nach, und ein späterer Ordner gewinnt einen Pfad, den beide halten. mask verbirgt Pfade. rules ist eine Liste fertiger Blöcke, gemacht mit where, all, named oder on und dann :change, und von sm-Pfaden, die eine .sm-Datei nennen. Eine Änderung ist set, scale, lock, remove oder append. scale kann eine untere und eine obere Grenze nehmen, und die Grenze hält nur diesen einen Faktor. Die Hooks sind Funktionen. Sie laufen in dieser Reihenfolge: units, weapons, features, sides, tables, dann menus. maps läuft nach jedem Mutator, und nur wenn das Match eine Karte gewählt hat. hacks setzt für dieses eine Match einen Parameter, den die Registrierung für Mutatoren öffnet. Die Schicht zu erklären ist das, was das Schreiben erlaubt.
Optionen und ctx
Während mutate hält ctx den Mod (seine Kennung, Version und das Spiel), die Engine-Version, die Optionen und ctx.incompatible. ctx.mod.id ist ta-3.1c, wenn kein Mod an ist. ctx.incompatible mit einem Grund aufzurufen stoppt diesen Mutator, und der Grund ist der Text, den der Spieler sieht. Die Sammlungen sind noch nicht geladen. Ein Hook darf units, weapons, features, sides, tables und menus auf ctx lesen, ohne die Schicht zu erklären. Schreiben braucht die Schicht.
ctx.options hält ein Feld je Options-Kennung. Ein Schalter ist true oder false. Eine Zahl, und eine Wahl, deren Werte Zahlen sind, ist eine Zahl. Eine Wahl, deren Werte Bezeichner sind, ist Text. Eine Option, die der Spieler gelassen hat, ist der Standardwert. type ist toggle, choice oder number. Eine Wahl listet 2 bis 16 values, alle Zahlen oder alle Bezeichner, und labels, wenn die Wörter von den Werten abweichen. Eine Zahl hat min, max, step und default. Der Spieler kann nur einen Wert von min bis max wählen, der auf einem Schritt liegt, darum muss das Skript den Bereich nicht noch einmal prüfen: ein Wert neben den Schritten wird abgelehnt, bevor das Skript läuft. Die Options-Kennung ist ein Lua-Name, und ein Lua-Schlüsselwort wird abgelehnt.
Die Sandbox
Das Skript läuft als Lua in einer Sandbox. Es hat keine Datei, kein Netz, keine Uhr, keine Umgebung und keinen Prozess. io, os, debug, package und coroutine werden nicht geöffnet, und ein vorkompilierter Block wird abgelehnt. Jeder Block ist Quelltext. Zwei Mutatoren teilen keinen Zustand.
Jede Phase beginnt wieder beim vollen Befehlskontingent, 50.000.000, und beim vollen Echtzeitlimit von 10 Sekunden. Die Speichergrenze ist 64 MiB und wird für die nächste Phase nicht neu ausgegeben. Eine Zeichenkette ist höchstens 65.536 Bytes. Nimm fixed für einen Wert, den das Skript rechnet. Es zählt 65.536stel, damit dasselbe Skript auf jeder Maschine denselben Text schreibt. pairs geht Schlüssel in einer festen Reihenfolge durch. Das Ergebnis hängt nicht von der Maschine ab.
Stapeln
Der Spieler listet Mutatoren in einer Reihenfolge, von oben nach unten angewandt. Der erste gilt zuerst. Jeder spätere sieht das Spiel so, wie die darüber es gelassen haben. Mutatoren, die requires.mutators nennt, werden mit diesem eingeschaltet und gelten vor ihm, in der Reihenfolge, in der die Liste sie schreibt. Mehr als 32 Mutatoren, eine Kennung zweimal, eine Voraussetzung, die nichts darüber erfüllt, oder zwei, die sich widersprechen, lehnt die ganze Liste ab, und nichts läuft.
Die Dateien jedes Mutators werden zuerst geschichtet, in Listenreihenfolge, und ein späterer Mutator gewinnt einen Pfad. Dann liest jeder Mutator, in derselben Reihenfolge, seine eigenen Einheiten-, Waffen- und Download-Dateien als Einträge, wendet seine Regeln an und führt dann seine Hooks aus. Regeln wirken eine Änderung nach der anderen, in einer festen Reihenfolge. Ein Faktor multipliziert die aktuelle Zahl, und eine Klammer begrenzt nur diesen Faktor, nicht einen späteren. Eine Zuweisung ersetzt den aktuellen Wert. Eine Sperre setzt den Wert und hindert jeden späteren Mutator daran, dieses Feld zu ändern. In einem Lua-Block laufen die Änderungen nach dem Feldnamen in ASCII-Kleinbuchstaben, nicht in der Reihenfolge, in der die Tabelle geschrieben wurde. Zwischen Mutatoren wird nicht gemittelt. Nachdem jeder Mutator gewirkt hat, wird eine Einheiten- oder Waffenzahl jenseits der Breite, die das Spiel speichert, und eine Geländeobjekt-Zahl jenseits des Bereichs, den das Spiel liest, am Ende dieses Bereichs gehalten, einmal.