`UnitCreatureType` read only a creature's template type, and fell back to "Humanoid" for a player. The form stage was not built. So a druid in cat, bear, travel or aquatic form and a shaman in Ghost Wolf all answered "Humanoid", where 1.12.1 answers "Beast".
`UnitCreatureType 0x51a280` names the type the resolver `0x605570` returns, and 0 names nil (`0x51a2c3`). The resolver tries three stages in order:
1. **Form:** the form byte (`UNIT_FIELD_BYTES_1` byte 2) indexes `SpellShapeshiftForm.dbc` column 12, which applies only above 0 (`0x60559a`).
2. **Template:** else the cached creature record (`0x6055a8`).
3. **Race:** else the race's `ChrRaces.dbc` type (`0x6055ca`).
A token naming no unit answers nil (`0x51a2b8`). The unit tooltip's level line takes the type only for a non-player (`0x52a4a6`).
Changes:
- `ui_unit::snapshot` sets `creature_type_name` for every unit through the shared `CreatureTypeSources::of`: players, creatures, pets and group tokens alike. `enrich_unit` no longer sets it.
- `UnitCreatureType` reads that field, with no fallback.
- The feeds at Bevy's parameter limit carry the sources in a `SnapshotTables` param.
- A player's tooltip level line is unchanged, since it reads race and class.
Behaviour that now matches the reference beyond the issue:
- a held pet, `partypetN` and `raidpetN` answer their template's type rather than nil;
- a party member in a form reads the form's type;
- a roster member with no object, and the pre-arrival player seat, answer nil.
Tests:
- `the_shipped_forms_name_a_beast_or_fall_through_to_the_race` reads the real `SpellShapeshiftForm.dbc`.
- `unit_creature_type_names_the_form_before_the_race_and_a_creature_its_template` runs `feed_units` and asks the Lua binding.
- Mouseover, party, raid and pet feeders each have a test.
- `a_players_level_line_ignores_the_snapshots_creature_type`.
Fixes#641🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>