Alle Formatseiten ↓
Karten und Gelände

Karten von TA: Kingdoms – .tnt + .ota + .crt + .kmp

Aus coreprime/kbot @ 0ab97bf · Auf GitHub bearbeiten

Karten von TA: Kingdoms sind eine TNT-Variante (mit anderem IDVersion-Wort), umgeben von einer oder zwei Metadatendateien, dazu kommt ein Format für Kampagnenarchive auf Basis von HPI v2 für die Einzelspielermissionen. Das liegt deutlich näher am Kartenmodell von TA, als die älteren Forschungsnotizen zu „BTM/Höhenkarten-BMP“ vermuten ließen – in einer echten GoG-Installation von TA:K gibt es überhaupt keine .btm-Dateien oder BMP-Begleitdateien.

Der vorhandene HPI-v2-Leser von kbot verarbeitet .kmp-Archive ohne Weiteres. Der TNT-Leser von kbot erkennt das Versionswort von TA:K und dekodiert den Header, die Höhenkarte der DataUnits, das Texture-Mapping-Raster (Tabellen mit Geländenamen und U/V-Offsets), das Platzierungsraster der Kartenobjekte samt Namenstabelle und die eingebettete Minikarte – genug, um eine vollständige Karte in voller Auflösung zu rendern, indem die externen Gelände-JPGs und die GAF-Sprites der Kartenobjekte zusammengesetzt werden. Diese Seite dokumentiert, was sich an der ausgelieferten Installation überprüfen lässt, und die verbleibenden Lücken.

Important

Neuer Stand (gegenüber der ursprünglichen Fassung dieser Seite als „Forschungsnotizen“). Die Dateitypen, um die es hier früher ging – .btm, BMP-Begleitdateien, PCX-Paletten pro Seite – gibt es in der ausgelieferten GoG-Installation von TA: Kingdoms tatsächlich nicht. Die echten Dateitypen sind unten dokumentiert. Zum Vergleich mit einem anderen Open-Source-Projekt zu TA:K siehe iiCompleteDestruction; dessen Parser ist bei einigen TA:K-spezifischen Strukturen vollständiger als der von kbot.


Dateien, aus denen eine TA:K-Karte besteht

Gezählt im Kartenverzeichnis der GoG-Installation:

Endung Anzahl Zweck
.kmp 181 HPI-v2-Archiv, das Karte, Skripte und Assets einer Kampagnenmission bündelt
.tnt 55 Geländedaten der Karte (TNT-artige Binärdatei mit einem TA:K-spezifischen IDVersion-Wort)
.ota 55 Karten-Metadaten – TDF-Format, gleich aufgebaut wie die .ota von TA, mit TAK-spezifischen Feldern
.txt 55 Freitext-Beschreibung der Karte (ein paar Wörter; wird in der Lobby angezeigt)
.crt 33 Szenario-Begleitdatei: vorab platzierte Einheiten, Regel-Engine pro Spieler, benannte Auslöserbereiche
.tdf 6 Anpassungsdateien für das Gameplay einzelner Karten (Feinabstimmung der Kampagne, Anstöße für die KI)

Eine typische Mehrspielerkarte wird als Dreiergespann aus .tnt + .ota + .txt ausgeliefert, manchmal mit einer .crt-Begleitdatei. Kampagnenmissionen sind in .kmp-Archive gepackt, die denselben Satz mit Missionsskripten bündeln.

Tip

Ein TA:K-Kartenpaket auflisten, ohne etwas zu entpacken:

# The HPI v2 reader handles .kmp transparently
kbot hpi list /path/to/tak/maps/adamantine\ gate.kmp -v
kbot hpi info /path/to/tak/maps/adamantine\ gate.kmp

.tnt – Gelände von TA:K (TNT v2)

TA:K verwendet die TNT-Struktur von TA wieder, erhöht aber das IDVersion-Wort. Hex-Dump von abnar's terrace.tnt:

00000000: 00 40 00 00 20 01 00 00 e0 00 00 00 3a 00 00 00   .@.. .......:...
00000010: 34 00 00 00 34 fc 00 00 34 f4 02 00 16 00 00 00   4...4...4.......

Das erste uint32 ist 0x00004000 – zum Vergleich: Das TNT von TA verwendet 0x00002000. Der Container ist nach wie vor ein Header, gefolgt von Abschnitten, die über Zeiger adressiert werden, aber TA:K ist überhaupt kein Kachelmosaik-Format. Wo TA ein Raster aus Kachelindizes plus einen Vorrat an Kachelgrafiken zu 32×32 speichert, speichert TA:K das Gelände als Texture-Mapping-Raster, das auf externe JPG-Texturen verweist, dazu eine separate Höhenkarte und ein Platzierungsraster der Kartenobjekte. Alles Folgende ist an allen 55 ausgelieferten Karten überprüft:

  1. Width/Height zählen DataUnits zu 16 px, keine Pixel. Eine „15 × 15“-Karte wie athri cay speichert Width = Height = 480 DataUnits → 480 × 16 = 7680 px pro Seite. Höhenkarte und Objektraster werden pro DataUnit abgetastet; das Gelände wird auf einem gröberen Raster aus Graphic Units zu 32 px abgetastet, das auf jeder Achse genau halb so fein ist wie das DataUnit-Raster (guW = Width/2).
  2. Der Header besteht aus zwölf aufeinanderfolgenden uint32 mit Offsets und Anzahlen; die Feldnamen von TA beschreiben den Inhalt nicht mehr. Die Tabelle unten gibt die Bedeutung in TA:K an.
  3. Abschnittszeiger sind absolut, jeder Abschnitt wird also über seinen eigenen Zeiger und eine berechnete Länge gelesen.
Offset TA:K-Feld Abschnittsgröße Anmerkungen
0x00 Version – 0x4000 (TA schreibt 0x2000)
0x04 Width – DataUnits; ×16 → Pixel, ÷2 → Graphic Units
0x08 Height – DataUnits
0x0C SeaLevel – Höhenschwelle für Wasser
0x10 HeightMapOffset Width × Height Byte ein Höhenbyte pro DataUnit
0x14 AttributesOffset Width × Height × 2 Objektraster: uint16-Index pro DataUnit (≥0xFF00 = keines)
0x18 FeatureNamesOffset Count × 132 Namenstabelle der Kartenobjekte (4-Byte-Index + 128-Byte-Name)
0x1C FeatureCount – Anzahl der Objekttypen
0x20 TerrainNamesOffset guW × guH × 4 Texturname pro GU → terrain/%08x.jpg
0x24 UMappingOffset guW × guH Byte Spalten-Offset pro GU in seine Textur (×32 px)
0x28 VMappingOffset guW × guH Byte Zeilen-Offset pro GU in seine Textur (×32 px)
0x2C MiniMapOffset 8 + 126×126 uint32 w, uint32 h, dann Indizes

Die Höhenkarte (0x10) hat ein Byte pro DataUnit – ein Höhenfeld in Graustufen, keine Farb-Bitmap. Das Gelände wird per Texture-Mapping rekonstruiert: Für jede Graphic Unit liefert die Tabelle der Geländenamen (0x20) eine Texturdatei (terrain/<name>.jpg, der Name als achtstellige Hexzahl in Kleinbuchstaben formatiert), und die U/V-Tabellen (0x24/0x28) geben die Teilkachel zu 32×32 an, die bei (u×32, v×32) aus diesem JPG kopiert wird. Das Objektraster (0x14) ist die Platzierungsebene: ein Array aus uint16 der Größe Width × Height, in dem jede Zelle entweder einen Objektindex in die Namenstabelle enthält oder einen hohen Sentinel-Wert (≥0xFF00), der „hier kein Objekt“ bedeutet; die DataUnit-Zelle (x, y) einer Platzierung entspricht dem Geländepixel (x×16, y×16). Die Namenstabelle (0x18) verwendet denselben Aufbau mit Einträgen zu 132 Byte wie die TileAnim-Tabelle von TA.

Der Minikarten-Block ist im gesamten ausgelieferten Bestand immer 126 × 126 groß und verwendet zum Auffüllen außerhalb nicht quadratischer Karten dasselbe Leer-Byte 0x64 wie TA.

Note

Was heute mit TNTs von TA:K funktioniert. kbot tnt describe gibt Header, Königreich, Maße von Höhenkarte und Gelände sowie die Aufteilung der Kartenobjekte aus. kbot tnt preview --vfs <root> rendert das texturierte Gelände in voller Auflösung und legt das GAF-Sprite jedes Kartenobjekts darüber, verankert an seinem Hotspot – die vollständige Karte, wie das Spiel sie zeichnet. kbot tnt image rendert die eigenständige Höhenkarte in Graustufen (ohne externe Texturen; --features legt nach Kategorie eingefärbte Markierungen darüber). kbot tnt minimap exportiert die eingebettete Vorschau in 126 × 126.

Minikarten-Palette – eine pro Königreich

TA:K färbt seine Minikarte nicht mit einer einzigen globalen Palette. Jede Karte backt ihre Vorschau in 126 × 126 mit der Texturpalette des Königreichs, zu dem sie gehört – dem Feld kingdom= in der danebenliegenden .ota (aramon / taros / veruna / zhon / creon). Dieselben Indizes mit der Palette des falschen Königreichs (oder mit der PALETTE.PAL von TA) zu rendern, ergibt gesprenkeltes Rauschen; mit der richtigen erhält man natürliches Wasser, Strände und Gelände.

kbot tnt minimap ermittelt das Königreich automatisch aus der danebenliegenden .ota. Fehlt die .ota (z. B. bei einer losen .tnt), gib --kingdom <name> ausdrücklich an:

kbot tnt minimap "athri cay.tnt" -t mini.png          # auto: veruna
kbot tnt minimap loose.tnt --kingdom aramon -t mini.png

.ota – Karten-Metadaten (TDF, größtenteils vertraut)

Die .ota von TA:K hat dasselbe TDF-artige Format wie die von TA, mit einigen TAK-spezifischen Feldern. Die vollständige Datei aus abnar's terrace.ota:

[GlobalHeader]
{
    Copyright=Copyright 1998 Cavedog Entertainment. All rights reserved.;
    missionname=Abnar's Terrace;
    missiondescription=9 x 7  4 Player  32MB;
    kingdom=veruna;          // ← TA:K-specific: the side the map "belongs" to
    numplayers=4;
    size=9 x 7;              // ← TA:K-specific: free-text size for the lobby
    memory=32 MB;            // ← TA:K-specific: ~RAM requirement for the lobby
    hasscenario=0;
    [Map Data]
    {
        Type=Network 1;
        aiprofile=DEFAULT;
        [specials]
        {
            [special0] { specialwhat=StartPos1; XPos=37;   ZPos=190; }
            [special1] { specialwhat=StartPos2; XPos=215;  ZPos=38;  }
            …
        }
    }
}
Feld Entsprechung in TA Anmerkungen
kingdom= keine Zugehörigkeit zu einer Seite (aramon / taros / veruna / zhon / creon). Die Lobby filtert danach; wählt außerdem die Gelände-/Minikarten-Palette, mit der die eingebackene Vorschau der .tnt eingefärbt ist.
size= keine Kartengröße in lesbarer Form für die Lobby.
memory= keine Empfohlener Arbeitsspeicher. Rein kosmetisch.
hasscenario= keine 1 für Kampagnenmissionen, 0 für Skirmish-Karten.
[Map Data] [Schema N] Entspricht dem Schema-Unterabschnitt, zu einem einzigen Block zusammengefasst (TA:K liefert pro Karte immer nur ein Schema aus).

Alles andere (StartPos1..N, aiprofile= usw.) funktioniert genau wie in TA – der OTA-Betrachter von kbot mount kommt mit beidem ohne Änderung zurecht.


.kmp – HPI-v2-Archive für Kampagnenmissionen

.kmp ist ein umbenanntes HPI-v2-Archiv. Der Anfang von adamantine gate.kmp als Hex:

00000000: 48 41 50 49 00 00 02 00 57 32 02 00 77 00 00 00   HAPI....W2..w...
00000010: 15 32 02 00 42 00 00 00 20 00 00 00 00 00 00 00   .2..B... .......
00000020: 53 51 53 48 …                                     SQSH…

Genau der Aufbau des v2-Headers (HAPI-Marker → Version 0x00020000 → 24-Byte-v2-Header → SQSH-Chunks). kbot hpi list, info und extract funktionieren alle direkt. Eine .kmp enthält typischerweise:

  • .tnt und .ota der Mission
  • Eine Handvoll GAFs für Zwischensequenzen und Briefings
  • COB-Dateien mit Missionsskripten – TA:K verwendet das COB-Format (VersionSignature == 6) für Missionsskripte wieder, statt einer eigenen Skriptsprache. Die 3.885 Fundstellen des Opcodes MISSION_COMMAND (0x10073000) in der Verkaufsversion von TAK liegen hier. Das Datenformat und den String-Pool mit Soundnamen pro COB, in den Missionsbefehle indizieren, beschreiben TA: Kingdoms – Unterschiede von COB v6 und Anhang C in cob.md.
  • Manchmal Überschreibungen von Einheiten pro Mission

.crt – Szenarioskript (Einheiten, Regeln, Auslöser)

Eine .crt enthält die geskriptete Ebene einer Karte: die Einheiten, die vor Spielbeginn platziert werden, die Regel-Engine pro Spieler, die die Skirmish-KI und die Kampagnenziele steuert, und die benannten rechteckigen Auslöserbereiche, auf die sich diese Regeln beziehen. Mehrspielerkarten liefern einen leeren Stub aus (keine Einheiten, neun leere Spielerplätze, keine Auslöser, 56 Byte); Kampagnen- und Sonderkarten füllen jeden Abschnitt, bis zu ~120 KB.

Die ganze Datei ist Little-Endian und ein direktes Abbild der Speicherstrukturen der Engine, daher enthalten die Einheiten-Datensätze mehrere nicht initialisierte Füllfelder.

Offset Typ Feld Anmerkungen
0x00 uint32 Signature 0x3F800000 – Marker 1.0f nach IEEE 754
0x04 uint32 Unknown1 0 auf jeder ausgelieferten Karte bis auf eine
0x08 uint32 UnitCount Anzahl der folgenden Datensätze platzierter Einheiten

abnar's terrace.crt (ein leerer Stub) beginnt so:

00000000: 00 00 80 3f 00 00 00 00 00 00 00 00 09 00 00 00

1.0f, Unknown1 = 0, UnitCount = 0, dann die Spieleranzahl 9.

Einheiten-Datensätze (je 568 Byte)

Offset Typ Feld
+0 char[256] UnitType (NUL-terminiert)
+256 char[256] UniqueName (meist leer)
+512 uint32 X (Welt)
+516 uint32 Y (Höhenachse)
+520 uint32 Z (Welt)
+524 uint32 PlayerId (ab 0)
+528 uint32 HealthPercent (meist 100)
+532 uint32 ArmorPercent (meist 100)
+536 uint32 WeaponPercent (meist 100)
+540 uint32 Angle (meist 180)
+544 uint32 Veteran
+548 uint32 unbekannt
+552 uint32 unbekannt
+556 uint32 FootprintX
+560 uint32 FootprintZ
+564 uint32 unbekannt

Spieler, Regeln, Bedingungen, Aktionen

Nach den Einheiten steht eine uint32-Spieleranzahl (immer 9), gefolgt von entsprechend vielen Spielerblöcken. Jeder Spielerblock ist eine uint32-Regelanzahl, gefolgt von entsprechend vielen Regeln. Eine Regel besteht aus:

  • einer uint32-Anzahl der Bedingungen, dann ist jede Bedingung ein uint32-Opcode und fünf Argumentplätze zu 64 Byte;
  • einer uint32-Anzahl der Aktionen, dann ist jede Aktion ein uint32-Opcode und fünf Argumentplätze zu 64 Byte.

Auslöser

Am Ende steht eine uint32-Anzahl der Auslöser, gefolgt von entsprechend vielen Auslöser-Datensätzen. Jeder besteht aus einem NUL-terminierten Namen zu 256 Byte, gefolgt von vier uint32-Grenzen – Left, Top, Right, Bottom – in Kartenzellen. Die Namen sind für Menschen lesbar (The Hill, Player 1).

Werkzeuge

kbot crt describe <map.crt> gibt die Aufteilung nach Einheitentypen, die Regelanzahlen und die Auslöserbereiche aus; mit --verbose kommt die vollständige Liste der Platzierungen dazu. Das MCP-Werkzeug crt_describe liefert dieselben Daten als JSON.

Eine Datei – cairbray coast landing.crt – hat einen verschobenen, von Hand bearbeiteten Header, der nicht zu diesem Aufbau passt; der Parser lehnt sie mit einer klaren Fehlermeldung ab, statt sie falsch zu dekodieren.


.txt – Freitext-Beschreibung

Ein einzeiliger ASCII-String, der in der Lobby verwendet wird, z. B. abnar's terrace.txt: 9 x 7 4 Player 32MB (derselbe String, den missiondescription der .ota enthält). Die Autorenwerkzeuge haben vermutlich beides beim Export geschrieben; das Spiel scheint den Wert aus der .ota anzuzeigen.


Heute mit TA:K-Karten arbeiten

Praktische Möglichkeiten, nach steigendem Aufwand geordnet:

  1. Frei untersuchen – kbot hpi list/info/extract auf .kmp-Dateien funktioniert auf Anhieb. .ota und .txt sind reiner Text.
  2. Eine Karte beschreiben – kbot tnt describe <map.tnt> gibt den TA:K-Header, das Königreich, die Maße von Höhenkarte und Gelände und eine Aufteilung der Kartenobjekte aus.
  3. Eine Minikarte rendern – kbot tnt minimap <map.tnt> -t mini.png exportiert die eingebettete Vorschau in 126 × 126 in Truecolor und wählt die Palette des Königreichs automatisch aus der danebenliegenden .ota (überschreiben mit --kingdom; siehe den Hinweis zur Palette oben).
  4. Die vollständige texturierte Karte rendern – kbot tnt preview <map.tnt> --vfs <flattened-tak-root> -t map.png texturiert das Gelände aus den terrain/*.jpg der Installation und setzt das GAF-Sprite jedes Kartenobjekts darauf; das Ergebnis ist die Karte, wie das Spiel sie rendert (athri cay → 7.680 × 7.680). Die Palette der Objekt-Sprites wird aus palettes/<kingdom>_features.pcx gelesen.
  5. Die Höhenkarte rendern – kbot tnt image <map.tnt> -t height.png braucht keine externen Assets; es gibt die Höhenkarte der DataUnits in Graustufen aus (--features legt nach Kategorie eingefärbte Platzierungsmarkierungen darüber).
  6. Ein Kampagnenarchiv neu packen – kbot hpi pack erzeugt derzeit nur v1, eine neu gepackte .kmp würde also nicht laden. Bearbeite eine .kmp von Hand, indem du sie entpackst, die losen Dateien änderst und einen v2-fähigen Packer eines Drittanbieters verwendest, bis kbot v2 schreiben kann.

Warning

TA: Kingdoms braucht -disablecavedogverification, um die meisten veränderten Dateien zu laden, auch veränderte Karten. Ohne den Schalter weist die Engine alles ab, dessen Hash nicht auf ihrer Allowlist steht. Schreib das in die Installationsanleitung jedes Mods.


Was kbot derzeit für TA:K-Karten kann und was nicht

Vorgang Stand
Header + Dateiliste von .kmp (HPI v2) lesen ✅
Dateien aus .kmp entpacken ✅
.ota parsen (TDF-Format) ✅
Header einer TA:K-.tnt lesen (kbot tnt describe) ✅
Minikarte einer TA:K-.tnt exportieren (kbot tnt minimap) ✅ (Truecolor – Palette pro Königreich aus der .ota)
Vollständige texturierte TA:K-Karte rendern (kbot tnt preview --vfs) ✅ (texturiertes Gelände + GAF-Sprites der Kartenobjekte)
Höhenkarte von TA:K rendern (kbot tnt image) ✅ (eigenständig in Graustufen; --features legt Markierungen darüber)
Eine TA:K-.tnt schreiben (kbot tnt pack) ❌
.kmp schreiben (HPI v2 packen) ❌

Pull Requests zu allen ❌-Punkten sind willkommen. Da Höhenkarte, Texture-Mapping-Raster, Objektraster und Objekttabelle vollständig dekodiert sind, werden Gelände und Kartenobjekte in voller Auflösung gerendert; es fehlen noch der Schreibpfad für den Round-Trip bearbeiteter TA:K-Karten und das Packen von .kmp in v2.


Siehe auch

  • HPI – der v2-Archivcontainer (.kmp ist ein HPI v2 mit umbenannter Endung).
  • TNT – das TNT-Format von TA; TA:K verwendet die Struktur mit IDVersion 0x4000 wieder.
  • TDF – das Format, als das .ota geparst wird.
  • GAF – .taf-Animationsdateien, die in TA:K überall vorkommen (Zwischensequenzen in .kmp-Archiven).
  • Oberfläche von TA: Kingdoms – das Widget-Format für Menüs und HUD.
  • Glossar – side, heightmap.