Alle Formatseiten ↓
Tutorials und Nachschlagewerk

Häufige Stolperfallen beim Modding und Parsen

Aus coreprime/kbot @ 0ab97bf · Auf GitHub bearbeiten

Ein Spickzettel auf einer Seite mit den häufigsten Stolperfallen aus den Formatdokumenten von kbot. Wenn du einem Fehler nachjagst, der keinen Sinn ergibt, fang hier an. Jeder Punkt verlinkt auf die ausführlichere Erklärung auf der jeweiligen Formatseite.

Tip

Suchst du nach „mein Mod lädt nicht“? Die Semikolon-Regel für TDF (TDF / FBI / OTA, erster Punkt) ist für mehr Meldungen über „stilles Kaputtgehen“ verantwortlich als alle anderen Stolperfallen zusammen.


HPI / UFO / CCX / GP3

  • Lose Dateien im Wurzelverzeichnis der Installation haben Vorrang vor jedem Archiv. Leg units/MYUNIT.fbi auf die Platte, und die Engine zieht sie allem in totala1.hpi vor. Das Schichtungsdiagramm in hpi.md zeigt die vollständige Rangfolge.
  • Unter den Archiven gewinnt das zuerst eingehängte, und es werden nur zehn *.hpi eingehängt. TA 3.1c hängt rev31.gp3 ein, dann *.ccx, *.ufo und die ersten zehn *.hpi, die sich öffnen lassen, jede Gruppe nach dem großgeschriebenen ASCII-Namen sortiert. Ein Mod, der als zz_mod.hpi ausgeliefert wird, rangiert unter jedem Archiv der Verkaufsversion. Hat die Installation schon zehn *.hpi, die davor einsortiert werden, wird er nur noch über den CD-Scan eingehängt – unter allem anderen. Liefere Mods als .ufo aus.
  • Zeiger in HPI v1 beziehen sich absolut auf den Dateianfang, nicht auf den Anfang des Verzeichnisses. Zieh nichts ab. Der Trick der kanonischen Parser besteht darin, einen Puffer von DirectorySize Byte anzulegen und das Verzeichnis entschlüsselt ab Offset Start hineinzuschreiben, damit die Zeiger den Puffer direkt indizieren. Siehe Verzeichnisbaum.
  • Der Seed der Chiffre von HPI v1 läuft mit der Dateiposition mit. Du kannst einen Puffer nicht isoliert entschlüsseln – du musst wissen, von welchem absoluten Datei-Offset er stammt. Siehe Den Chiffrierschlüssel ableiten.
  • Ist DecryptKey == 0, wende die XOR-Chiffre gar nicht an. Manche selbst gebauten Archive werden unverschlüsselt ausgeliefert; wendest du die Chiffre trotzdem an, verwürfelst du, was bereits lesbar ist.
  • Die Prüfsumme der SQSH-Chunks wird über die verschlüsselten Bytes berechnet. Prüfe sie vor dem Entwürfeln. Siehe Komprimierte Chunks (SQSH).
  • TA: Kingdoms verwendet HPI v2 (Version == 0x00020000) mit einem anderen Aufbau – kein XOR, ein einziger SQSH-Chunk pro Datei. Lies den Abschnitt TA: Kingdoms – HPI v2, bevor du den v1-Parser an einem TAK-Archiv ausprobierst.
  • Spielstände mit dem Marker BANK sind etwas ganz anderes – sie verwenden die HPI-Hülle wieder, aber der Inhalt ist serialisierter Spielzustand, kein Dateisystem. kbot dekodiert sie nicht.
  • .gp3 setzt den Patch rev3.1 voraus. Innen ist es nach wie vor HPI, aber ein ungepatchtes TA weigert sich, es einzuhängen.

TDF / FBI / OTA

  • Jeder Wert muss mit ; enden. Fehlende Semikolons verschmelzen Werte stillschweigend über Zeilen hinweg und führen zu völlig falschen Einheitenwerten. Das ist die Ursache Nr. 1 für „meine Einheit hat seltsame Trefferpunkte / keine Beschreibung / falsche Kosten“.
  • Schlüssel unterscheiden nicht zwischen Groß- und Kleinschreibung, Werte schon. Side=arm funktioniert bei den meisten Abfragen, scheitert aber an jedem Mod-Code, der Side per String-Vergleich prüft.
  • Listenwerte sind durch Leerzeichen getrennt (Category=COMMANDER MOBILE WEAPON) – nicht durch Kommas. Die Ausnahme ist numplayers=2,4,6,8,10 in der OTA, das Kommas verwendet.
  • Boolesche Werte sind die Ganzzahlen 1/0, nicht true/false. Die Engine akzeptiert nur die ganzzahligen Formen.
  • Bearbeite für Mods nie sidedata.tdf, um Einheiten hinzuzufügen. Nimm stattdessen eine [MENUENTRY]-Registrierung in download/<UNITNAME>.tdf – denselben Mechanismus, den Core Contingency verwendet. Siehe TDF: [MENUENTRY] und das Modding-Tutorial.
  • Bmcode=0 blendet eine Einheit aus dem Baumenü aus, auch wenn alles andere gültig ist. Fast immer willst du Bmcode=1.
  • Eine Einheit, die bei keiner Baueinheit aufgeführt ist, kann nicht gebaut werden, auch wenn ihre FBI ansonsten gültig ist. Der häufigste Fehler der Art „meine neue Einheit existiert, ist aber nicht baubar“. Siehe Modding, Schritt 5.
  • Die Verschachtelungstiefe von Abschnitten ist Konvention, keine Spezifikation. Manche Werkzeuge gehen von 2 Ebenen aus; Waffen-TDFs reichen 3 Ebenen tief ([WEAPON][DAMAGE][category]).

TNT / SCT – Kartengelände

  • Width und Height einer TNT zählen Attributzellen zu 16 px, weder Kacheln noch Pixel. Geteilt durch 2 ergibt sich die Zahl der Kacheln, mal 16 die Größe in Pixeln. Siehe TNT-Header.
  • SeaLevel == 0 bedeutet NICHT „kein Wasser“ – es bedeutet, dass der kleinstmögliche Wert auf der Schwelle liegt, also nichts unter Wasser ist. Nimm SeaLevel = 1 für wirklich trockene Karten.
  • Ein Objektwort einer TNT platziert nur dann ein Kartenobjekt, wenn es kleiner als die Zahl der Einträge in der Objekttabelle ist. 0xFFFC ist leer; 0xFFFE (Lava Run, AC02), 0xFFFD und jedes andere Wort ab der Tabellengröße platzieren nichts, und die Zelle bleibt bebaubar.
  • Die Auffüllung der Minikarte einer TNT verwendet Palettenindex 0x64, und die Größe des Kartenbereichs wird aus der Karte berechnet (längere Seite 252, Seitenverhältnis der sichtbaren Karte), nicht durch Suche nach der Auffüllung ermittelt. Das Spiel liest die gespeicherte Minikarte nur, wenn Bit 0 des Header-Worts bei 0x2c gesetzt ist. Siehe TNT.
  • Die .tnt von TA: Kingdoms verwendet IDVersion == 0x4000 statt 0x2000 wie TA (TA liest außerdem einen älteren Aufbau 0x1020). kbot tnt image erzeugt bei TNTs von TAK nur Müll; der Kachel-Decoder ist TA-spezifisch. Siehe TA:K-Karten.
  • SCT-Sektionen müssen in beiden Dimensionen ein Vielfaches von 4 sein, damit TAE sie lädt. Das Format auf der Platte erlaubt andere Größen, aber der Editor lehnt sie mit „section misaligned“ ab.
  • SCT V2 hat Höhenzellen zu 8 Byte, V3 solche zu 4 Byte. kbot akzeptiert beide; Mods, die mit dem Editor gebaut wurden, sehen nur V3.

3DO – Modelle

  • Oben ist Y, nicht Z. Wer ein 3DO ohne Achsentausch in eine Engine mit Z nach oben importiert (Blender, modernes Unreal), sieht jede Einheit auf der Seite liegen.
  • Untexturierte Primitive sind unsichtbar, sofern nicht IsColored != 0 gilt – der Pseudocode visible = (texture != "") || (IsColored != 0) deckt beide Fälle ab. Der häufigste Fehler beim Rendern von 3DO.
  • OffsetToSelectionPrim hat nur beim Wurzelobjekt eine Bedeutung; Kindobjekte müssen es auf -1 (0xFFFFFFFF) setzen.
  • Die Festkomma-Skalierung ist 1 / 65536. Ein als 0x00010000 geschriebener Vertex entspricht 1,0 Welteinheiten; die unteren 16 Bit sind der Nachkommaanteil.
  • Vertices sind objektlokal, nicht global. Zwei Objekte können identische Vertex-Arrays haben – das ist gespiegelte Geometrie, keine gemeinsam genutzten Daten.

COB / BOS – Skripte

  • Der Opcode von call-script ist 0x10062000, NICHT 0x10063000, wie manche Dokumente aus der Zeit vor 3.1 behaupten. Alte Decompiler, die 0x10063000 verwenden, erzeugen Unsinn – siehe die Opcode-Referenz.
  • Piece-Nummern in Opcodes sind Indizes in die Namenstabelle der Pieces, keine Strings. Die COB führt die Namen als String-Pool; die Laufzeitumgebung verwendet aus Geschwindigkeitsgründen Indizes.
  • SET_SIGNAL_MASK meldet nur Interesse an – es beendet nichts. Erst das Senden von signal X stoppt Skripte, deren Maske X gesetzt hat. Die Lint-Regel signal-never-signalled findet Skripte, die eine Maske setzen, die niemand je signalisiert.
  • Cavedogs Scriptor setzt CURRENT_SPEED als Literal 29 ein, was Skripte im Stil von MoveWatcher nach einem Round-Trip kaputtmacht. Der Decompiler von kbot stellt den symbolischen Namen wieder her; wenn du einen Round-Trip durch Scriptor machen musst, setze Klammern: (get CURRENT_SPEED) > 5.
  • Sprung-Offsets sind Byte-Offsets relativ zu OffsetToScriptCode, nicht relativ zur aktuellen Instruktion. JUMP 0x4C bedeutet „springe zu OffsetToScriptCode + 0x4C“.
  • Die Portnummern von GET_UNIT_VALUE unterscheiden sich zwischen TA und TA:K. Der Katalog von TA (der Decompiler von kbot benennt die Ports 1–20) ist in Anhang B dokumentiert.

GAF – Sprite-Animationen

  • Eine Sequenz läuft nur dann in einer Schleife, wenn das untere Byte ihres Worts bei +2 gesetzt ist; bei 0 spielt sie einmal und hält an. Jede Originalsequenz speichert 1; ein Werkzeug, das 0 schreibt, friert also animierte Kartenobjekte ein.
  • Frames in textures/*.gaf und anims/vismasks.gaf müssen roh sein. Das Spiel liest sie als einfache Pixel-Arrays.
  • Manche Sequenzen werden mit Frame-Dauern von 0 ausgeliefert; das Spiel zeigt einen solchen Frame einen Tick lang. Setz sie nicht auf einen Standardwert, um sie zu „reparieren“.
  • Palettenindex 0 ist nicht von sich aus transparent. Transparent sind nur der Schlüssel eines rohen Frames und die Überspring-Läufe eines komprimierten Frames.
  • Komprimierte Pixelzeilen können kürzer als Width sein. Das Spiel liest in die nächsten Bytes weiter; kbot füllt die Zeile mit transparenten Pixeln auf und warnt. Keine Originaldatei hat solche Zeilen.
  • Die Ursprünge der Ebenen sind Hotspots: Jede Ebene eines zusammengesetzten Frames wird so platziert, dass ihr Ursprung auf dem Ursprung des Frames liegt.
  • anims/terrain.gaf und anims/vismasks.gaf haben in ihren Headern Version == 0. Das Spiel ignoriert das Versionswort.
  • Die .taf von TA: Kingdoms gibt es in zwei Arten. Eine .taf mit Palette IST ein GAF – dasselbe Format auf der Platte, nur dass TAK die Palette aus einer .pcx pro Seite holt statt aus der globalen Palette von TA. Eine Truecolor-.taf verwendet denselben Container, speichert aber 16-Bit-ARGB-Pixel und braucht keine Palette. Maßgeblich ist das Format-Byte des Frames (0/1 = mit Palette, 4/5 = Truecolor), nicht die Endung – siehe TAF / TSF.

TAF / TSF – Truecolor-Animationen

  • .taf ist mehrdeutig – mit Palette (wird als GAF gelesen) oder Truecolor (wird mit kbot taf gelesen). Prüfe immer das Format-Byte des Frames, nie den Dateinamen, auch wenn die meisten Truecolor-Dateien von TAK nach Konvention ein Suffix _4444 / _1555 tragen.
  • Der GIF-Export ist verlustbehaftet. GIF fasst nur eine 1-Bit-Maske und 255 Farben; weiches ARGB4444-Alpha wird also zu harten Kanten. Nimm APNG (kbot taf export --format apng), um den echten Alphakanal zu erhalten.
  • Das Namensfeld des Frames und das Flag-Byte 0x0B können Datenmüll enthalten. Übernimm sie für einen bytegenauen Round-Trip unverändert; normalisiere nichts.
  • Ein Delay / eine Duration von 0 ist zulässig – wie bei GAF ist ein Frame mit null Ticks ereignisgesteuert (statische Menühintergründe verwenden das). „Repariere“ das nicht.

PCX – Bilder

  • TA ignoriert BytesPerLine. Übliche Leser verwerfen die Auffüllung, wenn BytesPerLine > Width; TA 3.1c dekodiert genau Width Byte pro Zeile, sodass Dateien mit Auffüllung im Spiel verschoben erscheinen. Schreib BytesPerLine == Width und prüfe es mit kbot pcx describe.
  • TA lädt nur Version 5 und dekodiert jede Datei als 8-Bit-Daten mit einer einzigen Ebene.
  • Literal-Bytes, bei denen die oberen zwei Bits gesetzt sind, müssen per RLE maskiert werden. Ein nacktes Byte mit dem Wert 0xC0–0xFF ist als Literal unzulässig; gib es als Lauf der Länge 1 aus (0xC1, 0xFF für ein einzelnes 0xFF). Wer das falsch behandelt, bringt das Dekodieren nach einer Zeile aus dem Tritt.
  • Das Spiel nimmt die letzten 768 Byte mit oder ohne den Marker 0x0C als Palette; übliche Leser brauchen den Marker.

PAL / ALP / LHT / SHD – Paletten und Nachschlagetabellen

  • Das 4. Byte pro Eintrag ist NICHT Alpha. Es ist ein unbenutztes Füllbyte, das Cavedog immer auf 0x00 gesetzt hat. Open-Source-Werkzeuge für Paletten, die es als Alpha behandeln, rendern die Palette nicht (alpha=0 → alles transparent).
  • Index 0 ist schwarz, nicht transparent. Gelände, Minikarten und Hintergründe zeichnen ihn deckend; Sprites wählen ihren eigenen Transparenzschlüssel.
  • Eine leere oder fehlende palette.pal wird durch palette.pcx ersetzt (deren letzte 768 Byte); eine .pal, die länger als 1.024 Byte ist, wird bis Byte 1.024 gelesen.
  • .alp / .lht / .shd sind KEINE RGB-Paletten – .alp ist eine 256×256-Tabelle, .shd / .lht sind 32×256-Tabellen, jeweils aus Palettenindizes, und das Spiel ignoriert eine Tabelle jeder anderen Größe (und baut sie neu auf). Rendert man sie mit kbot pal describe, kommt nur Müll heraus; nimm stattdessen kbot pal lookup.
  • Die Palette von TA enthält 13 doppelte RGB-Tripel. Wenn dein Editor beim Import Duplikate entfernt (manche tun das), verlierst du Einträge, und die Palette hat stillschweigend nur noch 243 Einträge.

FNT – Bitmap-Schriften

  • Offsets[c] == 0 bedeutet „kein Glyph“, nicht „Glyph bei Offset 0“. Offset 0 liegt mitten im Header – Cavedog verwendet null als Sentinel-Wert.
  • Innerhalb jedes Bytes kommt das MSB zuerst. LSB zuerst ist bei modernen Bitmap-Schriften häufiger; geh nicht einfach davon aus.
  • Der Bitstrom läuft zwischen den Zeilen durch – am Ende jeder Scanzeile gibt es keine Auffüllung.

KI-Profile

  • KI-Dateien von TA: Kingdoms haben keine plan-Direktiven – nur nackte weight-/limit-Zeilen. Der Parser von kbot öffnet einen impliziten default-Plan; Leser sollten den fehlenden Block tolerieren. Siehe TA:K – Profile ohne plan.
  • Nirgends wird etwas geprüft. Falsch geschriebene Einheitennamen, kaputte Gewichtswerte, Zeilen außerhalb von plan – alles wird stillschweigend ignoriert. Das erste Anzeichen eines kaputten Profils ist „die KI verhält sich seltsam“, ohne jede Log-Meldung.
  • Kategorie-Aliasse (PLANT, LEVEL3) „existieren“ nur, wenn mindestens eine Einheit sie in Category= deklariert. Schreib versehentlich LEVL3, und die Direktive bewirkt stillschweigend nichts.

Sounds

  • Eine fehlende WAV ist stumm, kein Fehler. Schreib versehentlich select1=cmsdel1 (vertauschte Buchstaben), und die Engine spielt nichts – kein Log, kein Ersatz.
  • Die Endung .wav ist in TDF-Werten implizit – schreib sie nie. select1=cmdsel1.wav wird zu sounds/cmdsel1.wav.wav und findet nichts.

Besonderheiten von TA: Kingdoms

  • TAK braucht -disablecavedogverification als Kommandozeilenargument, um die meisten gemoddeten Dateien zu laden. Ohne den Schalter weist die Engine alles ab, dessen Hash nicht auf ihrer Allowlist steht.
  • TAK hat in den Daten 8 Seitencodes, nicht 4: ARA / TAR / VER / ZON für die vier spielbaren Seiten, dazu CRE (Creon, Iron Plague), MON (Monster), LIF (Tierwelt), NPC (Kampagnenfiguren). Das Filtern von Einheitenlisten muss mit allen zurechtkommen.
  • Die Waffen von TAK stehen inline in jeder FBI als Unterabschnitte [WEAPON1]–[WEAPON3], nicht in einem eigenen Verzeichnis weapons/*.tdf.
  • Die Baumenüs von TAK sind linear, nicht 2×3. Jede Baueinheit hat ein Verzeichnis canbuild/<builder>/<unit>.tdf mit einem einzigen Block [Menu] { Priority = N; }.

Siehe auch

  • Modding-Tutorial – Rundgang durch einen Einheiten-Mod für TA, von Anfang bis Ende.
  • Glossar – Definitionen aller formatübergreifenden Begriffe, auf die oben verwiesen wird.
  • Schnellstart – fünf kbot-Befehle für den Anfang.