모든 형식 페이지 ↓
맵·지형

TA: Kingdoms 맵 — .tnt + .ota + .crt + .kmp

출처: coreprime/kbot @ 0ab97bf · GitHub에서 편집

TA: Kingdoms 맵은 메타데이터 파일 한두 개를 곁들인 TNT의 변형(IDVersion 워드가 다름)이며, 여기에 싱글플레이 미션용 HPI v2 캠페인 아카이브 형식이 더해집니다. 예전의 "BTM/높이 맵 BMP" 연구 노트가 짐작했던 것보다 TA의 맵 모델에 훨씬 가깝습니다 — 실제 GoG TA:K 설치본을 살펴보면 .btm이나 부속 BMP 파일은 전혀 없습니다.

kbot의 기존 HPI v2 리더는 .kmp 아카이브를 따로 신경 쓸 필요 없이 그대로 처리합니다. kbot의 TNT 리더는 TA:K 버전 워드를 인식하고 헤더, DataUnit 높이 맵, 텍스처 매핑 그리드(지형 이름 + U/V 오프셋 테이블), 지형지물 배치 그리드 + 이름 테이블, 내장 미니맵을 디코딩합니다 — 외부 지형 JPG와 지형지물 GAF 스프라이트를 합성해 완전한 맵을 원래 해상도로 렌더링하기에 충분합니다. 이 페이지는 정식 출시된 설치본에서 확인할 수 있는 내용과 아직 남아 있는 공백을 정리합니다.

Important

상태 업데이트(이 페이지의 처음 "연구 노트" 버전과 비교해). 이 페이지가 예전에 다루던 파일 유형(.btm, 부속 BMP, 진영별 팔레트 PCX)은 정식 출시된 GoG TA: Kingdoms 설치본에 실제로 존재하지 않습니다. 실제 파일 유형은 아래에 정리되어 있습니다. 다른 오픈 소스 TA:K 프로젝트와 비교해 보려면 iiCompleteDestruction을 참고하세요. 일부 TA:K 전용 구조에 대해서는 그쪽 파서 구현이 kbot보다 더 완전합니다.


TA:K 맵을 이루는 파일

GoG 설치본의 maps 디렉터리 전체에서 센 결과:

확장자 개수 용도
.kmp 181 캠페인 미션의 맵 + 스크립트 + 에셋을 묶은 HPI v2 아카이브
.tnt 55 맵 지형 데이터(TNT 모양의 바이너리, TA:K 전용 IDVersion 워드)
.ota 55 맵 메타데이터 — TDF 형식, TA의 .ota와 같은 모양에 TAK 전용 필드가 추가됨
.txt 55 자유 텍스트 맵 설명(몇 단어, 로비에 표시됨)
.crt 33 시나리오 부속 파일: 미리 배치된 유닛, 플레이어별 규칙 엔진, 이름 붙은 트리거 영역
.tdf 6 맵별 게임플레이 조정 파일(캠페인 조정, AI 유도)

일반적인 멀티플레이 맵은 .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는 TA의 TNT 구조를 다시 쓰지만 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**입니다 — 0x00002000을 쓰는 TA의 TNT와 비교해 보세요. 컨테이너는 여전히 헤더 뒤에 포인터로 가리키는 섹션들이 오는 구조지만, TA:K는 타일 모자이크 형식이 전혀 아닙니다. TA가 타일 인덱스 그리드 + 32×32 타일 그래픽 팔레트를 저장하는 자리에, TA:K는 외부 JPG 텍스처를 참조하는 텍스처 매핑 그리드로 지형을 저장하고, 별도의 높이 맵과 지형지물 배치 그리드를 둡니다. 다음 내용은 모두 정식 출시된 55개 맵에서 확인했습니다.

  1. Width/Height는 픽셀이 아니라 16px _DataUnit_의 개수입니다. athri cay처럼 "15 × 15"인 맵은 Width = Height = 480 DataUnit을 저장합니다 → 한 변이 480 × 16 = 7680 px입니다. 높이 맵과 지형지물 그리드는 DataUnit마다 하나씩 표본을 두고, 지형은 그보다 거친 32px Graphic Unit 그리드로 표본을 둡니다. 이 그리드는 각 축에서 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 지형지물 그리드: DataUnit마다 uint16 인덱스(≥0xFF00 = 없음)
0x18 FeatureNamesOffset Count × 132 지형지물 이름 테이블(4바이트 인덱스 + 128바이트 이름)
0x1C FeatureCount — 지형지물 종류의 수
0x20 TerrainNamesOffset guW × guH × 4 GU별 텍스처 이름 → terrain/%08x.jpg
0x24 UMappingOffset guW × guH바이트 GU별 텍스처 안의 열 오프셋(×32px)
0x28 VMappingOffset guW × guH바이트 GU별 텍스처 안의 행 오프셋(×32px)
0x2C MiniMapOffset 8 + 126×126 uint32 w, uint32 h, 그 뒤 인덱스

높이 맵(0x10)은 DataUnit마다 한 바이트입니다 — 색상 비트맵이 아니라 회색조 고도 필드입니다. 지형은 텍스처 매핑으로 재구성합니다: 각 Graphic Unit에 대해 지형 이름 테이블(0x20)이 텍스처 파일(terrain/<name>.jpg, 이름은 소문자 8자리 16진수로 표기)을 알려 주고, U/V 테이블(0x24/0x28)이 그 JPG의 (u×32, v×32)에서 복사할 32×32 서브타일을 알려 줍니다. 지형지물 그리드(0x14)는 배치 레이어입니다: uint16의 Width × Height 배열로, 각 칸은 이름 테이블을 가리키는 지형지물 인덱스이거나 "여기에는 지형지물 없음"을 뜻하는 높은 감시값(≥0xFF00)입니다. 배치의 DataUnit 칸 (x, y)는 지형 픽셀 (x×16, y×16)에 대응합니다. 이름 테이블(0x18)은 TA의 TileAnim 테이블과 같은 132바이트 항목 구조를 씁니다.

미니맵 블록은 정식 출시된 파일 전체에서 항상 126 × 126이며, 정사각형이 아닌 맵의 바깥쪽을 채울 때 TA와 같은 0x64 공백(void) 바이트를 씁니다.

Note

현재 TA:K TNT에서 되는 것. kbot tnt describe는 헤더, 왕국, 높이 맵/지형 크기, 지형지물 분류별 개수를 보여 줍니다. kbot tnt preview --vfs <root>는 원래 해상도의 텍스처 매핑 지형을 렌더링하고, 그 위에 모든 지형지물의 GAF 스프라이트를 핫스팟에 맞춰 합성합니다 — 게임이 그리는 그대로의 완전한 맵입니다. kbot tnt image는 자체적으로 완결된 회색조 높이 맵을 렌더링합니다(외부 텍스처가 필요 없음, --features는 분류별 색상 표시를 겹쳐 그림). kbot tnt minimap은 내장된 126 × 126 미리 보기를 내보냅니다.

미니맵 팔레트 — 왕국마다 하나

TA:K는 미니맵을 하나의 전역 팔레트로 칠하지 않습니다. 각 맵은 126 × 126 미리 보기를 그 맵이 속한 왕국의 텍스처 팔레트에 맞춰 구워 둡니다 — 같은 이름의 .ota에 있는 kingdom= 필드(aramon / taros / veruna / zhon / creon)입니다. 같은 인덱스를 엉뚱한 왕국의 팔레트로(또는 TA의 PALETTE.PAL로) 렌더링하면 얼룩덜룩한 잡음이 나오고, 올바른 팔레트로 렌더링하면 자연스러운 물, 해변, 지형이 나옵니다.

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, 대부분 익숙함)

TA:K의 .ota는 TA의 것과 같은 TDF 모양의 형식이며, 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= 없음 권장 RAM. 표시용일 뿐입니다.
hasscenario= 없음 캠페인 미션은 1, 스커미시 맵은 0.
[Map Data] [Schema N] 스키마 하위 섹션을 블록 하나로 대응시키는 맵(TA:K는 맵마다 스키마를 하나씩만 배포함).

그 밖의 모든 것(StartPos1..N, aiprofile= 등)은 TA와 똑같이 동작합니다 — kbot mount의 OTA 뷰어는 두 게임의 파일을 고치지 않고 모두 처리합니다.


.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)을 다시 씁니다. 정식판 TAK 설치본 전체에 있는 3,885개의 MISSION_COMMAND(0x10073000) 옵코드 사용 지점이 여기에 있습니다. 바이너리 형식과, 미션 명령이 인덱스로 가리키는 COB별 사운드 이름 문자열 풀은 cob.md의 TA: Kingdoms — COB v6 차이점과 부록 C를 참고하세요.
  • 때로는 미션별 유닛 재정의

.crt — 시나리오 스크립트(유닛, 규칙, 트리거)

.crt는 맵의 스크립트 레이어를 담습니다: 플레이가 시작되기 전에 배치되는 유닛, 스커미시 AI와 캠페인 목표를 움직이는 플레이어별 규칙 엔진, 그리고 그 규칙들이 참조하는 이름 붙은 직사각형 트리거 영역입니다. 멀티플레이 맵은 빈 스텁(유닛 없음, 빈 플레이어 슬롯 아홉 개, 트리거 없음, 56바이트)을 담아 배포되고, 캠페인 맵과 특수 맵은 모든 섹션을 채우며 최대 약 120 KB에 이릅니다.

파일 전체가 리틀 엔디언이며 엔진의 메모리 내 구조체를 그대로 옮긴 것이므로, 유닛 레코드에는 초기화되지 않은 패딩 필드가 여럿 들어 있습니다.

오프셋 형식 필드 비고
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(널 종료)
+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바이트 널 종료 이름과, 맵 칸 단위의 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(.ota의 missiondescription에 들어 있는 것과 같은 문자열). 제작 도구가 내보내기 과정에서 둘 다 썼을 것으로 보이며, 게임은 .ota의 값을 표시하는 것으로 보입니다.


현재 TA:K 맵을 다루는 방법

실제로 쓸 수 있는 방법을 수고가 적은 것부터 순서대로 소개합니다.

  1. 자유롭게 살펴보기 — .kmp 파일에 대한 kbot hpi list/info/extract는 별다른 설정 없이 동작합니다. .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는 로드에 실패합니다. kbot이 v2 쓰기를 지원할 때까지는 .kmp를 추출해 낱개 파일을 고친 다음, v2를 지원하는 서드파티 패커를 써서 손으로 편집하세요.

Warning

TA: Kingdoms는 고친 맵을 포함해 고친 파일 대부분을 로드하려면 -disablecavedogverification이 필요합니다. 이것이 없으면 엔진은 해시가 허용 목록에 없는 모든 것을 거부합니다. 모든 모드의 설치 안내에 이 내용을 적어 두세요.


현재 kbot이 TA:K 맵에 대해 할 수 있는 것과 없는 것

작업 상태
.kmp(HPI v2) 헤더 + 파일 목록 읽기 ✅
.kmp에서 파일 추출 ✅
.ota 파싱(TDF 형식) ✅
TA:K .tnt 헤더 읽기(kbot tnt describe) ✅
TA:K .tnt 미니맵 내보내기(kbot tnt minimap) ✅(트루컬러 — .ota에 따른 왕국별 팔레트)
텍스처를 입힌 TA:K 전체 맵 렌더링(kbot tnt preview --vfs) ✅(텍스처 매핑 지형 + 지형지물 GAF 스프라이트)
TA:K 높이 맵 렌더링(kbot tnt image) ✅(자체 완결 회색조, --features는 표시를 겹쳐 그림)
TA:K .tnt 쓰기(kbot tnt pack) ❌
.kmp 쓰기(HPI v2 패키징) ❌

❌ 항목에 대한 풀 리퀘스트는 언제든 환영합니다. 높이 맵, 텍스처 매핑 그리드, 지형지물 그리드, 지형지물 테이블이 모두 디코딩되었으므로 지형과 지형지물은 원래 해상도로 렌더링됩니다. 남은 공백은 편집한 TA:K 맵을 왕복 변환하기 위한 쓰기 경로와 v2 .kmp 패키징입니다.


함께 보기

  • HPI — v2 아카이브 컨테이너(.kmp는 확장자만 바꾼 HPI v2).
  • TNT — TA의 TNT 형식. TA:K는 0x4000 IDVersion으로 이 구조를 다시 씁니다.
  • TDF — .ota를 파싱하는 형식.
  • GAF — TA:K 전반에서 쓰이는 .taf 애니메이션 파일(.kmp 아카이브 안의 컷신).
  • TA: Kingdoms GUI — 메뉴/HUD 위젯 형식.
  • 용어집 — side, heightmap.