Mapas de TA: Kingdoms (.tnt + .ota + .crt + .kmp)
Fuente: coreprime/kbot @ 0ab97bf · Editar en GitHub
Los mapas de TA: Kingdoms son una variante de TNT (con otra palabra IDVersion) acompañada de uno o dos archivos de metadatos, más un formato de archivo comprimido de campaña HPI v2 para las misiones de un jugador. Esto se parece bastante más al modelo de mapas de TA de lo que sugerían las antiguas notas de investigación sobre «BTM/BMP de mapa de alturas»: en una instalación real de TA:K de GoG no hay ni rastro de archivos
.btmni de BMP acompañantes.El lector de HPI v2 que ya tiene kbot maneja los archivos comprimidos
.kmpde forma transparente. El lector de TNT de kbot reconoce la palabra de versión de TA:K y decodifica la cabecera, el mapa de alturas por DataUnit, la cuadrícula de mapeado de texturas (tablas de nombres de terreno y de desplazamientos U/V), la cuadrícula de colocación de elementos con su tabla de nombres y el minimapa incrustado: basta para renderizar un mapa completo a resolución completa componiendo los JPG de terreno externos y los sprites GAF de los elementos. Esta página documenta lo que se puede verificar a partir de la instalación distribuida y las lagunas que quedan.
Important
Actualización de estado (respecto a la versión original de esta página
como «notas de investigación»). Los tipos de archivo de los que hablaba
antes esta página (.btm, BMP acompañantes, PCX de paleta por bando)
no existen realmente en la instalación de TA: Kingdoms que distribuye
GoG. Los tipos de archivo reales se documentan más abajo. Si quieres
compararlo con otro proyecto de código abierto de TA:K, consulta
iiCompleteDestruction;
su analizador está más completo que el de kbot en algunas estructuras
propias de TA:K.
Archivos que forman un mapa de TA:K
Recuento en el directorio de mapas de la instalación de GoG:
| Extensión | Cantidad | Finalidad |
|---|---|---|
.kmp |
181 | Archivo comprimido HPI v2 que reúne el mapa, los scripts y los recursos de una misión de campaña |
.tnt |
55 | Datos del terreno del mapa (binario con forma de TNT y una palabra IDVersion propia de TA:K) |
.ota |
55 | Metadatos del mapa: formato TDF, con la misma forma que el .ota de TA y campos propios de TAK |
.txt |
55 | Descripción del mapa en texto libre (unas pocas palabras; se muestra en el lobby) |
.crt |
33 | Archivo acompañante del escenario: unidades colocadas de antemano, motor de reglas por jugador, regiones de disparo con nombre |
.tdf |
6 | Archivos de ajustes de juego por mapa (ajuste de campaña, empujones a la IA) |
Un mapa multijugador típico se distribuye como el trío .tnt + .ota +
.txt, a veces con un .crt acompañante. Las misiones de campaña se
empaquetan en archivos comprimidos .kmp que reúnen el mismo conjunto con
los scripts de la misión.
Tip
Lista el contenido de un mapa de TA:K sin desempaquetar nada:
# 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: el terreno de TA:K (TNT v2)
TA:K reutiliza la estructura TNT de TA, pero sube la palabra
IDVersion. Volcado hexadecimal de 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.......
El primer uint32 es 0x00004000, frente al 0x00002000 del TNT de
TA. El contenedor sigue siendo una cabecera seguida de secciones
direccionadas por punteros, pero TA:K no es en absoluto un formato de
mosaico de casillas. Donde TA guarda una cuadrícula de índices de
casilla y una paleta de gráficos de casilla de 32×32, TA:K guarda el
terreno como una cuadrícula de mapeado de texturas que hace referencia
a texturas JPG externas, más un mapa de alturas aparte y una
cuadrícula de colocación de elementos. Todo lo que sigue está
verificado en los 55 mapas distribuidos:
Width/Heightcuentan DataUnits de 16 px, no píxeles. Un mapa «15 × 15» comoathri cayguardaWidth = Height = 480DataUnits →480 × 16 = 7680px de lado. El mapa de alturas y la cuadrícula de elementos se muestrean por DataUnit; el terreno se muestrea en una cuadrícula más gruesa de Graphic Units de 32 px, exactamente la mitad que la de DataUnits en cada eje (guW = Width/2).- La cabecera son doce
uint32consecutivos de desplazamientos y recuentos; los nombres de campo de TA ya no describen su contenido. La tabla de abajo da el significado en TA:K. - Los punteros de sección son absolutos, así que cada sección se lee a partir de su propio puntero y de una longitud calculada.
| Desplazamiento | Campo de TA:K | Tamaño de la sección | Notas |
|---|---|---|---|
0x00 |
Version |
— | 0x4000 (TA escribe 0x2000) |
0x04 |
Width |
— | DataUnits; ×16 → píxeles, ÷2 → Graphic Units |
0x08 |
Height |
— | DataUnits |
0x0C |
SeaLevel |
— | umbral de altura del agua |
0x10 |
HeightMapOffset |
Width × Height bytes |
un byte de altura por DataUnit |
0x14 |
AttributesOffset |
Width × Height × 2 |
cuadrícula de elementos: un índice uint16 por DataUnit (≥0xFF00 = ninguno) |
0x18 |
FeatureNamesOffset |
Count × 132 |
tabla de nombres de elementos (índice de 4 bytes + nombre de 128 bytes) |
0x1C |
FeatureCount |
— | número de tipos de elemento |
0x20 |
TerrainNamesOffset |
guW × guH × 4 |
nombre de textura por GU → terrain/%08x.jpg |
0x24 |
UMappingOffset |
guW × guH bytes |
desplazamiento de columna por GU dentro de su textura (×32 px) |
0x28 |
VMappingOffset |
guW × guH bytes |
desplazamiento de fila por GU dentro de su textura (×32 px) |
0x2C |
MiniMapOffset |
8 + 126×126 |
uint32 w, uint32 h y después los índices |
El mapa de alturas (0x10) tiene un byte por DataUnit: es un campo de
elevación en escala de grises, no un mapa de bits de color. El
terreno se reconstruye por mapeado de texturas: para cada Graphic
Unit, la tabla de nombres de terreno (0x20) da un archivo de textura
(terrain/<name>.jpg, con el nombre escrito como 8 dígitos hexadecimales
en minúsculas) y las tablas U/V (0x24/0x28) dan la subcasilla de 32×32
que hay que copiar de ese JPG en (u×32, v×32). La cuadrícula de
elementos (0x14) es la capa de colocación: un array Width × Height
de uint16 en el que cada celda es o bien un índice de elemento en la
tabla de nombres o bien un valor centinela alto (≥0xFF00) que significa
«aquí no hay elemento»; la celda DataUnit (x, y) de una colocación
corresponde al píxel de terreno (x×16, y×16). La tabla de nombres
(0x18) usa la misma disposición de entradas de 132 bytes que la tabla
TileAnim de TA.
El bloque del minimapa mide siempre 126 × 126 en todo el material
distribuido y usa el mismo byte de vacío 0x64 que TA como relleno
fuera de los mapas no cuadrados.
Note
Qué funciona hoy con los TNT de TA:K. kbot tnt describe muestra
la cabecera, el reino, las dimensiones del mapa de alturas y del terreno
y el desglose de elementos. kbot tnt preview --vfs <root> renderiza el
terreno con texturas a resolución completa y compone encima el
sprite GAF de cada elemento, anclado en su hotspot: el mapa completo tal
como lo dibuja el juego. kbot tnt image renderiza el mapa de alturas en
escala de grises, que no depende de nada más (no necesita texturas
externas; --features superpone marcadores coloreados por categoría).
kbot tnt minimap exporta la vista previa incrustada de 126 × 126.
Paleta del minimapa: una por reino
TA:K no colorea su minimapa con una única paleta global. Cada mapa
genera su vista previa de 126 × 126 con la paleta de texturas del reino
al que pertenece: el campo kingdom= del .ota acompañante (aramon /
taros / veruna / zhon / creon). Si renderizas los mismos índices
con la paleta de otro reino (o con el PALETTE.PAL de TA) obtienes ruido
moteado; con la correcta salen agua, playas y terreno naturales.
kbot tnt minimap resuelve el reino automáticamente a partir del .ota
acompañante. Cuando no hay .ota (p. ej., un .tnt suelto), pasa
--kingdom <name> de forma explícita:
kbot tnt minimap "athri cay.tnt" -t mini.png # auto: veruna
kbot tnt minimap loose.tnt --kingdom aramon -t mini.png
.ota: metadatos del mapa (TDF, casi todo conocido)
El .ota de TA:K tiene el mismo formato con forma de TDF que el de TA,
con varios campos propios de TAK. El archivo completo de
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; }
…
}
}
}
| Campo | Equivalente en TA | Notas |
|---|---|---|
kingdom= |
ninguno | Afinidad de bando (aramon / taros / veruna / zhon / creon). El lobby filtra por él; también elige la paleta de terreno/minimapa con la que está coloreada la vista previa incrustada del .tnt. |
size= |
ninguno | Tamaño del mapa legible para el lobby. |
memory= |
ninguno | RAM recomendada. Solo estético. |
hasscenario= |
ninguno | 1 en las misiones de campaña, 0 en los mapas de escaramuza. |
[Map Data] |
[Schema N] |
Reduce la subsección de esquema a un único bloque (TA:K nunca distribuye más de un esquema por mapa). |
Todo lo demás (StartPos1..N, aiprofile=, etc.) funciona igual que en
TA: el visor de OTA de kbot mount maneja ambos sin cambios.
.kmp: archivos comprimidos HPI v2 de misiones de campaña
.kmp es un archivo comprimido HPI v2 con
otra extensión. El principio de adamantine gate.kmp en hexadecimal:
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…
Es exactamente la forma de la cabecera v2 (marca HAPI → versión
0x00020000 → cabecera v2 de 24 bytes → chunks SQSH). kbot hpi list,
info y extract funcionan directamente. Cada .kmp suele contener:
- El
.tnty el.otade la misión - Unos cuantos GAF de cinemáticas y de instrucciones de la misión
- Archivos COB de scripts de misión: TA:K reutiliza el formato COB
(
VersionSignature == 6) para los scripts de misión, en lugar de un lenguaje de scripting aparte. Aquí están los 3885 usos del opcodeMISSION_COMMAND(0x10073000) de la instalación comercial de TAK. Consulta Diferencias de COB v6 en TA: Kingdoms y el apéndice C de cob.md para el formato en disco y el pool de cadenas de nombres de sonido por COB al que indexan las órdenes de misión. - A veces, modificaciones de unidades propias de la misión
.crt: script del escenario (unidades, reglas, disparadores)
Un .crt contiene la capa con script de un mapa: las unidades colocadas
antes de que empiece la partida, el motor de reglas por jugador que
dirige la IA de escaramuza y los objetivos de campaña, y las regiones de
disparo rectangulares con nombre a las que hacen referencia esas reglas.
Los mapas multijugador distribuyen un esqueleto vacío (sin unidades,
nueve plazas de jugador vacías, sin disparadores, 56 bytes); los mapas de
campaña y los especiales rellenan todas las secciones, hasta unos 120 KB.
Todo el archivo es little-endian y es una imagen directa de las estructuras en memoria del motor, así que los registros de unidad incluyen varios campos de relleno sin inicializar.
Cabecera
| Desplazamiento | Tipo | Campo | Notas |
|---|---|---|---|
0x00 |
uint32 |
Signature | 0x3F800000: marca 1.0f en IEEE-754 |
0x04 |
uint32 |
Unknown1 | 0 en todos los mapas distribuidos salvo uno |
0x08 |
uint32 |
UnitCount | número de registros de unidades colocadas que siguen |
abnar's terrace.crt (un esqueleto vacío) empieza así:
00000000: 00 00 80 3f 00 00 00 00 00 00 00 00 09 00 00 00
1.0f, Unknown1 = 0, UnitCount = 0 y después el número de jugadores,
9.
Registros de unidad (568 bytes cada uno)
| Desplazamiento | Tipo | Campo |
|---|---|---|
+0 |
char[256] |
UnitType (terminado en NUL) |
+256 |
char[256] |
UniqueName (normalmente vacío) |
+512 |
uint32 |
X (mundo) |
+516 |
uint32 |
Y (eje de altura) |
+520 |
uint32 |
Z (mundo) |
+524 |
uint32 |
PlayerId (empieza en 0) |
+528 |
uint32 |
HealthPercent (normalmente 100) |
+532 |
uint32 |
ArmorPercent (normalmente 100) |
+536 |
uint32 |
WeaponPercent (normalmente 100) |
+540 |
uint32 |
Angle (normalmente 180) |
+544 |
uint32 |
Veteran |
+548 |
uint32 |
desconocido |
+552 |
uint32 |
desconocido |
+556 |
uint32 |
FootprintX |
+560 |
uint32 |
FootprintZ |
+564 |
uint32 |
desconocido |
Jugadores, reglas, condiciones, acciones
Después de las unidades, un recuento de jugadores uint32 (siempre 9)
precede a otros tantos bloques de jugador. Cada bloque de jugador es un
recuento de reglas uint32 seguido de esas reglas. Una regla es:
- un recuento de condiciones
uint32y después cada condición, que es un opcodeuint32y cinco posiciones de argumento de 64 bytes; - un recuento de acciones
uint32y después cada acción, que es un opcodeuint32y cinco posiciones de argumento de 64 bytes.
Disparadores
Un recuento de disparadores uint32 al final precede a otros tantos
registros de disparador. Cada uno es un nombre de 256 bytes terminado en
NUL seguido de cuatro límites uint32 (Left, Top, Right, Bottom)
en celdas del mapa. Los nombres son legibles (The Hill, Player 1).
Herramientas
kbot crt describe <map.crt> muestra el desglose por tipo de unidad, los
recuentos de reglas y las regiones de disparo; añade --verbose para ver
la lista completa de colocaciones. La herramienta MCP crt_describe
devuelve los mismos datos en JSON.
Un archivo, cairbray coast landing.crt, tiene una cabecera desplazada y
editada a mano que no encaja con esta disposición; el analizador lo
rechaza con un error claro en lugar de decodificarlo mal.
.txt: descripción en texto libre
Una cadena ASCII de una línea que se usa en el lobby. Por ejemplo,
abnar's terrace.txt: 9 x 7 4 Player 32MB (la misma cadena que lleva
el missiondescription del .ota). Probablemente las herramientas de
creación escribían las dos al exportar; el juego parece mostrar el valor
del .ota.
Trabajar hoy con mapas de TA:K
Opciones prácticas, de menos a más esfuerzo:
- Inspeccionar sin restricciones:
kbot hpi list/info/extractsobre archivos.kmpfunciona sin más..otay.txtson texto plano. - Describir un mapa:
kbot tnt describe <map.tnt>muestra la cabecera de TA:K, el reino, las dimensiones del mapa de alturas y del terreno y un desglose de elementos. - Renderizar un minimapa:
kbot tnt minimap <map.tnt> -t mini.pngexporta la vista previa incrustada de 126 × 126 en color real y elige automáticamente la paleta del reino a partir del.otaacompañante (puedes forzarla con--kingdom; consulta la nota sobre la paleta de arriba). - Renderizar el mapa completo con texturas:
kbot tnt preview <map.tnt> --vfs <flattened-tak-root> -t map.pngmapea las texturas del terreno a partir de losterrain/*.jpgde la instalación y compone el sprite GAF de cada elemento, con lo que produce el mapa tal como lo renderiza el juego (athri cay → 7680 × 7680). La paleta de los sprites de elementos se lee depalettes/<kingdom>_features.pcx. - Renderizar el mapa de alturas:
kbot tnt image <map.tnt> -t height.pngno necesita recursos externos; genera el mapa de alturas por DataUnit en escala de grises (--featuressuperpone marcadores de colocación coloreados por categoría). - Reempaquetar un archivo comprimido de campaña: hoy
kbot hpi packsolo produce v1, así que un.kmpreempaquetado no cargaría. Para editar a mano un.kmp, extráelo, modifica los archivos sueltos y usa un empaquetador de terceros que entienda v2 hasta que kbot sepa escribir v2.
Warning
TA: Kingdoms necesita -disablecavedogverification para cargar la
mayoría de los archivos modificados, mapas modificados incluidos. Sin
esa opción, el motor rechaza todo aquello cuyo hash no esté en su lista
de permitidos. Indícalo en las instrucciones de instalación de cualquier
mod.
Qué puede hacer kbot ahora mismo con los mapas de TA:K y qué no
| Operación | Estado |
|---|---|
Leer las cabeceras y la lista de archivos de un .kmp (HPI v2) |
✅ |
Extraer archivos de un .kmp |
✅ |
Analizar un .ota (formato TDF) |
✅ |
Leer la cabecera de un .tnt de TA:K (kbot tnt describe) |
✅ |
Exportar el minimapa de un .tnt de TA:K (kbot tnt minimap) |
✅ (color real: paleta por reino a partir del .ota) |
Renderizar el mapa completo de TA:K con texturas (kbot tnt preview --vfs) |
✅ (terreno con texturas + sprites GAF de los elementos) |
Renderizar el mapa de alturas de TA:K (kbot tnt image) |
✅ (escala de grises sin dependencias; --features superpone marcadores) |
Escribir un .tnt de TA:K (kbot tnt pack) |
❌ |
Escribir un .kmp (empaquetado HPI v2) |
❌ |
Las pull requests para cualquiera de los puntos ❌ son bienvenidas. Con el
mapa de alturas, la cuadrícula de mapeado de texturas, la cuadrícula de
elementos y la tabla de elementos ya decodificados, el terreno y los
elementos se renderizan a resolución completa; lo que falta es la parte
de escritura para hacer el viaje de ida y vuelta con mapas de TA:K
editados y el empaquetado v2 de .kmp.
Véase también
- HPI: el contenedor de archivo comprimido v2 (
.kmpes un HPI v2 con otra extensión). - TNT: el formato TNT de TA; TA:K reutiliza la estructura con un IDVersion
0x4000. - TDF: el formato con el que se analiza el
.ota. - GAF: los archivos de animación
.tafque se usan en todo TA:K (cinemáticas dentro de archivos comprimidos.kmp). - Interfaz de TA: Kingdoms: el formato de widgets de menús y HUD.
- Glosario: side, heightmap.