ADT Files - cmangos/issues GitHub Wiki

Introduction

ADT Files contain the actual terrain information (height maps, texturing, WMOs, doodads, etc) required by the client to render the static parts of the terrain. They use a chunked file structure like WDT Files. Each ADT File contains 256 (16x16) map tiles (or map chunks). Each map tile is 33.3333 yards on each side, making the size of the map block in an ADT file 533.3333 yards on each side in total. As every WDT File can reference 64x64 ADT map blocks, the whole map is approximately 34133.33 yards on each side.

Chunks

MVER - Version

Identifier MVER
Length 4 bytes

This chunk specifies the format version. All ADT Files in 1.12.X have Version 18.


MHDR - Header

Identifier MHDR
Length 64 bytes

The Header chunk contains offsets to various other chunks. All offsets are relative to the start of the MHDR data block

00h      uint32          flags;     //Known Values: 1 = contains MFBO
04h      uint32          offsMCIN;
08h      uint32          offsMTEX;
0Ch      uint32          offsMMDX;
10h      uint32          offsMMID;
14h      uint32          offsMWMO;
18h      uint32          offsMWID;
1Ch      uint32          offsMDDF;
20h      uint32          offsMODF;
24h      uint32          offsMFBO;  // this is only set if flags &1.
28h      uint32          offsMH2O;
2Ch      uint32          offsMTFX;
30h      uint32[4]       unused;

MCIN - Chunk Index

Identifier MCIN
Length 4096 bytes

This is a lookup table containing absolute offsets and sizes for every map tile in the file. There are 16x16 = 256 entries of 16 bytes each:

00h    uint32 offsMCNK            // absolute offset.
04h    uint32 size                // the size of the MCNK chunk, this is refering to.
08h    uint32 flags               // these two are always 0. only set in the client.
0Ch    uint32 asyncId

MTEX - Texture File Names

Identifier MTEX
Length variable

A list of zero-terminated file names for the textures used in this map.


MMDX - Doodad File Names

Identifier MMDX
Length variable

A list of zero-terminated file names for the doodads / models used in this map.


MMID - Doodad File Name Lookup

Identifier MMID
Length variable

uint32 offsets into the MMDX chunk for every doodad.


MWMO - WMO File Names

Identifier MWMO
Length variable

A list of zero-terminated file names for the WMOs used in this map.


MWID - WMO File Name Lookup

Identifier MWID
Length variable

uint32 offsets into the MWMO chunk for every doodad.


MDDF - Doodad Definition

Identifier MDDF
Length nDoodad * 36 bytes

Placement Information for Doodads

00h      uint32          mmidEntry;           // references an entry in the MMID chunk, specifying the model to use.
04h      uint32          uniqueId;            // this ID should be unique for all ADTs currently loaded. Blizzard has these unique for the whole game.
08h      float[3]        position;
14h      float[3]        rotation;            // degrees.
20h      uint16          scale;               // 1024 is the default size equaling 1.0f.
22h      uint16          flags;               // values from enum MDDFFlags.

MODF - WMO Definition

Identifier MODF
Length nWMO * 64 bytes

Placement Information for World Map Objects

00h      uint32          mwidEntry;           // references an entry in the MWID chunk, specifying the model to use.
04h      uint32          uniqueId;            // unique ID for the whole map.
08h      float[3]        position;
14h      float[3]        rotation;            // same as in MDDF.
20h      float[3]        lowerBounds;         // these two are position plus the wmo bounding box.
2Ch      float[3]        upperBounds;         // they are used for defining when if they are rendered as well as collision.
38h      uint16          flags;
3Ah      uint16          doodadSet;           // which WMO doodad set is used.
3Ch      uint16          nameSet;             // which WMO name set is used. Used for renaming goldshire inn to northshire inn while using the same model.
3Eh      uint16          padding;

MCNK - Map Chunk Data

Identifier MCNK
Length 128 byte header + variable data

After the general information above 256 MCNK chunks follow. Each of these has a header followed by subchunks. Subchunks mostly behave like normal file chunks, except for some flakyness in their chunk size values. The header looks like this:

00h      uint32          flags;        // 1h=has MCSH, 2h=impassible, 4h=River, 8h=Ocean, 10h=Magma, 20h=Slime, 40h=has MCCV
04h      uint32          IndexX;
08h      uint32          IndexY;
0Ch      uint32          nLayers;      // maximum 4
10h      uint32          nDoodadRefs;
14h      uint32          ofsMCVT;      // offsets to various chunks. Relative to the beginning of the MCNK Chunk
18h      uint32          ofsMCNR;
1Ch      uint32          ofsMCLY;
20h      uint32          ofsMCRF;
24h      uint32          ofsMCAL;
28h      uint32          sizeAlpha;
2Ch      uint32          ofsMCSH;                           // only with flags&0x1
30h      uint32          sizeShadow;
34h      uint32          areaid;
38h      uint32          nMapObjRefs;
3Ch      uint32          holes;
40h      uint2[8][8]     ReallyLowQualityTextureingMap;     // the content is the layer being on top, I guess.
50h      uint32          predTex;                           // ???
54h      uint32          noEffectDoodad;                            // ???
58h      uint32          ofsMCSE;
5Ch      uint32          nSndEmitters;                              //will be set to 0 in the client if ofsSndEmitters doesn't point to MCSE!
60h      uint32          ofsMCLQ;
64h      uint32          sizeLiquid;                                // 8 when not used; only read if >8.
68h      float[3]        position;
74h      uint32          ofsMCCV;                           // only with flags&0x20, had uint32 textureId;
78h      uint32          ofsMCLV;                           // introduced in Cataclysm
7Ch      uint32          unused;                            // currently unused

About the holes in the terrain: This is a bitmapped field, the least significant 16 bits are used row-wise in the following arrangement with a 1 bit meaning that the map chunk has a hole in that part of its area: 0x1 0x2 0x4 0x8 0x10 0x20 0x40 0x80 0x100 0x200 0x400 0x800 0x1000 0x2000 0x4000 0x8000


MCVT Subchunk

Identifier MCVT
Length 580 bytes

These are the actual height values for the 9x9+8x8 vertices. 145 floats in the following order/arrangement:. The values in here are only relative to the position given in the corresponding MCNK chunk.

  1    2    3    4    5    6    7    8    9
   10   11   12   13   14   15   16   17
 18   19   20   21   22   23   24   25   26
   27   28   29   30   31   32   33   34
 35   36   37   38   39   40   41   42   43
   44   45   46   47   48   49   50   51
 52   53   54   55   56   57   58   59   60
   61   62   63   64   65   66   67   68
 69   70   71   72   73   74   75   76   77
   78   79   80   81   82   83   84   85
 86   87   88   89   90   91   92   93   94
   95   96   97   98  99  100  101  102
103  104  105  106  107  108  109  110  111
  112  113  114  115  116  117  118  119
120  121  122  123  124  125  126  127  128
  129  130  131  132  133  134  135  136
137  138  139  140  141  142  143  144  145

WoW uses Squares out of 4 of the Outer(called NoLoD)-Vertices with one of the Inner(called LoD)-Vertices in the Center:

  1    2
    10
 18   19

MCNR Subchunk - Normals

Identifier MCNR
Length 435 bytes + 13 bytes of unknown data

9x9 + 8x8 surface normals, laid out as in the MCVT chunk.

int8[3] normal; // normalized. X, Y, Z. 127 == 1.0, -127 == -1.0.

This chunk has 13 bytes of unknown data at the end. The chunk size only covers the normals, though.


MCLY Subchunk - Texture Layers

Identifier MCLY
Length 1-4 layers * 16 bytes

These are texture layer definitions for this map chunk. 16 bytes per layer, up to 4 layers. Every texture layer other than the first will have an alpha map to specify blending amounts. The first layer is rendered with full opacity. To know which alphamap is used, there is an offset into the MCAL chunk. That one is relative to MCAL. You can animate these by setting the flags. Only simple linear animations are possible. You can specify the direction in 45° steps and the speed. The textureId is just the array index of the filename array in the MTEX chunk. The effectId links to GroundEffectTexture.dbc. It defines the little detaildoodads as well as the footstep sounds and if footprints are visible.

00h      uint32          textureId;
04h      uint32          flags;
08h      uint32          offsetInMCAL;
0Ch      int32           effectId;    // (actually int16 and padding)

Flags

Flag     Description
---------------------------------------------------------------------------------
0x001    Animation: Rotate 45° clockwise.
0x002    Animation: Rotate 90° clockwise.
0x004    Animation: Rotate 180° clockwise.
0x008    Animation: Make this faster.
0x010    Animation: Faster!!
0x020    Animation: Faster!!!!
0x040    Animation: Animate this texture as told in the other bits.
0x080    This will make the texture way brighter. Used for lava to make it "glow".
0x100    Use alpha map - set for every layer after the first
0x200    Alpha map is compressed

MCRF Subchunk

Identifier MCRF
Length variable

A uint32 list of with MCNK.nDoodadRefs + MCNK.nMapObjRefs indices into the file's MDDF and MODF chunks, saying which MCNK subchunk those particular doodads and objects are drawn within. This MCRF list contains duplicates for map doodads that overlap areas. As both, WMOs and M2s are referenced here, they get doodad indices first, then WMOs. If you have a doodad and a WMO in the ADT as well as the MCNK, you will have a {0,0} in MCRF with nDoodadRefs and MCNK.nMapObjRefs being 1.


MCSH Subchunk - Shadows

Identifier MCSH
Length 512 bytes

Shadow map for static shadows on the terrain. Can be left out with the chunk&1 flag not set. The shadow maps work as follows: the shadows are stored per bit as 0 or 1 (off or on) so we have 8 bytes (which equates to 64 values) X 64 bytes (64 values in this case) which ends up as a square 64x64 shadowmap with either white or black. Note that the shadow values come LSB first.


MCAL Subchunk - Alpha maps

Identifier MCAL
Length 0-3 layers * 2048 bytes

These are alpha maps for additional texture layers beside the base layer. Each layer contains a 64x64 alpha map. There are 2 alpha values per byte, first 4 bits and second 4 bits. Results in 2048 bytes per layer.


MCLQ Subchunk - Liquids

Identifier MCLQ
Length ???

The size of the chunk is in the mapchunk header. The type of liquid is given in the mapchunk flags, also in the header. This information is old and incomplete as well as maybe wrong. The first two floats specify the minimum and maximum liquid height level. After them comes a 9x9 height map for the water with the following format per vertex:

0x00     int16    ?
0x02     int16    ?
0x04     float    height value

The unknown int values might be color or transparency info, or something entirely different... Most frequently they are 0. Followed by 8x8 bytes of flags for every liquid "tile" between the 9x9 vertex grid. The value 0x0F means do not render. (the specific flag for this seems to be 8 but I'm not sure - but it fixes some places where there was extra "water" sticking into the rest of the scenery) Finally, 0x54 bytes of additional data, no idea what it's used for.


MCSE Subchunk - Sound emitters

Identifier MCSE
Length ???

This is not well understood. Struct from WoWDev Wiki:

00h      uint32          soundPointID;
04h      uint32          soundNameID;
08h      float[3]        pos;
0Ch
10h
14h      float           minDistance;
18h      float           maxDistance;
1Ch      float           cutoffDistance;
20h      uint16          startTime;
22h      uint16          endTime;
24h      uint16          groupSilenceMin;
26h      uint16          groupSilenceMax;
28h      uint16          playInstancesMin;
2Ah      uint16          playInstancesMax;
2Ch      uint16          loopCountMin;
2Eh      uint16          loopCountMax;
30h      uint16          interSoundGapMin;
32h      uint16          interSoundGapMax;

Back to Client File Formats

⚠️ **GitHub.com Fallback** ⚠️