Todas as páginas de formatos ↓
Mapas e terreno

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 .btm nem BMP acompanhante.

O leitor de HPI v2 que o kbot já tem lida com arquivos .kmp de 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:

  1. Width/Height contam DataUnits de 16 px, não pixels. Um mapa "15 × 15" como athri cay guarda Width = Height = 480 DataUnits → 480 × 16 = 7680 px 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).
  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.
  3. 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 .tnt e o .ota da 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 opcode MISSION_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.

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 opcode uint32 e cinco posições de argumento de 64 bytes;
  • uma contagem de ações uint32, e depois cada ação é um opcode uint32 e 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:

  1. Inspecionar à vontade: kbot hpi list/info/extract em arquivos .kmp funciona sem configuração. .ota e .txt são texto simples.
  2. 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.
  3. Renderizar um minimapa: kbot tnt minimap <map.tnt> -t mini.png exporta a prévia embutida de 126 × 126 em cores reais, escolhendo automaticamente a paleta do reino pelo .ota vizinho (substitua com --kingdom; veja a nota sobre a paleta acima).
  4. Renderizar o mapa texturizado completo: kbot tnt preview <map.tnt> --vfs <flattened-tak-root> -t map.png aplica as texturas ao terreno a partir dos terrain/*.jpg da 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 de palettes/<kingdom>_features.pcx.
  5. Renderizar o mapa de altura: kbot tnt image <map.tnt> -t height.png não precisa de recursos externos. Gera o mapa de altura por DataUnit em tons de cinza (--features sobrepõe marcadores de posicionamento coloridos por categoria).
  6. Reempacotar um arquivo compactado da campanha: hoje kbot hpi pack só produz v1, então um .kmp reempacotado 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 .taf usados 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).