- The MSB is the scene graph: model definitions, parts (instances), regions (points and volumes) and events.
- What you see (FLVER map pieces) and what you stand on (Havok collision meshes) are made separately and never derived from each other. A third layer, the navmesh, is for AI.
- Collision parts are rooms. Standing on one decides what's drawn (draw groups), the reverb, the area name and which neighbouring map stays loaded.
- Every collision triangle has a material: stone, wood, water ankle-deep or poison swamp. It drives footsteps, splashes, sliding and wading.
1Three layers and a layout
| Layer | File | Format | Used for | Placed by |
|---|---|---|---|---|
| Layout | map/mapstudio/m40_00_00_00.msb | MSB | Places everything | — |
| Visual | m40_00_00_00_NNNNNN.mapbnd (337 in m40) | BND4 → FLVER2 | Rendering only | Each part's position, rotation, scale |
| Collision, high | h40_00_00_00.hkxbhd/.hkxbdt | BXF4 → Havok 2014 packfiles | Characters | Identity: baked into map space |
| Collision, low | l40_00_00_00.hkxbhd | the same, ~1/7 the triangles | Other queries guess | Identity |
| Navmesh | m40_00_00_00.nvmhktbnd + .nva | hkaiNavMesh | AI pathfinding | — |
The scale of it, for High Wall of Lothric: the high collision has 1,363,951 triangles, the low 184,265, and the visual pieces are thousands of separate models data. Firelink's m40 places 4,057 map pieces of 394 models, with 1.26 M collision triangles.


2The MSB: the level's scene graph
An MSB (v1, 64-bit offsets, UTF-16 names) is a chain of tables data:
| Table | Holds |
|---|---|
MODEL_PARAM_ST | Model definitions: map pieces, objects, collisions, enemies, the player |
EVENT_PARAM_ST | Treasure, generators, object actions (doors, levers), platoons |
POINT_PARAM_ST | Regions: spawn points, sound regions, effect regions, wind, light-probe points and boxes, trigger areas |
PARTS_PARAM_ST | Instances: map pieces, objects, enemies, collisions, connect-collisions, player starts |
Every part shares one header:
name, type, modelIndex, sibPath,
position (3f), rotation (3f, Euler degrees), scale (3f),
mapStudioLayer, drawGroups[8], dispGroups[8], backreadGroups[8],
entityData (EntityID, …, 8 render flags), typeData (per part type), [gparam], [sceneGparam]
The gparam block names the part's light set, fog, light scattering and env map
(Renderer). The entity data ends in eight render flags: casts the sun's shadow, receives it,
drawn by the reflection camera, drawn only by it, and more.
Draw groups: occlusion by where you stand
DS3 doesn't find what's visible with a general visibility system. The level designers wrote it down. Draw, display and back-read groups are 256-bit masks: standing on a collision part makes its display groups active, and a part is drawn when its draw groups share a bit with them. Back-read groups keep things loaded data. In m40, depending on the floor, between 3 M and 15 M of the 24.7 M placed LOD0 triangles are visible.
Groups
17 of m40's 45 collision parts show no groups (special-purpose ones). 7 map pieces have no draw groups, among them the great dead tree right of the starting grave. A game screenshot shows DS3 draws them anyway.
Groups
The same masks, in the .col (show groups per body) and .scene (groups per instance). Standing
on a part with no groups keeps what was shown guess; ungrouped pieces always draw. At the spawn the groups took the frame from 8.2 to 6.3 M triangles.
DS3's own groups from the MSB, with the rule as the map editors (Smithbox) describe it, checked against a game screenshot.
3Collision parts are rooms
A collision part carries gameplay data about a region of floor, not just a mesh reference:
| Field | Meaning |
|---|---|
HitFilterID | Which collision layer: 8 standard, 9 camera only, 11 enemies only, 13 fall-death camera, 15 kill, 22 a hull in front of the walls |
SoundSpaceType | The reverb while you stand here |
ReflectPlaneHeight | The water's reflection plane (−62.254 m on the stream) |
MapNameID | The area name shown on screen |
DisableBonfireEntityID | A bonfire you can't use while here (boss arenas) |
PlayRegionID, LockCamID1/2, MapVisType | Multiplayer region, camera override, darkness |
| draw / disp groups | What becomes visible when you stand on it |
ConnectCollision parts say that standing on this piece keeps a neighbouring map loaded and drawn. Maps stitch together through these, not through one world mesh. Enemies and objects record which collision part they belong to, so whole rooms of characters switch on and off with the floor.
Special layers
h900400 is a near-flat sheet just below Firelink's cliff edges (filter 13): crossing it means you fell to your death, and the camera stops following.
h900000 (15) kills. h900100 (22) is a hull just in front of the visible walls, with material 29 "Without".
Special layers
9 stops only the camera ray, 11 only enemies, 13 and 15 are triggers that kill the player on crossing, and 22 stops characters and the camera but not swords, so swings can clang off the real wall behind it. Before this, corpses lay on the fall-death sheet in mid-air.
4Collision: Havok's compressed meshes
Each collision model is a Havok 2014.1 packfile using the newer hknp physics data:
hkRootLevelContainer
└─ hknpPhysicsSceneData → hknpPhysicsSystemData
├─ materials[] generic hknpMaterial (friction 1.75 …)
└─ bodyCinfos[] one static body, identity transform
└─ fsnpCustomParamCompressedMeshShape ← FromSoft's subclass
├─ hknpCompressedMeshShapeData BVH + quantised vertices
├─ fsnpCustomMeshParameter ← per-triangle game data
└─ triangleIndexToShapeKey[]
- The mesh is split into sections of up to 255 primitives (a triangle, or a quad as two).
- Packed vertices are 32 bits each (11/11/10, against the section's offset and scale). Shared vertices on section borders are 64 bits (21/21/22 over the whole mesh's box). Placeholders of
0xDEADDEADare skipped. - A shape key is
section << 8 | primitive << 1 | quadHalf, left-aligned in 18 bits. It links each triangle to its game data.
Every triangle knows what it's made of
materialNameData = slideClass × 100 + HitMtrlParam row
The material (row)
1 cobblestone, 2 stone (73 % of High Wall), 3 soil, 4 wood, 5 grass, 8 trees, 9 swamp, 11 iron, 13 sand, 16 roof tiles, 17 cloth, 18 fallen leaves, 20 water (puddle), 21 ankle, 22 knee, 27 waist, 23-26 poison swamp, 28 carpet … It picks footsteps, foot effects, wading and status effects.
The slide class (hundreds)
0 normal (slope rules apply), 1 never slide, 2 mostly vertical (unclear), 4 always slide regardless of angle ER.
Collision
Havok's compressed mesh with a BVH per section and FromSoft's per-triangle parameter block.
Collision
.col: triangles with {surface, slide class}. The engine makes them 363 Jolt MeshShape bodies
in 0.5 s (43 MB of Jolt heap), with the material in each triangle's user data, read back from the ground contact's sub-shape. Jolt builds its own BVH.
DS3's triangles, materials and filter layers. Only the physics library differs (Jolt instead of Havok).
How it was fitted to the art: each Havok body is named after its source, an art model's hit mesh (m005590_hh) or a placed instance (m002040_1004),
and a measurement shows three quarters of collision vertices lie within 5 cm of the art but only a third on its vertices. What that suggests about how FromSoftware built it is on
How it was probably made.
5Water in the level
Water is three separate things in DS3's data, none of them a "water volume":
- The surface you wade in: collision part
h900300is nothing but flatwater_anklesheets at each pond's and stream's level (y −62.25, −59.77, −69.02), 0.1-0.45 m above the bed. The bed beneath is ordinary solid collision. The wading materials are the HitMtrlParam rows withHitMtrlType1 = 2. - What you see: the water meshes
m000010/11/12with a water material (Renderer). - What it reflects: the collision parts'
ReflectPlaneHeight, and a few parts markedDrawOnlyReflectCam, bands of unlit cards with 128×64 panoramas of the surroundings that stand in for the terrain in the mirror.

6Objects: doors, candles, corpses
Objects are parts with an objbnd, which can hold a model, its own collision, a skeleton and clips. Three m40 examples:
The posed corpses
The item corpse o000250 is placed 29 times. Each part's AnimIDs[0] names a one-frame clip in its objbnd: slumped against a wall, face down, on its back in a grave. Without the pose they stand upright, half in the ground. Ours: the importer bakes each pose into a mesh stand-in
Candles and torches
Effects come from ModelSfxParam row = model number × 1000 + the part's relative id: 210 lit candles get a flame per wick at dummy poly 200, and 10 wall torches get fire and a point light (Effects).
Gundyr's door
A FLVER with rigid leaves, a 4-bone skeleton, a 10 s opening clip and three keyframed Havok bodies. None of it is in the map's collision. An ObjAct event and event script 14000816 open it once Gundyr dies (flag 14000800).

a000_060170 (TAE flag 19: no map collision), they pass through and end 1.15 m beyond.7Bonfires
A bonfire is surprisingly many things data:
o400100), named by a BonfireWarpParam row: menu text, lit flagRegisterBonfire(lit flag, entity, 5 m, 180°) in m40's event 0; a boss's bonfire waits in common event 20005500 for the defeat flag, then plays effect 1060 and appearsc1000 enemy part (no mesh) sits on it with a talk script (an ESD state machine): "Light bonfire" (button 6100), then "Rest at bonfire" (6101), then the menua000_068000, sit 068010 → loop 068011, stand 068012; warp out 068100, arrive 060260

Lighting, resting (HP, FP, stamina and flasks refilled, enemies back, the death return point) and Gundyr's bonfire appearing, all from the event and talk scripts. The fire's effect (1011) is a guess, and there's no travel, attune or storage menu.
8Enemies in the map
Enemy parts carry a model, an NpcParam row (its body and stats), an NpcThinkParam row (its AI), a
talk id, a platoon, a walk route and an entity id for event scripts. m40 has 100 enemy parts and 43 DummyEnemy parts (cutscene stand-ins).
One map holds two areas: the Cemetery of Ash and, at the same places, the late-game Untended Graves. The hollows exist in both
sets, sometimes at identical positions; event scripts pick the set guess.
Our importer drops the parts whose rows are for Untended Graves (by Paramdex's names or the level-scaling SpEffect 7130/7135), 37 of them, Champion Gundyr among them. The engine places 25 Cemetery of Ash hollows of four kinds and Iudex Gundyr (Enemies).
9Regions
| Region type | In m40 | Engine |
|---|---|---|
| SpawnPoint | New-game start, one per bonfire | Yes: the engine can start at any bonfire |
| EnvironmentMapPoint / EffectBox | 14 probe cubemaps, 31 boxes that blend them per pixel | Yes (Renderer) |
| SFX | 18: ground mist, distant fog banks, the shrine's dust motes, candle lights | Yes (Effects) |
| Sound | 19: boss music, hub music, the Fire Keeper's chant, wind | Yes (Sound) |
| Event area | Gundyr's fight-start box 4002800 in the courtyard's gateway | Copied into code stand-in |
| WindSFX, walk routes | 6 wind, hollow patrols | not done |
10Navmesh
m40_00_00_00.nvmhktbnd holds one hkaiNavMesh per navmesh part (an AABB tree and a cluster graph). The
.nva links navmeshes and portals. Only the AI uses it.
Read but not imported: our enemies walk straight at you, as the hollows on open ground mostly do.
11What our .scene carries
The importer merges the MSB, the area's gparam, its lights (.btl), lightmap atlas table (.btab) and
probe grids (.btpb) into one .scene (v16): meshes and instances (with groups, light set, fog, LOD
distances), spawns, probe cubemaps and boxes, SH probe grids, light sets, fogs, enemies, effects, lightmaps, point lights,
bonfires, sound regions and animated objects. Collision goes to .col, an animated object's bodies to .objcol.
The engine loads the area into a level arena and frees it by resetting the arena.