Toutes les pages de formats ↓
Cartes et terrain

SCT — sections de carte

Source : coreprime/kbot @ 0ab97bf · Modifier sur GitHub

Un fichier .sct est un morceau de terrain de carte réutilisable : les level designers de Cavedog en assemblaient des dizaines dans l'éditeur de cartes officiel (TAE) pour construire les cartes .tnt finies. Chaque section regroupe ses propres graphismes de tuiles, sa grille de tuiles, ses hauteurs par case et une minicarte en vignette. Ce sont les briques ; les TNT sont le produit assemblé.

Section de côte de Greenworld rendue en tuiles
sections/greenworld/coast/b_n_w02_135.sct rendue par kbot sct image

Minicarte de la section    Carte des hauteurs de la section
Minicarte intégrée (à gauche) et grille d'altitudes (à droite).

Tip

Essayez vous-même.

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

Consultez la référence de kbot sct de la CLI.

Depuis Go. Utilisez 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))

Disposition sur le disque

┌─ 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

Les champs pointeurs peuvent désigner les sections dans n'importe quel ordre, mais les outils de Cavedog les écrivent dans la disposition ci-dessus, et c'est ce que suppose chaque lecteur tiers.

En-tête (28 octets)

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;
Champ Remarques
Version 3 pour les sections d'origine de TA. Certains prototypes anciens utilisent 2 — même disposition, mais les entrées de hauteur font 8 octets au lieu de 4. kbot accepte les deux.
Width, Height Tous deux exprimés en tuiles (unités de 32 px). Pour une section compatible avec TAE, les deux doivent être des multiples de 4 (soit des multiples de 128 px).
NumTiles Nombre de tuiles uniques. La grille d'index de la section de données renvoie dans ce tableau.

Pixels des tuiles

NumTiles blocs de 32 × 32 = 1024 octets chacun — des index dans la palette de TA. Les tuiles identiques ne sont pas dédoublonnées automatiquement par le format : une section mal construite peut donc gaspiller de la place ; la commande image de kbot avertit si une section contient des tuiles inaccessibles.

Données de la section — index des tuiles + grille des hauteurs

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];

La grille des hauteurs est quatre fois plus dense que la grille des tuiles : chaque tuile reçoit 2 × 2 = 4 échantillons de hauteur à une résolution de 16 pixels, comme les cases d'attributs des TNT. Les champs always_-1 et always_0 sont des métadonnées de travail de l'éditeur ; vous pouvez réécrire l'une ou l'autre valeur lors d'un aller-retour.

Minicarte

128 × 128 index de palette. Les dimensions sont fixes, quelles que soient la largeur et la hauteur de la section en tuiles, et la minicarte est étirée pour suivre les proportions de la section plutôt que bordée de bandes noires.


Ordre de lecture

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)

Exemple commenté — 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

Une section de 4×4 tuiles est la plus petite que TAE accepte (les dimensions doivent être des multiples de 128 px). Bien que la section ait 4 × 4 = 16 placements, elle fait référence à 64 tuiles uniques, car chaque case de 32×32 est elle-même bordée de transitions dont le designer voulait des variantes. C'est normal : les sections échangent de l'espace de stockage contre de la liberté de raccord.


Comment le TNT utilise les sections

Le pool de tuiles d'une carte .tnt est l'union de tous les .sct que le level designer y a « peints », dédoublonnée après coup par TAE. Quand vous constatez que deux TNT partagent une tuile, elle vient donc presque toujours du même SCT.

Le lien n'existe qu'à la construction. Le moteur n'ouvre jamais de section à l'exécution ; il ne voit que le TNT déjà assemblé. Les sections se trouvent sur le disque dans les archives de l'éditeur (worlds.hpi) et dans les archives des mondes de la campagne, par ex. sections/greenworld/coast/, sections/lava/hills/, etc.


Pièges

Warning

Width × Height doit être un multiple de 4 pour que TAE charge la section. Le format lui-même ne l'impose pas — vous pouvez écrire une section de 3×3 tuiles et kbot l'affichera sans broncher —, mais l'éditeur de Cavedog la rejettera avec une erreur sibylline « section misaligned ».

  • Version == 2 a des cases de hauteur de 8 octets, et non de 4. Le premier octet reste l'altitude ; les 7 autres octets sont des données de travail de l'éditeur que vous pouvez mettre à zéro à l'écriture.
  • La minicarte de 128×128 est étirée, et non bordée de bandes noires, pour suivre les proportions de la section. Une section de 4×16 paraîtra horriblement écrasée dans la minicarte.
  • Il n'y a pas de signature en dehors de Version. Pour valider un SCT candidat, vérifiez que Version ∈ {2, 3} et que les quatre champs pointeurs tombent tous à l'intérieur du fichier.
  • Les plages de hauteurs sont entièrement laissées au designer. TAE les borne à 0–255, mais une section peut être parfaitement plate (une seule valeur) ou couvrir toute la plage. Le rendu des TNT normalise avant l'affichage ; celui des SCT, non.

Tailles typiques

Ressource Plage observée dans les sections/**/*.sct de Cavedog
Taille du fichier 30 Ko – 2 Mo
Dimensions de la section (tuiles) 4×4 – 32×32
Tuiles uniques par section 30–600
Surcoût de l'en-tête toujours 28 octets
Minicarte (toujours 128×128 à palette) 16 384 octets
Sections dans worlds.hpi ~5 000 (tous biomes confondus)

Voir aussi

  • TNT — le format de carte assemblée qui consomme les sections.
  • PAL — la palette utilisée pour colorer à la fois les pixels des tuiles et la minicarte.
  • Glossaire — tuile, case d'attributs, carte des hauteurs.