WDT
WDT files specify exactly which map tiles are present in a world, if any, and can also reference a "global" WMO. They have a chunked file structure.
MPHD chunk
Contains 8 32-bit integers.
uint32 flags; uint32 something; uint32 unused[6];
These are the only flags checked:
enum mphd_flags { wdt_uses_global_map_obj = 0x0001, // Use global map object definition. adt_has_mccv = 0x0002, // ≥ adds color: ADT.MCNK.MCCV. with this flag every ADT in the map _must_ have MCCV chunk at least with default values, else only base texture layer is rendered on such ADTs. adt_has_big_alpha = 0x0004, // shader = 2. Decides whether to use _env terrain shaders or not: funky and if MCAL has 4096 instead of 2048(?) adt_has_doodadrefs_sorted_by_size_cat = 0x0008, // if enabled, the ADT's MCRF(m2 only)/MCRD chunks need to be sorted by size category adt_has_mclv = 0x0010, // ≥ adds second color: ADT.MCNK.MCLV adt_has_upside_down_ground = 0x0020, // ≥ Flips the ground display upside down to create a ceiling unk_0x0040 = 0x0040, // ≥ ??? -- Only found on Firelands2.wdt (but only since MoP) before Legion adt_has_height_texturing = 0x0080, // ≥ shader = 6. Decides whether to influence alpha maps by _h+MTXP: (without with) // also changes MCAL size to 4096 for uncompressed entries unk_0x0100 = 0x0100, // ≥ implicitly sets 0x8000 unk_0x0200 = 0x0200, unk_0x0400 = 0x0400, unk_0x0800 = 0x0800, unk_0x1000 = 0x1000, unk_0x2000 = 0x2000, unk_0x4000 = 0x4000, unk_0x8000 = 0x8000, // ≥ implicitly set for map ids 0, 1, 571, 870, 1116 (continents). Affects the rendering of _lod.adt mask_vertex_buffer_format = adt_has_mccv | adt_has_mclv, // CMap::LoadWdt mask_render_chunk_something = adt_has_height_texturing | adt_has_big_alpha, // CMapArea::PrepareRenderChunk, CMapChunk::ProcessIffChunks };
See a list here.
The second integer as of WotLK is not ignored but stores something too:
for( int i = 0; i < WDT_MPHD.something/8; i++ ) { WDT_MAIN[i].flags = 0; WDT_MAIN[i].somedata = 0; }
The other bytes seem to be unused from what I can tell. In 6.0.1.18179 I was unable to find any code referencing something other than flags.
vertexBufferFormat = !(flags & adt_has_mccv) ? EGxVertexBufferFormat_PN : flags & adt_has_mclv ? EGxVertexBufferFormat_PNC2 : EGxVertexBufferFormat_PNC ; mcal_size = flags & mask_render_chunk_something ? 4096 : 2048;
As preparation for the removal of namehashes, this chunk underwent a change. The 'unused' array is now used for storing FileDataID references to associated WDT files and the 'something' has been removed. The new structure now looks like the following:
uint32 lgtFileDataID; uint32 occFileDataID; uint32 fogsFileDataID; uint32 mpvFileDataID; uint32 texFileDataID; uint32 wdlFileDataID; uint32 unused;
MAIN chunk
- Map tile table. Needs to contain 64x64 = 4096 entries of sizeof(SMAreaInfo) ( 8 ) bytes each.
struct SMAreaInfo // -> CMapAreaTableEntry { #if version < ? // until they maps are split into adts uint32_t offset; uint32_t size; #endif #if version > ? // beginning them being split into adts uint32_t Flag_HasADT : 1; #endif #if version ≥ uint32_t Flag_AllWater : 1; #endif uint32_t Flag_Loaded : 1; uint32_t asyncId; // only set during runtime. } map_area_info[64*64];
On Cataclysm, 2 on a tile displays "fake water" ingame. If only one "fake water tile" is activated, "fake water" will appear everywhere you don't have an ADT loaded. (seen on 4.3.4.15595)
MAID chunk
- Map filedataid table. Needs to contain 64x64 = 4096 entries of sizeof(MapFileDataIDs) ( 32 ) bytes each.
struct MapFileDataIDs { uint32_t rootADT; // reference to fdid of mapname_xx_yy.adt uint32_t obj0ADT; // reference to fdid of mapname_xx_yy_obj0.adt uint32_t obj1ADT; // reference to fdid of mapname_xx_yy_obj1.adt uint32_t tex0ADT; // reference to fdid of mapname_xx_yy_tex0.adt uint32_t lodADT; // reference to fdid of mapname_xx_yy_lod.adt uint32_t mapTexture; // reference to fdid of mapname_xx_yy.blp uint32_t mapTextureN; // reference to fdid of mapname_xx_yy_n.blp uint32_t minimapTexture; // reference to fdid of mapxx_yy.blp } MapFileDataIDs[64*64];
MWMO, MODF chunks
For worlds with terrain, parsing ends here. If it has none, there is one MWMO and one MODF chunk here. The MODF chunk is limited to one entry. See the ADT format description for details.
MWMO chunk
- A filename for one WMO (world map object) that appears in this map. A zero-terminated string. 0x100 is the maximum size for this chunk due to being copied into a stack allocated array (at least in MOP)! (including \0).
MODF chunk
- Placement information for the global WMO. 64 bytes. Only one instance is possible.
Offset Type Description 0x00 uint32 ID -- unused, always uses MWMO's content instead 0x04 uint32 unique identifier for this instance -- unused, generates uid dynamically 0x08 3 floats Position (X,Y,Z) 0x14 3 floats Orientation (A,B,C) 0x20 3 floats Upper Extents 0x2C 3 floats Lower Extents 0x38 uint16 Flags 0x3A uint16 Doodad set index 0x3C uint16 Name set? 0x3E uint16 Padding
struct SMMapObjDef { uint nameId; uint uniqueId; C3Vectorⁱ pos; C3Vectorⁱ rot; CAaBoxⁱ extents; uint16 flags; uint16 doodadSet; uint16 nameSet; uint16 pad; };
- How to compute a matrix to map WMO to world coordinates
Refer to MODF(ADT)
_occ, _lgt
WoD added _occ.wdt (occlusion) and _lgt.wdt (lights) for each .wdt. They are only used for adt-maps, not WMO-only ones.
occ
MAOI and MAOH might be zero size. (WMO-only WDTs)
MVER
struct { uint32_t version; // 18, just as all others } mver;
MAOI
struct { uint16_t tile_x; // MAOH entries are per ADT tile uint16_t tile_y; uint32_t offset; // in MAOH uint32_t size; // always (17*17+16*16)*2 } maoi[];
MAOH
unknown. blocks referenced from MAOI. Possibly shorts. either really huge or small values. possibly a 2d map for something.
short interleaved_map[17*17+16*16];
lgt
Might only have MVER for WMO-only WDTs. Level designers are able to freely place lights, without placing models containing lights now. This is used below lamp posts and alike. As of Legion, there is support for point and spot lights.
MVER
struct { uint32_t version; // ≤ (7.0.1.20740): 18 just as all others, ≥ (7.0.1.20914): 20 } mver;
MPLT
struct { uint32 id; uint16 tile_x; uint16 tile_y; CArgbⁱ color; C3Vectorⁱ position; float unknown[3]; // intensity, and stuff. flicker? } map_point_lights[];
- starting some Legion build, these are no longer read for backwards compatibility but MPL2 is required.
MPL2 (Legion+)
- appears to be either, not both MPLT and MPL2, or they need to have the same size.
struct { uint32 id; CArgbⁱ color; C3Vectorⁱ position; float unknown[0x6]; //First 3 match MPLT's unknown uint16 tile_x; uint16 tile_y; char unknown_2[0x4]; } map_point_lights[];
- the only file I know having this (e3148cc88c7f2fcaebe99c53e5e5079e) has a size of 0x40 for MPL2, which does not match to what the client parses (0x34) --Schlumpf (talk) 03:18, 22 November 2015 (UTC)
- unknown_2, as an int16 array, has seen values of [0,-1] and [-1,-1] --Barncastle
MSLT (Legion+)
struct { char _[0x34]; } map_spot_lights[];
MTEX (Legion+)
uint32_t textureFileDataIds[];
MLTA
struct { float _1; float _2; uint32_t _3; //Always 1 or 2 ?? } map_lta[];
_fogs
Legion added _fogs.wdt for a subset of .wdts. They seem to be only present for terrain maps, not WMO maps. As of (7.2.5.24076) (when they were added) and (7.3.2.25383) (when this paragraph was added), they are all empty and not even read by the client. It is likely that they are merged into the branch by accident and are a feature. The first files with content are zandalar and kultiras with (8.0.1.25902).
MVER
uint32_t version; // ≥ (7.2.5.24076): 1
VFOG
struct { C3Vector _unk00; // 0…1 float _unk0c[3]; char _unk18[4]; C3Vector _unk1c; // position? char _unk28[0x14]; float _unk3C[3]; char _unk48[0x14]; // fog level relatedᵘ, as uint32_t mostly 10000, 20000, 50000, 60000, 1 uint32_t modelFileDataId; // the client only supports models with one M2Batch char _unk60[4]; // mostly 0 filled uint32_t _unk64; // globally unique in the files } volumetric_fogs[];
_mpv
As of ≥ (8.0.1.26287) references to _mpv.wdt (particulate volume) have been seen in the client. While these files haven't been shipped (26310), the CMap::Load function does attempt to read them when present. These files were first shipped in (8.0.1.26433).
While the file is chunked, it does require the exact order of #PVPD, #PVMI, #PVBD: #PVMI might override #PVPD, and as soon as #PVBD is read, it is finalised.
MVER
enum mpv_version : uint32_t { mpv_version_0, // ignores the rest of the file (actually, all < 1, so probably just ≥1 as requirement)ᵘ mpv_version_1, // (8.0.1.26433) mpv_version_2, // (8.0.1.26476) … (8.0.1.26557) mpv_version_3, // (8.0.1.26567) … (8.0.1.27404) mpv_version_4, // ≥ (8.0.1.27481) }; mpv_version version;
PVPD
struct { C2Vectorⁱ _unk00; // [-1.f, 1.f]ᵘ float _unk08; // only seen: -0.fᵘ float _unk0c; } particle_volume_pd[];
PVMI
If #PVPD was already read, it is nulled out. Note that the inverse is not true, i.e. if #PVMI comes first, #PVPD may be non-null. This is not a bug but actual files have #PVMI first, followed by #PVPD and #PVBD.ᵘ
struct { #if version == mpv_version_1 char _unk00[0xF5C]; // appears to be a huge blob, 0xF5C bytes, including five (binary) WWFParticulateGroupsᵘ // this might not actually be pure binary WWFParticulateGroups (or that size changed without MVER change), since the block is 0xF84 in (8.0.1.26433)ᵘ #else if version == mpv_version_2 char _unk00[0xFE8]; #else if version >= mpv_version_3 char _unk00[0x10D8]; #endif } particle_volume_mi[];
PVBD
struct { uint32_t num_unk1C; CAaBoxⁱ _unk04; // bounds/extentsᵘ uint32_t _unk1C[8]; // indices into #PVPDᵘ uint32_t _unk3C; // boolean: This entry is complete. If false, it is joined with the next entry. It will have the same bounds.ᵘ } particle_volume_bd[];