- Models are FLVER2: meshes, materials, bones and dummy polys, the named points where weapons attach, hits are measured and effects spawn.
- One enemy FLVER holds every weapon and outfit of its type. Display masks from NpcParam pick which meshes are drawn.
- Animations are Havok spline-compressed clips with root motion. TAE event lists turn them into gameplay: invincibility, cancel windows, attacks, sounds, effects.
- Equipment and items are mostly params. The Estus Flask is an item row that points at a status effect that heals 250 HP.
- Every character carries a Havok ragdoll, whose capsules double as hurtboxes. Some, like Gundyr, carry Havok Cloth that drives bones and rewrites vertices.
1Assembling the Knight


chr/c0000.anibnd → Skeleton.HKX: an hkaSkeleton "Master" of 110 bones, reference pose as hkQsTransformsparts/hd_m_1950 (helm), bd_ (chest), am_ (gauntlets), lg_ (leggings) .partsbnd: a FLVER and a TPF each, skinned to the same bones. The full set covers the body, so no bare body is drawn.wp_a_0201 Longsword, wp_a_2104 Knight Shield. EquipParamWeapon.wepAbsorpPosId → WepAbsorpPosParam gives the body's dummy poly for each hand: Longsword 20 (on R_Weapon), Knight Shield 23 (on L_Weapon)chr/c0000.chrbnd → c0000.flver: no mesh you see, but the dummy polys (901 the right hand, where the Estus Flask appears) and the ragdollA dummy poly's matrix is built XNA-style, CreateWorld(0, forward, upward) × its position × its parent node's bind,
and it follows its attach bone. Each weapon model is first turned 180° about its own Y (DSAnimStudio's WeaponFlipSideways, true for both hands in DS3).
Without that the shield's face points at the arm.
DS3's skeleton, parts and weapon placement, matched bone by bone: every bone an armour piece skins to has exactly the skeleton's bind pose (the importer checks).
2FLVER: the model format
FLVER2 (version 0x20014 on map pieces) holds meshes, materials, nodes (bones) and dummy polys data.
Things that were easy to get wrong:
- Bone indices are FLVER node indices, not per-mesh palettes (FLVER ≥
0x2000E). The importer maps them to skeleton bones by name. Gundyr has 274 bones, so they don't fit in a byte. Clipping them to 255 made his pauldrons follow a bone of the pus's tail..meshv9 stores them asu16. - UVs are integers ÷ 2048 for every layout type, including Float2 (SoulsFormats doesn't divide those, but DS3's shaders do: m40's terrain UVs run to ±32,768). UByte4Norm "UVs" are really layer blend weights.
- Face sets: LOD0 (
flags 0), LOD1 (0x01000000), LOD2 (0x02000000) and motion-blur variants (0x80000000), with a back-face cull flag on 89 % of m40's triangles. - The tangent points along +V.
w × cross(normal, tangent)points along +U (measured on the knight's chest and a map piece). - Rigid meshes (
Dynamic 0) store each vertex in the space of the node itsNormalWnames: the door's two leaves sit on their hinges only so.
Display masks: one model, many enemies
A Cemetery hollow's c1430.flver holds every weapon and outfit its kind can wear. A mesh belongs to mask NN
when its material's name starts #NN#. Unnamed meshes always draw, and NpcParam's ModelDispMask0-31 turn masks on
data. For c1430: mask 0 a blade, 1 and 2 other weapons, 3 a broken straight sword, 4 a
longsword, 5 and 6 shields, 14 a lantern. Gundyr's masks are his halberd (2), the pus (1) and two sets of arms (4, 5). His transformation
swaps them with TAE event 233 (Enemies).

c1430, NpcParam 143000: mask 0, the blade). Its cape is Havok Cloth.
3Textures
Textures come in TPF binders as DDS: BC1 and BC7 for colour, BC4 and BC5 for masks, BC6H for the HDR probe cubemaps. The suffix says the role:

_a albedo: the chest's colour (BC1 sRGB). Metal is dark here.
_n normal: red and green are the tangent-space normal…

_r reflectance: the specular colour F0. DS3 is a specular workflow, so metal shines here.
wp_a_0201
wp_a_2104
c1430_body2
c5110_aMap materials also carry a _s "shininess" texture. Following DSAnimStudio, gloss comes from the normal map's blue and
_s is ignored guess. Engine placeholders like SYSTEX_Dummy* mean "no texture", and
SYSTEX_DummyBurn_* slots are burn and damage overlays. Lightmaps, probes and the sky's layers are on the Renderer page.
4Skeletons and animations
Clips
- One
hkaSplineCompressedAnimationper clip, namedaXXX_YYYYYY. XXX is the motion category: 000 for the common moves, 023 for longsword moves, 048 for the small shield. - Clips spread over several anibnds: idle in
c0000_a00_lo, locomotion in_a00_hi, Longsword attacks in_a2x. - Root motion is separate: an
hkaDefaultAnimatedReferenceFrame, samples of(x, y, z, yaw)at 30 Hz. It's what moves the character (Movement). - Some TAE entries have no clip of their own and borrow another's motion (
LandLow a000_004290 ← a000_004200).
Clips
Our animation reader, a port of the community SoulsAssetPipeline's decoder (and the riskiest part of the importer), decodes every frame at 30 Hz into .anim:
per-bone TRS keys, the root track, and the clip's TAE events. The engine only interpolates neighbours, blends (1-D by speed,
directional by picking one of four clips as DS3 does) and layers an upper-body clip by the behaviour graph's half-blend weights.
GPU skinning, all bone palettes in one storage buffer.
DS3's clips, decoded exactly. In a RenderDoc capture, Gundyr's kneel matches DS3's own bone matrices to 0.1° and 4 mm.
5TAE: what every frame means
Each clip has a list of timed events (.tae, 186,508 of them for the player). They're the game's switchboard:
| Event | Name (DSAnimStudio) | What it does |
|---|---|---|
| 0 | ChrActionFlag | A flag on for the span: 8 invincible, 7 no turning, 11 stick may cancel, 4/26 attack/dodge may cancel, 19 no map collision, 27 no gravity, 3 guarding, 50 no push… |
| 1 | AttackBehavior | The active window of an attack, and which param row it uses (Combat) |
| 2 | Bullet | Fire a projectile from a dummy poly (the crossbow hollow) |
| 16 | Blend | Crossfade time into the clip |
| 65 / 66 | ConsumeCurrentGoods / SetSpEffect | Use the item (the Estus heal) / apply a status effect (Gundyr's phase change) |
| 96 | SpawnOneShotFFX | Play an effect on a dummy poly (Effects) |
| 128-132 | PlaySound_* | Sounds, including footsteps whose name depends on the floor (Sound) |
| 224 / 225 | SetTurnSpeed / SetSPRegenRatePercent | Turn rate for the span / stamina regen (0 % through every Longsword attack) |
| 228 | RagdollReviveTime | An enemy goes limp |
| 231 / 233 | event message / ChangeChrDrawMask | Talk to the event script / show and hide display masks |
| 236 / 237 | RootMotionReduction / SpawnAISound | Scale root motion / make a noise enemies hear |
| 300 | ActivateJumpTableEarly | Interpolate a value: jump table 27 is the gravity multiplier |
| 710 / 792 / 795 | HideEquippedWeapon / FootSfx / DS3Poise | Hide weapons (drinking, pulling the sword) / a special footstep effect / a hyper-armour window |
A small tool of ours, built on the community's SoulsFormats library, lists every event, and the importer copies them unchanged into our .anim files.
The engine knows which event types and arguments it reads. One importer bug is worth recording: TAE files were once matched to clips by
their first two digits, so a234.tae's events landed on the Longsword's a023_* clips.
6Equipment and items are params
The Longsword · EquipParamWeapon 2010000
atkBasePhysics 110, atkBaseStamina 45, weight 3.0, behaviorVariationId 2300 (its attack rows),
wepmotionCategory 23 (its clips, a023_*), attackBaseRepel 66, saWeaponDamage (poise damage),
scaling correctStrength / Agility, wepAbsorpPosId (where it's held).
The Knight Shield · 2104
physGuardCutRate 100 (blocks all physical damage), staminaGuardDef 48 (stability),
guardBaseRepel 50 (flick power), swordArtId 91 → "Parry", motion category 48.
The Knight set · EquipParamProtector
Absorption is stored as the share let through (0.947 …): the four pieces multiply to 72.1 %. The Poise
field is the share of poise damage that counts (product 75.1 %; the menu shows 100 × (1 − rate)).
defenseMaterial picks the armour's rattle on every step.
The class · CharaInitParam 3000
The Knight's stats (Vigor 12 → 454 HP through CalcCorrectGraph 100; Attunement 10 → 93 FP), equipment, and
Item_01 151 "Estus Flask" × 3.
The Estus Flask
goodsUseAnim 10 (a drink), isConsume, maxNum 20, refId1 → SpEffect 2000 "Item - Estus Flask": subHpPoint −250ExecItema000_050110 start (no cancels: committed) → 050111 the gulp, whose TAE 65 at 0.267 s uses the charge → 050112 end; 050114 shaking an empty flask

MENU_Icon_00000, 160 px cells in iconId order): icons 6-9 are the flask from empty to full. Our HUD uses them.7Ragdolls
Every chrbnd's cXXXX.HKX holds an hknpRagdollData data: capsule bodies on the
bones (18 for the player, 90 kg; 19 for the hollow, 101 kg; 46 for Gundyr, 25 of them the pus) with DS3's mass, inertia, damping,
friction and speed caps. They're joined by twist-cone-plane ragdoll joints and limited hinges (feet, hands). Each body's collision filter
ignores its joint's parent. The motors are present but disabled.
Going limp
An enemy's death clip carries TAE 228: the hollow falls backwards, lands at 1.77 s and goes limp from 1.93 s.
None of the player's 186k events have it, and none of Gundyr's. NpcParam.UseRagdoll is not the death switch: it says whether the
living ragdoll blocks the player (big characters only).
Going limp
Jolt bodies with DS3's mass properties and SixDOFConstraints. Havok's round cone becomes a pyramid
stand-in. At event 228 each body takes its pose and the velocity the clip gave it, so the fall carries on.
The bodies drive the bones from then on, two collision steps a tick. Walking through a corpse kicks it ours.
Which way an asymmetric limit turns isn't in the data. Tested against DS3's own clips: reading the limits as the parent relative to the child fits the thighs (99 % / 95 % of frames) and the feet. The arms fit the other reading better, so that's still open.
8Cloth
Gundyr's c5110_c.hkx is Havok Cloth: five cloths (loincloth, apron, waist armour, shoulders, the pus's arm), each a
small program of operators run every frame:
Gravity is tuned per piece (−15 m/s² on the loincloth, −100 on the apron). The local range keeps each shoulder particle within 3 cm of its skinned place. The hollow's lantern and cape run the same way.
DS3's operators and numbers, run by our own solver (Havok's code isn't read). Compared with three RenderDoc captures of the fight, the cloth bones turn out rigid in DS3, and ours, orthonormalised the way that fits best, sit a median 2-4 cm from DS3's over 34 attack poses.
9Our .chr
A .chr ties it together: the .skel, skinned parts (each with its display mask), rigid attachments on bones
(weapons, with their hand slot), clips, dummies (on an attachment, on a bone, or fixed in model space like Gundyr's dummy 100),
hurt capsules (the ragdoll's bodies), and the upper-body weights for half blends. Enemies get one part per display mask and borrow
the clips of the character normalChangeAnimChrId names (Enemies).