SCT – Kartensektionen
Eine
.sct-Datei ist ein wiederverwendbares Stück Kartengelände – Cavedogs Leveldesigner haben im offiziellen Karteneditor (TAE) Dutzende davon zusammengefügt, um die fertigen.tnt-Karten zu bauen. Jede Sektion bündelt ihre eigenen Kachelgrafiken, ihr Kachelraster, Höhen pro Zelle und eine Minikarte als Vorschaubild. Sie sind die Bausteine; TNTs sind das zusammengesetzte Produkt.
sections/greenworld/coast/b_n_w02_135.sct, gerendert mit kbot sct image
Eingebettete Minikarte (links) und Höhenraster (rechts).
Tip
Probier es selbst.
kbot sct info sections/greenworld/coast/b_n_w02_135.sct
kbot sct describe sections/greenworld/coast/b_n_w02_135.sct
kbot sct image sections/greenworld/coast/b_n_w02_135.sct -t out.png
kbot sct minimap sections/greenworld/coast/b_n_w02_135.sct -t mini.png
kbot sct heightmap sections/greenworld/coast/b_n_w02_135.sct -t height.png
Siehe die kbot sct-Referenz der CLI.
Aus Go heraus. Verwende formats/sct:
import "github.com/coreprime/kbot/formats/sct"
f, _ := os.Open("sections/greenworld/coast/b_n_w02_135.sct")
defer f.Close()
s, _ := sct.LoadFromReader(f)
fmt.Printf("%dx%d tiles, %d unique, %d heights\n",
s.Header.Width, s.Header.Height, s.Header.NumTiles, len(s.HeightMap))
Aufbau auf der Platte
┌─ Header (28 B) ──┐ version, pointers, dimensions
├─ Tile pixels ────┤ NumTiles × 1024 bytes (32×32 palette indices)
├─ Section data ───┤ Width × Height × int16 tile indices
├─ Height grid ────┤ (Width × 2) × (Height × 2) × {4 or 8} bytes
└─ Minimap ────────┘ 128 × 128 palette indices
Die Zeigerfelder können in beliebiger Reihenfolge auf die Abschnitte zeigen, aber Cavedogs Werkzeuge geben sie im oben gezeigten Aufbau aus, und davon geht jeder Leser von Drittanbietern aus.
Header (28 Byte)
typedef struct {
uint32 Version; // 2 or 3 (TA's TAE always emits 3)
uint32 PtrMinimap; // → 128×128 minimap
uint32 NumTiles; // unique 32×32 tile count
uint32 PtrTiles; // → tile pixel block
uint32 Width; // section width in tiles
uint32 Height; // section height in tiles
uint32 PtrData; // → tile-index grid + heights
} SCTHeader;
| Feld | Anmerkungen |
|---|---|
Version |
3 bei Sektionen der Verkaufsversion von TA. Einige frühe Prototypen verwenden 2 – gleicher Aufbau, aber Höheneinträge zu 8 statt 4 Byte. kbot akzeptiert beides. |
Width, Height |
Beide in Kacheln angegeben (Einheiten zu 32 px). Für eine Sektion, die TAE verarbeiten kann, müssen beide Vielfache von 4 sein (also Vielfache von 128 px). |
NumTiles |
Anzahl der einzigartigen Kacheln. Das Indexraster im Datenabschnitt verweist in dieses Array. |
Kachelpixel
NumTiles Blöcke zu je 32 × 32 = 1024 Byte – Palettenindizes in die
Palette von TA. Identische Kacheln werden vom Format nicht automatisch
zusammengefasst, eine schlecht gebaute Sektion kann also Platz
verschwenden; der Befehl image von kbot warnt, wenn eine Sektion
unerreichbare Kacheln hat.
Sektionsdaten – Kachelindizes + Höhenraster
int16 tileMap[Height][Width]; // Index into the tile pixel array
// (signed; negative values are unused
// in retail content but valid)
struct HeightCell_V3 { uint8 h; int16 always_minus_one; uint8 always_zero; };
struct HeightCell_V2 { uint8 h; int16 always_minus_one; uint8 always_zero;
uint32 reserved; };
HeightCell heights[Height * 2][Width * 2];
Das Höhenraster ist viermal so dicht wie das Kachelraster – jede
Kachel bekommt 2 × 2 = 4 Höhenwerte in einer Auflösung von 16 Pixeln,
passend zur Funktionsweise der Attributzellen von TNT. Die Felder
always_-1 und always_0 sind Hilfsmetadaten aus dem Editor; du kannst
beim Round-Trip jeden der beiden Werte zurückschreiben.
Minikarte
128 × 128 Palettenindizes. Die Maße sind unabhängig von Breite und Höhe
der Sektion in Kacheln fest, und die Minikarte wird auf das
Seitenverhältnis der Sektion gestreckt, statt mit Balken eingepasst zu
werden.
Lesereihenfolge
header = read_struct(SCTHeader)
assert header.Version in (2, 3)
seek(header.PtrTiles)
tiles = [read(1024) for _ in range(header.NumTiles)]
seek(header.PtrData)
tile_map = read_int16_array(header.Width * header.Height)
entry_size = 4 if header.Version == 3 else 8
attrs_w, attrs_h = header.Width * 2, header.Height * 2
heights = [read(entry_size)[0] for _ in range(attrs_w * attrs_h)]
seek(header.PtrMinimap)
minimap = read(128 * 128)
Beispiel im Detail – b_n_w02_135.sct
$ kbot sct describe sections/greenworld/coast/b_n_w02_135.sct
Version: 3
Section: 4 × 4 tiles (128 × 128 px)
Tiles: 64 unique
Heights: 8 × 8 cells (height range 50–62)
Minimap: 128 × 128
Eine Sektion aus 4×4 Kacheln ist die kleinste, die TAE akzeptiert (es
müssen Vielfache von 128 px sein). Obwohl die Sektion 4 × 4 = 16
Platzierungen hat, verweist sie auf 64 einzigartige Kacheln, weil jede
32×32-Zelle selbst von Randübergängen begrenzt ist, für die der Designer
Varianten haben wollte. Das ist normal – Sektionen tauschen
Speicherplatz gegen Freiheit beim Überblenden.
Wie TNT Sektionen verwendet
Der Kachelvorrat einer .tnt-Karte ist die Vereinigung aller .sct, die
der Leveldesigner hineingemalt hat, nachträglich von TAE von Duplikaten
befreit. Wenn sich also zwei TNTs eine Kachel teilen, stammt sie fast
immer aus derselben SCT.
Die Verbindung besteht nur zur Bauzeit. Die Engine öffnet zur
Laufzeit nie eine Sektion; sie sieht nur die bereits zusammengesetzte TNT.
Sektionen liegen auf der Platte in den Editor-Archiven (worlds.hpi) und
den Weltarchiven der Kampagne, z. B. sections/greenworld/coast/,
sections/lava/hills/ usw.
Stolperfallen
Warning
Width × Height muss ein Vielfaches von 4 sein, damit TAE die Sektion
lädt. Das Format selbst erzwingt das nicht – du kannst eine Sektion aus
3×3 Kacheln schreiben, und kbot rendert sie anstandslos –, aber Cavedogs
Editor lehnt sie mit einem kryptischen Fehler „section misaligned“ ab.
Version == 2hat Höhenzellen zu 8 Byte, nicht zu 4. Das erste Byte ist nach wie vor die Höhe; die übrigen 7 Byte sind Hilfsdaten des Editors, die du beim Schreiben nullen kannst.- Die Minikarte von 128×128 wird gestreckt, nicht mit Balken eingepasst, um auf das Seitenverhältnis der Sektion zu passen. Eine Sektion von 4×16 sieht in der Minikarte furchtbar gestaucht aus.
- Außer
Versiongibt es keine Signatur. Um eine mutmaßliche SCT zu prüfen, stelle sicher, dassVersion ∈ {2, 3}gilt und alle vier Zeigerfelder innerhalb der Datei liegen. - Die Höhenbereiche liegen ganz beim Designer. TAE begrenzt auf 0–255, aber eine Sektion kann vollkommen flach sein (ein einziger Wert) oder den vollen Bereich nutzen. Der TNT-Renderer normalisiert vor der Anzeige; die SCT tut das nicht.
Typische Größen
| Asset | Beobachteter Bereich in Cavedogs sections/**/*.sct |
|---|---|
| Dateigröße | 30 KB – 2 MB |
| Sektionsmaße (Kacheln) | 4×4 – 32×32 |
| Einzigartige Kacheln pro Sektion | 30–600 |
| Header-Overhead | immer 28 Byte |
| Minikarte (immer 128×128 mit Palette) | 16.384 Byte |
Sektionen in worlds.hpi |
~5.000 (über alle Biome) |