Mapas do TA: Kingdoms (.tnt + .ota + .crt + .kmp)
Fonte: coreprime/kbot @ 0ab97bf · Editar no GitHub
Os mapas do TA: Kingdoms são uma variante do TNT (com outro valor de IDVersion) acompanhada de um ou dois arquivos de metadados, mais um formato de arquivo compactado HPI v2 para as missões da campanha de um jogador. Isso é bem mais próximo do modelo de mapas do TA do que as antigas notas de pesquisa sobre "BTM/BMP de mapa de altura" sugeriam: numa instalação real do TA:K da GOG, não há nenhum
.btmnem BMP acompanhante.O leitor de HPI v2 que o kbot já tem lida com arquivos
.kmpde forma transparente. O leitor de TNT do kbot reconhece o valor de versão do TA:K e decodifica o cabeçalho, o mapa de altura por DataUnit, a grade de mapeamento de texturas (tabelas de nomes de terreno + offsets U/V), a grade de posicionamento de elementos + a tabela de nomes e o minimapa embutido: o suficiente para renderizar um mapa completo em resolução máxima, compondo os JPGs de terreno externos e os sprites GAF dos elementos. Esta página documenta o que dá para verificar na instalação distribuída e as lacunas que restam.
Important
Atualização de situação (em relação à versão original de "notas de
pesquisa" desta página). Os tipos de arquivo de que esta página
tratava (.btm, BMPs acompanhantes, PCXs de paleta por lado) não
estão presentes de fato na instalação do TA: Kingdoms distribuída pela
GOG. Os tipos de arquivo reais estão documentados abaixo. Para comparar
com outro projeto de código aberto do TA:K, veja o
iiCompleteDestruction.
A implementação do analisador deles é mais completa que a do kbot em algumas
estruturas específicas do TA:K.
Arquivos que formam um mapa do TA:K
Contagem na pasta de mapas da instalação da GOG:
| Extensão | Quantidade | Finalidade |
|---|---|---|
.kmp |
181 | Arquivo compactado HPI v2 que reúne o mapa, os scripts e os recursos de uma missão da campanha |
.tnt |
55 | Dados do terreno do mapa (binário no formato do TNT, com um valor de IDVersion próprio do TA:K) |
.ota |
55 | Metadados do mapa: formato TDF, com a mesma estrutura do .ota do TA e campos próprios do TAK |
.txt |
55 | Descrição do mapa em texto livre (poucas palavras, mostradas no lobby) |
.crt |
33 | Arquivo acompanhante do cenário: unidades posicionadas, motor de regras por jogador, regiões de gatilho com nome |
.tdf |
6 | Arquivos de ajustes de jogabilidade por mapa (ajustes da campanha, empurrões na IA) |
Um mapa multijogador típico vem como o trio .tnt + .ota + .txt, às
vezes com um .crt acompanhante. As missões da campanha são empacotadas
em arquivos .kmp que reúnem esse mesmo conjunto com os scripts da
missão.
Tip
Liste o conteúdo de um mapa do TA:K sem desempacotar 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: o terreno do TA:K (TNT v2)
O TA:K reaproveita a estrutura do TNT do TA, mas muda o valor de
IDVersion. Dump 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.......
O primeiro uint32 é 0x00004000; compare com o TNT do TA, que usa
0x00002000. O contêiner continua sendo um cabeçalho seguido de seções
endereçadas por ponteiros, mas o TA:K não é, de forma alguma, um
formato de mosaico de blocos. Onde o TA guarda uma grade de índices de
blocos + uma paleta de gráficos de blocos de 32×32, o TA:K guarda o
terreno como uma grade de mapeamento de texturas que referencia
texturas JPG externas, mais um mapa de altura separado e uma grade
de posicionamento de elementos. Tudo o que vem a seguir foi verificado
nos 55 mapas distribuídos:
Width/Heightcontam DataUnits de 16 px, não pixels. Um mapa "15 × 15" comoathri cayguardaWidth = Height = 480DataUnits →480 × 16 = 7680px de lado. O mapa de altura e a grade de elementos são amostrados por DataUnit. O terreno é amostrado numa grade mais grossa, de Graphic Units de 32 px, que tem exatamente a metade da grade de DataUnits em cada eixo (guW = Width/2).- O cabeçalho são doze
uint32s seguidos de offsets e contagens. Os nomes dos campos do TA não descrevem mais o conteúdo. A tabela abaixo dá o significado no TA:K. - Os ponteiros de seção são absolutos, por isso cada seção é lida pelo seu próprio ponteiro + um comprimento calculado.
| Offset | Campo do TA:K | Tamanho da seção | Observações |
|---|---|---|---|
0x00 |
Version |
— | 0x4000 (o TA grava 0x2000) |
0x04 |
Width |
— | DataUnits; ×16 → pixels, ÷2 → Graphic Units |
0x08 |
Height |
— | DataUnits |
0x0C |
SeaLevel |
— | limite de altura para a água |
0x10 |
HeightMapOffset |
Width × Height bytes |
um byte de altura por DataUnit |
0x14 |
AttributesOffset |
Width × Height × 2 |
grade de elementos: índice uint16 por DataUnit (≥0xFF00 = nenhum) |
0x18 |
FeatureNamesOffset |
Count × 132 |
tabela de nomes de elementos (índice de 4 bytes + nome de 128 bytes) |
0x1C |
FeatureCount |
— | número de tipos de elemento |
0x20 |
TerrainNamesOffset |
guW × guH × 4 |
nome da textura por GU → terrain/%08x.jpg |
0x24 |
UMappingOffset |
guW × guH bytes |
offset de coluna por GU dentro da sua textura (×32 px) |
0x28 |
VMappingOffset |
guW × guH bytes |
offset de linha por GU dentro da sua textura (×32 px) |
0x2C |
MiniMapOffset |
8 + 126×126 |
uint32 w, uint32 h, depois os índices |
O mapa de altura (0x10) tem um byte por DataUnit: um campo de
elevação em tons de cinza, não um bitmap colorido. O terreno é
reconstruído por mapeamento de texturas: para cada Graphic Unit, a tabela
de nomes de terreno (0x20) dá um arquivo de textura
(terrain/<name>.jpg, com o nome escrito em hexadecimal minúsculo de 8
dígitos), e as tabelas U/V (0x24/0x28) dão o sub-bloco de 32×32 a
copiar desse JPG em (u×32, v×32). A grade de elementos (0x14) é a
camada de posicionamento: um array Width × Height de uint16, em que
cada célula é um índice de elemento na tabela de nomes ou um sentinela
alto (≥0xFF00) que significa "nenhum elemento aqui". A célula de
DataUnit (x, y) de um posicionamento corresponde ao pixel de terreno
(x×16, y×16). A tabela de nomes (0x18) usa a mesma estrutura de
entrada de 132 bytes da tabela TileAnim do TA.
O bloco do minimapa tem sempre 126 × 126 em todo o material
distribuído e usa o mesmo byte de vazio 0x64 do TA para preencher o
espaço fora dos mapas não quadrados.
Note
O que já funciona com os TNTs do TA:K. kbot tnt describe mostra o
cabeçalho, o reino, as dimensões do mapa de altura e do terreno e a
distribuição dos elementos. kbot tnt preview --vfs <root> renderiza o
terreno com mapeamento de texturas em resolução máxima e compõe por
cima o sprite GAF de cada elemento, ancorado no seu hotspot: o mapa
completo como o jogo o desenha. kbot tnt image renderiza o mapa de
altura em tons de cinza, autossuficiente (não precisa de texturas
externas; --features sobrepõe marcadores coloridos por categoria). kbot tnt minimap exporta a prévia embutida de 126 × 126.
A paleta do minimapa: uma por reino
O TA:K não colore o minimapa com uma única paleta global. Cada mapa
grava a sua prévia de 126 × 126 com a paleta de texturas do reino a que
pertence: o campo kingdom= do .ota vizinho (aramon / taros /
veruna / zhon / creon). Renderizar os mesmos índices com a paleta
do reino errado (ou com o PALETTE.PAL do TA) produz um ruído
salpicado. Com a paleta certa, saem água, praias e terreno naturais.
kbot tnt minimap descobre o reino automaticamente pelo .ota vizinho.
Quando o .ota não existe (por exemplo, um .tnt avulso), passe
--kingdom <name> explicitamente:
kbot tnt minimap "athri cay.tnt" -t mini.png # auto: veruna
kbot tnt minimap loose.tnt --kingdom aramon -t mini.png
.ota: metadados do mapa (TDF, quase tudo conhecido)
O .ota do TA:K tem o mesmo formato TDF do .ota do TA, com vários
campos próprios do TAK. O arquivo 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 no TA | Observações |
|---|---|---|
kingdom= |
nenhum | Afinidade de lado (aramon / taros / veruna / zhon / creon). O lobby filtra por ele, e ele também escolhe a paleta de terreno/minimapa com que a prévia gravada no .tnt é colorida. |
size= |
nenhum | Tamanho do mapa, legível por pessoas, para o lobby. |
memory= |
nenhum | RAM sugerida. Apenas informativo. |
hasscenario= |
nenhum | 1 nas missões da campanha, 0 nos mapas de escaramuça. |
[Map Data] |
[Schema N] |
Corresponde à subseção do esquema num único bloco (o TA:K só traz um esquema por mapa). |
Todo o resto (StartPos1..N, aiprofile= etc.) funciona igual ao TA: o
visualizador de OTA do kbot mount lida com os dois sem modificação.
.kmp: arquivos compactados HPI v2 das missões da campanha
O .kmp é um arquivo compactado HPI v2
renomeado. O início, em hexadecimal, de adamantine gate.kmp:
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…
É exatamente a estrutura do cabeçalho v2 (marcador HAPI → versão
0x00020000 → cabeçalho v2 de 24 bytes → chunks SQSH). kbot hpi list,
info e extract funcionam diretamente. Cada .kmp costuma conter:
- O
.tnte o.otada missão - Alguns GAFs de cinemáticas e de briefing
- Arquivos COB com os scripts da missão: o TA:K reaproveita o formato
COB (
VersionSignature == 6) para os scripts das missões, em vez de uma linguagem de script separada. Os 3.885 pontos de uso do opcodeMISSION_COMMAND(0x10073000) na instalação comercial do TAK estão aqui. Veja TA: Kingdoms: diferenças do COB v6 e o Apêndice C em cob.md para o formato binário e o pool de strings de nomes de som de cada COB que os comandos de missão indexam. - Às vezes, substituições de unidades por missão
.crt: script do cenário (unidades, regras, gatilhos)
Um .crt traz a camada de script de um mapa: as unidades posicionadas
antes do início da partida, o motor de regras por jogador que conduz a IA
da escaramuça e os objetivos da campanha, e as regiões de gatilho
retangulares com nome que essas regras referenciam. Os mapas
multijogador trazem um esboço vazio (sem unidades, nove lugares de
jogador vazios, sem gatilhos, 56 bytes). Os mapas da campanha e os
especiais preenchem todas as seções, chegando a ~120 KB.
O arquivo inteiro é little-endian e é uma imagem direta das estruturas do motor na memória, por isso os registros de unidades incluem vários campos de preenchimento não inicializados.
Cabeçalho
| Offset | Tipo | Campo | Observações |
|---|---|---|---|
0x00 |
uint32 |
Signature | 0x3F800000: marcador IEEE-754 1.0f |
0x04 |
uint32 |
Unknown1 | 0 em todos os mapas distribuídos, exceto um |
0x08 |
uint32 |
UnitCount | número de registros de unidades posicionadas que vêm a seguir |
abnar's terrace.crt (um esboço vazio) começa assim:
00000000: 00 00 80 3f 00 00 00 00 00 00 00 00 09 00 00 00
1.0f, Unknown1 = 0, UnitCount = 0 e depois a contagem de jogadores
9.
Registros de unidades (568 bytes cada)
| Offset | Tipo | Campo |
|---|---|---|
+0 |
char[256] |
UnitType (terminado em NUL) |
+256 |
char[256] |
UniqueName (em geral vazio) |
+512 |
uint32 |
X (mundo) |
+516 |
uint32 |
Y (eixo da altura) |
+520 |
uint32 |
Z (mundo) |
+524 |
uint32 |
PlayerId (a partir de 0) |
+528 |
uint32 |
HealthPercent (em geral 100) |
+532 |
uint32 |
ArmorPercent (em geral 100) |
+536 |
uint32 |
WeaponPercent (em geral 100) |
+540 |
uint32 |
Angle (em geral 180) |
+544 |
uint32 |
Veteran |
+548 |
uint32 |
desconhecido |
+552 |
uint32 |
desconhecido |
+556 |
uint32 |
FootprintX |
+560 |
uint32 |
FootprintZ |
+564 |
uint32 |
desconhecido |
Jogadores, regras, condições, ações
Depois das unidades, uma contagem de jogadores uint32 (sempre 9)
precede o mesmo número de blocos de jogador. Cada bloco de jogador é uma
contagem de regras uint32 seguida do mesmo número de regras. Uma regra
é:
- uma contagem de condições
uint32, e depois cada condição é um opcodeuint32e cinco posições de argumento de 64 bytes; - uma contagem de ações
uint32, e depois cada ação é um opcodeuint32e cinco posições de argumento de 64 bytes.
Gatilhos
Uma contagem de gatilhos uint32 no final precede o mesmo número de
registros de gatilho. Cada um é um nome de 256 bytes terminado em NUL,
seguido de quatro limites uint32 (Left, Top, Right, Bottom) em
células do mapa. Os nomes são legíveis por pessoas (The Hill,
Player 1).
Ferramentas
kbot crt describe <map.crt> mostra a distribuição dos tipos de unidade,
as contagens de regras e as regiões de gatilho. Acrescente --verbose
para a lista completa de posicionamentos. A ferramenta MCP crt_describe
devolve os mesmos dados em JSON.
Um arquivo, cairbray coast landing.crt, tem um cabeçalho deslocado,
editado à mão, que não segue esta estrutura. O analisador o rejeita com um
erro claro em vez de decodificá-lo errado.
.txt: descrição em texto livre
Uma string ASCII de uma linha, usada no lobby. Por exemplo,
abnar's terrace.txt: 9 x 7 4 Player 32MB (a mesma string que o
missiondescription do .ota traz). As ferramentas de criação
provavelmente gravavam as duas na exportação. O jogo parece mostrar o
valor do .ota.
Trabalhar com mapas do TA:K hoje
Opções práticas, em ordem crescente de esforço:
- Inspecionar à vontade:
kbot hpi list/info/extractem arquivos.kmpfunciona sem configuração..otae.txtsão texto simples. - Descrever um mapa:
kbot tnt describe <map.tnt>mostra o cabeçalho do TA:K, o reino, as dimensões do mapa de altura e do terreno e a distribuição dos elementos. - Renderizar um minimapa:
kbot tnt minimap <map.tnt> -t mini.pngexporta a prévia embutida de 126 × 126 em cores reais, escolhendo automaticamente a paleta do reino pelo.otavizinho (substitua com--kingdom; veja a nota sobre a paleta acima). - Renderizar o mapa texturizado completo:
kbot tnt preview <map.tnt> --vfs <flattened-tak-root> -t map.pngaplica as texturas ao terreno a partir dosterrain/*.jpgda instalação e compõe o sprite GAF de cada elemento, produzindo o mapa como o jogo o renderiza (athri cay → 7.680 × 7.680). A paleta dos sprites dos elementos é lida depalettes/<kingdom>_features.pcx. - Renderizar o mapa de altura:
kbot tnt image <map.tnt> -t height.pngnão precisa de recursos externos. Gera o mapa de altura por DataUnit em tons de cinza (--featuressobrepõe marcadores de posicionamento coloridos por categoria). - Reempacotar um arquivo compactado da campanha: hoje
kbot hpi packsó produz v1, então um.kmpreempacotado não carregaria. Para editar um.kmpà mão, extraia-o, modifique os arquivos soltos e use um empacotador de terceiros que entenda v2, até o kbot passar a gravar v2.
Warning
O TA: Kingdoms exige -disablecavedogverification para carregar a
maioria dos arquivos modificados, inclusive mapas modificados. Sem isso,
o motor rejeita tudo cujo hash não esteja na sua lista de permissões.
Documente isso nas instruções de instalação de qualquer mod.
O que o kbot consegue e não consegue fazer com mapas do TA:K hoje
| Operação | Situação |
|---|---|
Ler cabeçalhos + lista de arquivos de .kmp (HPI v2) |
✅ |
Extrair arquivos de .kmp |
✅ |
Analisar .ota (formato TDF) |
✅ |
Ler o cabeçalho de .tnt do TA:K (kbot tnt describe) |
✅ |
Exportar o minimapa de .tnt do TA:K (kbot tnt minimap) |
✅ (cores reais: paleta do reino a partir do .ota) |
Renderizar o mapa texturizado completo do TA:K (kbot tnt preview --vfs) |
✅ (terreno com mapeamento de texturas + sprites GAF dos elementos) |
Renderizar o mapa de altura do TA:K (kbot tnt image) |
✅ (tons de cinza, sem dependências; --features sobrepõe marcadores) |
Gravar um .tnt do TA:K (kbot tnt pack) |
❌ |
Gravar .kmp (empacotamento HPI v2) |
❌ |
Pull requests são bem-vindos em qualquer um dos itens ❌. Com o mapa de
altura, a grade de mapeamento de texturas, a grade de elementos e a
tabela de elementos todos decodificados, o terreno e os elementos são
renderizados em resolução máxima. As lacunas que restam são a gravação,
para fazer a ida e volta de mapas do TA:K editados, e o empacotamento de
.kmp v2.
Veja também
- HPI: o contêiner de arquivos compactados v2 (
.kmpé um HPI v2 com a extensão trocada). - TNT: o formato TNT do TA. O TA:K reaproveita a estrutura com um IDVersion
0x4000. - TDF: o formato com que o
.otaé analisado. - GAF: os arquivos de animação
.tafusados em todo o TA:K (cinemáticas nos arquivos compactados.kmp). - Interface do TA: Kingdoms: o formato de widgets dos menus e do HUD.
- Glossário: side (lado), heightmap (mapa de altura).