Skip to content

M2 root — the MD20 body

The model payload — the client's own M2Root. Unlike the chunked formats it is offset-addressed: fields carry no FourCC; their wire positions come from the entity's canonical wire_order, which is also the order they are listed in below. Pre-Legion this is the .m2 file; Legion+ it is the content of the chunked shell's MD21 chunk.

Rather than repeat eleven near-identical class listings, this page documents the generic model: M2Root is the abstract base; the per-version layout below is shown generically as M2Root⟨version⟩. A field whose availability is version-restricted carries an expansion badge naming the range of clients that have it (both ends inclusive); a field with no badge exists in every version. The badges are generated from the C++ sources, so they cannot drift.

Expansions:VanillaTBCWotLKCataMoPWoDLegionBfASLDFTWW

Two wire fields are managed for you and hidden from Python: the leading MD20 magic, and WotLK+'s num_skin_profiles (stamped from the assembly's skins vector on write).

The M2Root base

M2Root

M2Root()

An MD20 model body, abstract over the client version. Construct a concrete version with M2Root.for_version(expansion); the per-version M2Root* classes are subclasses. See https://wowdev.wiki/M2.

for_version staticmethod

for_version(expansion: Expansion) -> M2Root⟨version⟩

Construct the concrete M2Root for a client version — the abstract M2Root is never instantiated directly. The return type narrows per expansion (a typed overload per Expansion member), so for_version(Expansion.Wotlk) returns a M2RootWotlk; a runtime Expansion value yields the AnyM2Root union.

validate

validate() -> ValidationReport

Check the logical integrity contracts this file must satisfy to LOAD in the client, which write() deliberately never enforces. Call it before writing when you want to know the result will load. A file read from a client and left unmodified reports no errors; warnings mark states real client files ship.

Returns:

Type Description
ValidationReport

every violated contract, each with its member path

ensure_valid

ensure_valid() -> None

Validate and raise on the first error instead of returning a report — the assert-style face of validate().

Returns:

Type Description
None

nothing; raises when validate() finds any error

Fields

Header & identity

The layout format version, the model's name and its global flags.

name property writable

name: str

The model's internal name; empty in 9.2+ files.

Sequences & animation

The animation sequences, global loops and the animation-id lookup tables.

sequences property

sequences: list[M2Sequence⟨version⟩]

The animation sequences.

Bones

The bone hierarchy and the key-bone lookup.

bones property

The bones (MAX_BONES nominally 256).

Geometry

The global vertex list and the pre-WotLK embedded LOD views.

vertices property

vertices: list[M2Vertex]

The global vertex list (Z-up model space).

Textures & materials

Texture definitions, UV animations, color/alpha and transparency animations, and the materials.

textures property

textures: list[M2Texture]

The texture definitions.

materials property

materials: list[M2Material]

Materials: render flags + blending modes.

Attachments & events

Attachment points and timed events.

attachments property

attachments: list[M2Attachment⟨version⟩]

Attachment points (weapons, effects, name plates).

events property

events: list[M2Event⟨version⟩]

Timed events (sounds, footsteps, death thud).

Lights & cameras

Model lights and cameras, with their lookups.

lights property

lights: list[M2Light⟨version⟩]

Model lights.

cameras property

cameras: list[M2Camera⟨version⟩]

Cameras (portrait, character info, flyby).

Global flags

GlobalFlags

Bases: IntFlag

M2 global flags: tilt behavior, the texture-combiner-combo gate, physics participation and exporter-era markers.

Attributes:

Name Description
TiltX

Tilt the model over X (flying mounts).

TiltY

Tilt the model over Y.

UseTextureCombinerCombos

The texture_combiner_combos block trails the header (TBC+).

LoadPhysData

Request the .phys file (MoP+).

Unk0x80

Unset stops demon-hunter tattoos glowing (WoD+).

CameraRelated

Camera related (WoD+).

NewParticleRecord

Cata: particle records are the 492-byte layout even below v272.

TextureTransformsUseBoneSequences

Texture transforms animate on the bone's sequence (Legion+).

ChunkedAnimFiles

The .anim files are chunked (Legion+).

TiltX class-attribute instance-attribute

TiltX = 1

TiltY class-attribute instance-attribute

TiltY = 2

UseTextureCombinerCombos class-attribute instance-attribute

UseTextureCombinerCombos = 8

LoadPhysData class-attribute instance-attribute

LoadPhysData = 32

Unk0x80 class-attribute instance-attribute

Unk0x80 = 128

CameraRelated class-attribute instance-attribute

CameraRelated = 256

NewParticleRecord class-attribute instance-attribute

NewParticleRecord = 512

TextureTransformsUseBoneSequences class-attribute instance-attribute

TextureTransformsUseBoneSequences = 2048

ChunkedAnimFiles class-attribute instance-attribute

ChunkedAnimFiles = 8192