Все страницы форматов ↓
Карты и рельеф

Карты TA: Kingdoms — .tnt + .ota + .crt + .kmp

Источник: coreprime/kbot @ 0ab97bf · Редактировать на GitHub

Карты TA: Kingdoms — это вариант TNT (с другим словом IDVersion), дополненный одним или двумя файлами метаданных, а для миссий одиночной игры есть ещё формат архивов кампании на основе HPI v2. Это намного ближе к модели карт TA, чем предполагали старые исследовательские заметки про «BTM / BMP с картой высот»: в настоящей установке TA:K от GoG нет ни .btm, ни сопутствующих BMP.

Существующий в kbot читатель HPI v2 прозрачно открывает архивы .kmp. Читатель TNT в kbot распознаёт слово версии TA:K и декодирует заголовок, карту высот по DataUnit, сетку наложения текстур (таблицы имён текстур рельефа и смещений U/V), сетку расстановки объектов с таблицей имён и встроенную миникарту — этого достаточно, чтобы отрисовать всю карту в полном разрешении, собрав её из внешних JPG-текстур рельефа и GAF-спрайтов объектов. На этой странице описано то, что можно проверить по поставляемой установке, а также оставшиеся пробелы.

Important

Обновление статуса (по сравнению с первоначальной версией этой страницы, «исследовательскими заметками»). Типы файлов, которые здесь раньше обсуждались, — .btm, сопутствующие BMP, PCX с палитрами сторон — в установке TA: Kingdoms от GoG на самом деле отсутствуют. Настоящие типы файлов описаны ниже. Для сравнения с другим проектом TA:K с открытым исходным кодом см. iiCompleteDestruction: для некоторых структур, специфичных для TA:K, их парсер полнее, чем у kbot.


Из каких файлов состоит карта TA:K

Подсчёт по каталогу карт установки от GoG:

Расширение Количество Назначение
.kmp 181 Архив HPI v2, в котором собраны карта, скрипты и ресурсы миссии кампании
.tnt 55 Данные рельефа карты (двоичный файл по образцу TNT со своим для TA:K словом IDVersion)
.ota 55 Метаданные карты — формат TDF, та же структура, что у .ota в TA, с полями, специфичными для TAK
.txt 55 Описание карты в свободной форме (несколько слов, показывается в лобби)
.crt 33 Сопутствующий файл сценария: заранее расставленные юниты, движок правил для каждого игрока, именованные области триггеров
.tdf 6 Файлы настройки игрового процесса для отдельных карт (балансировка кампании, подсказки ИИ)

Обычная карта для сетевой игры поставляется тройкой .tnt + .ota + .txt, иногда с сопутствующим .crt. Миссии кампании упакованы в архивы .kmp, где тот же набор файлов собран вместе со скриптами миссии.

Tip

Просмотр содержимого карты TA:K без распаковки:

# 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 — рельеф TA:K (TNT v2)

TA:K использует структуру TNT из TA, но повышает слово IDVersion. Шестнадцатеричный дамп 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.......

Первый uint32 — 0x00004000, тогда как TNT в TA использует 0x00002000. Контейнер по-прежнему состоит из заголовка и секций, к которым обращаются по указателям, но TA:K вовсе не мозаика из тайлов. Там, где TA хранит сетку индексов тайлов и палитру графики тайлов 32×32, TA:K хранит рельеф как сетку наложения текстур, ссылающуюся на внешние JPG-текстуры, а также отдельную карту высот и сетку расстановки объектов. Всё нижеследующее проверено на 55 поставляемых картах:

  1. Width/Height — это количество DataUnit по 16 пикселей, а не пиксели. Карта «15 × 15», например athri cay, хранит Width = Height = 480 DataUnit → 480 × 16 = 7680 пикселей по стороне. Карта высот и сетка объектов заданы с шагом в один DataUnit, а рельеф — на более крупной сетке Graphic Unit по 32 пикселя, ровно вдвое реже сетки DataUnit по каждой оси (guW = Width/2).
  2. Заголовок — это двенадцать идущих подряд uint32 со смещениями и количествами; имена полей из TA больше не описывают содержимое. В таблице ниже указано их значение в TA:K.
  3. Указатели на секции абсолютные, поэтому каждая секция читается по своему указателю и вычисленной длине.
Смещение Поле TA:K Размер секции Примечания
0x00 Version — 0x4000 (TA пишет 0x2000)
0x04 Width — в DataUnit; ×16 → пиксели, ÷2 → Graphic Unit
0x08 Height — в DataUnit
0x0C SeaLevel — порог высоты для воды
0x10 HeightMapOffset Width × Height байт один байт высоты на DataUnit
0x14 AttributesOffset Width × Height × 2 сетка объектов: индекс uint16 на DataUnit (≥0xFF00 = нет объекта)
0x18 FeatureNamesOffset Count × 132 таблица имён объектов (4-байтовый индекс + 128-байтовое имя)
0x1C FeatureCount — количество типов объектов
0x20 TerrainNamesOffset guW × guH × 4 имя текстуры для каждой GU → terrain/%08x.jpg
0x24 UMappingOffset guW × guH байт смещение столбца внутри текстуры для каждой GU (×32 пикселя)
0x28 VMappingOffset guW × guH байт смещение строки внутри текстуры для каждой GU (×32 пикселя)
0x2C MiniMapOffset 8 + 126×126 uint32 w, uint32 h, затем индексы

Карта высот (0x10) — это один байт на DataUnit, поле высот в оттенках серого, а не цветное изображение. Рельеф восстанавливается наложением текстур: для каждой Graphic Unit таблица имён текстур рельефа (0x20) даёт файл текстуры (terrain/<name>.jpg, имя записано как 8-значное шестнадцатеричное число в нижнем регистре), а таблицы U/V (0x24/0x28) — подтайл 32×32, который нужно скопировать из этого JPG с позиции (u×32, v×32). Сетка объектов (0x14) — это слой расстановки: массив uint16 размером Width × Height, где каждая ячейка содержит либо индекс объекта в таблице имён, либо большое сигнальное значение (≥0xFF00), означающее «здесь объекта нет»; ячейка DataUnit (x, y) соответствует пикселю рельефа (x×16, y×16). Таблица имён (0x18) использует ту же 132-байтовую структуру записи, что и таблица TileAnim в TA.

Блок миникарты во всех поставляемых картах всегда 126 × 126 и использует тот же байт пустоты 0x64, что и в TA, для заполнения вне неквадратных карт.

Note

Что уже работает с TNT из TA:K. kbot tnt describe выводит заголовок, королевство, размеры карты высот и рельефа и сводку по объектам. kbot tnt preview --vfs <root> отрисовывает рельеф в полном разрешении с наложенными текстурами и накладывает поверх GAF-спрайт каждого объекта, привязанный к его активной точке, — всю карту так, как её рисует игра. kbot tnt image отрисовывает самодостаточную карту высот в оттенках серого (внешние текстуры не нужны; --features добавляет маркеры, раскрашенные по категориям). kbot tnt minimap экспортирует встроенное превью 126 × 126.

Палитра миникарты — своя для каждого королевства

TA:K не раскрашивает миникарту одной общей палитрой. Превью 126 × 126 каждой карты запечено с палитрой текстур того королевства, которому она принадлежит, — это поле kingdom= в соседнем .ota (aramon / taros / veruna / zhon / creon). Если отрисовать те же индексы с палитрой чужого королевства (или с PALETTE.PAL из TA), получится пёстрый шум; с правильной палитрой видны естественные вода, пляжи и рельеф.

kbot tnt minimap определяет королевство автоматически по соседнему .ota. Если .ota нет (например, .tnt лежит отдельно), передайте --kingdom <name> явно:

kbot tnt minimap "athri cay.tnt" -t mini.png          # auto: veruna
kbot tnt minimap loose.tnt --kingdom aramon -t mini.png

.ota — метаданные карты (TDF, в основном знакомый)

.ota в TA:K — тот же формат в стиле TDF, что и в TA, с несколькими полями, специфичными для TAK. Полный файл 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;  }
            …
        }
    }
}
Поле Аналог в TA Примечания
kingdom= нет Принадлежность к стороне (aramon / taros / veruna / zhon / creon). По нему фильтрует лобби; кроме того, оно выбирает палитру рельефа и миникарты, которой раскрашено запечённое превью в .tnt.
size= нет Размер карты в читаемом виде для лобби.
memory= нет Рекомендуемый объём ОЗУ. Ни на что не влияет.
hasscenario= нет 1 для миссий кампании, 0 для карт схватки.
[Map Data] [Schema N] Сводит подсекцию схемы к одному блоку (TA:K всегда поставляет только одну схему на карту).

Всё остальное (StartPos1..N, aiprofile= и т. д.) работает так же, как в TA: просмотрщик OTA в kbot mount справляется с обоими вариантами без изменений.


.kmp — архивы HPI v2 с миссиями кампании

.kmp — это переименованный архив HPI v2. Начало файла 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…

В точности структура заголовка v2 (маркер HAPI → версия 0x00020000 → 24-байтовый заголовок v2 → фрагменты SQSH). kbot hpi list, info, extract работают напрямую. Обычно в .kmp упакованы:

  • .tnt и .ota миссии
  • Несколько GAF для роликов и брифингов
  • COB-файлы скриптов миссии — для скриптов миссий TA:K использует формат COB (VersionSignature == 6), а не отдельный язык скриптов. Здесь находятся все 3 885 мест опкода MISSION_COMMAND (0x10073000) в оригинальной установке TAK. Формат хранения и пул строк с именами звуков в каждом COB, на который ссылаются команды миссии по индексу, описаны в разделах TA: Kingdoms — отличия COB v6 и Приложение C в cob.md.
  • Иногда — переопределения юнитов для конкретной миссии

.crt — скрипт сценария (юниты, правила, триггеры)

.crt содержит скриптовый слой карты: юниты, расставленные до начала игры, движок правил для каждого игрока, который управляет ИИ в схватке и задачами кампании, и именованные прямоугольные области триггеров, на которые ссылаются эти правила. Карты для сетевой игры поставляются с пустой заглушкой (без юнитов, девять пустых слотов игроков, без триггеров, 56 байт); в картах кампании и особых картах заполнены все секции, вплоть до ~120 КБ.

Весь файл записан в little-endian и представляет собой прямой образ структур движка в памяти, поэтому записи юнитов содержат несколько неинициализированных полей выравнивания.

Смещение Тип Поле Примечания
0x00 uint32 Signature 0x3F800000 — маркер IEEE-754 1.0f
0x04 uint32 Unknown1 0 на всех поставляемых картах, кроме одной
0x08 uint32 UnitCount число следующих записей расставленных юнитов

abnar's terrace.crt (пустая заглушка) начинается так:

00000000: 00 00 80 3f 00 00 00 00 00 00 00 00 09 00 00 00

1.0f, Unknown1 = 0, UnitCount = 0, затем число игроков 9.

Записи юнитов (по 568 байт)

Смещение Тип Поле
+0 char[256] UnitType (завершён NUL)
+256 char[256] UniqueName (обычно пусто)
+512 uint32 X (мир)
+516 uint32 Y (ось высоты)
+520 uint32 Z (мир)
+524 uint32 PlayerId (с 0)
+528 uint32 HealthPercent (обычно 100)
+532 uint32 ArmorPercent (обычно 100)
+536 uint32 WeaponPercent (обычно 100)
+540 uint32 Angle (обычно 180)
+544 uint32 Veteran
+548 uint32 неизвестно
+552 uint32 неизвестно
+556 uint32 FootprintX
+560 uint32 FootprintZ
+564 uint32 неизвестно

Игроки, правила, условия, действия

После юнитов идёт uint32 с числом игроков (всегда 9), а за ним — столько же блоков игроков. Каждый блок игрока — это uint32 с числом правил, за которым следуют сами правила. Правило устроено так:

  • uint32 с числом условий, затем каждое условие — это опкод uint32 и пять 64-байтовых слотов аргументов;
  • uint32 с числом действий, затем каждое действие — это опкод uint32 и пять 64-байтовых слотов аргументов.

Триггеры

Завершающий uint32 с числом триггеров предшествует такому же числу записей триггеров. Каждая запись — это 256-байтовое имя, завершённое NUL, и четыре границы uint32 — Left, Top, Right, Bottom — в ячейках карты. Имена читаемые (The Hill, Player 1).

Инструменты

kbot crt describe <map.crt> выводит сводку по типам юнитов, число правил и области триггеров; добавьте --verbose, чтобы получить полный список расстановки. MCP-инструмент crt_describe возвращает те же данные в виде JSON.

Один файл — cairbray coast landing.crt — имеет сдвинутый, вручную отредактированный заголовок, не соответствующий этой структуре; парсер отклоняет его с понятной ошибкой, а не декодирует неверно.


.txt — описание в свободной форме

Одна строка ASCII, используется в лобби. Например, abnar's terrace.txt: 9 x 7 4 Player 32MB (та же строка, что в поле missiondescription файла .ota). Скорее всего, инструменты создания карт записывали оба файла при экспорте; игра, по-видимому, показывает значение из .ota.


Работа с картами TA:K сегодня

Практические варианты, по возрастанию трудоёмкости:

  1. Свободный просмотр — kbot hpi list/info/extract работает с файлами .kmp сразу. .ota и .txt — обычный текст.
  2. Описание карты — kbot tnt describe <map.tnt> выводит заголовок TA:K, королевство, размеры карты высот и рельефа и сводку по объектам.
  3. Отрисовка миникарты — kbot tnt minimap <map.tnt> -t mini.png экспортирует встроенное превью 126 × 126 в полном цвете, автоматически выбирая палитру королевства по соседнему .ota (переопределяется через --kingdom; см. примечание о палитре выше).
  4. Отрисовка всей текстурированной карты — kbot tnt preview <map.tnt> --vfs <flattened-tak-root> -t map.png накладывает на рельеф текстуры из terrain/*.jpg установки и добавляет GAF-спрайт каждого объекта, получая карту такой, какой её отрисовывает игра (athri cay → 7680 × 7680). Палитра спрайтов объектов читается из palettes/<kingdom>_features.pcx.
  5. Отрисовка карты высот — kbot tnt image <map.tnt> -t height.png не требует внешних ресурсов и выдаёт карту высот по DataUnit в оттенках серого (--features добавляет маркеры расстановки, раскрашенные по категориям).
  6. Перепаковка архива кампании — kbot hpi pack пока создаёт только v1, поэтому перепакованный .kmp не загрузится. Чтобы вручную отредактировать .kmp, извлеките его, измените файлы и упакуйте сторонним упаковщиком с поддержкой v2, пока kbot не научится записывать v2.

Warning

TA: Kingdoms требует -disablecavedogverification, чтобы загрузить большинство изменённых файлов, включая изменённые карты. Без этого ключа движок отклоняет всё, чей хэш не входит в его список разрешённых. Указывайте это в инструкции по установке любого мода.


Что kbot умеет и чего не умеет с картами TA:K сейчас

Операция Статус
Чтение заголовков .kmp (HPI v2) и списка файлов ✅
Извлечение файлов из .kmp ✅
Разбор .ota (формат TDF) ✅
Чтение заголовка .tnt TA:K (kbot tnt describe) ✅
Экспорт миникарты .tnt TA:K (kbot tnt minimap) ✅ (полный цвет — палитра королевства из .ota)
Отрисовка всей текстурированной карты TA:K (kbot tnt preview --vfs) ✅ (рельеф с наложенными текстурами + GAF-спрайты объектов)
Отрисовка карты высот TA:K (kbot tnt image) ✅ (самодостаточная, в оттенках серого; --features добавляет маркеры)
Запись .tnt TA:K (kbot tnt pack) ❌
Запись .kmp (упаковка HPI v2) ❌

Пулреквесты по любому из пунктов ❌ приветствуются. Карта высот, сетка наложения текстур, сетка объектов и таблица объектов уже декодированы, так что рельеф и объекты отрисовываются в полном разрешении; остаются запись для round-trip отредактированных карт TA:K и упаковка .kmp v2.


См. также

  • HPI — контейнер архивов v2 (.kmp — это HPI v2 с переименованным расширением).
  • TNT — формат TNT из TA; TA:K использует ту же структуру с IDVersion 0x4000.
  • TDF — формат, в котором разбирается .ota.
  • GAF — файлы анимаций .taf, которые используются по всей TA:K (ролики в архивах .kmp).
  • Интерфейс TA: Kingdoms — формат виджетов меню и HUD.
  • Глоссарий — side, heightmap.