Files
healer-man/docs/CHARACTER_EQUIPMENT_APPEARANCE.md
2026-10-04 22:51:21 -04:00

78 lines
3.9 KiB
Markdown

# Character equipment appearance
The shared `src/avatar/CharacterModel.tsx` renders the player, party NPCs,
roster, and creator. Equipment appearance is presentation-only; it never
changes item ownership, stats, or progression.
## WoW and Ascension
`src/avatar/equipmentAppearance.ts` keeps exact appearances for the packaged
Wailing Caverns drops. Unmapped armor, including synthetic heirlooms, gets a
representative native WoW appearance by equipment slot and armor type. Empty
preview slots receive starter clothing: chest, legs, boots, gloves, shoulders,
and cloak. Cloth uses a robe, leather uses leather armor, and heavy armor uses
the packaged mail breastplate. These are visual defaults, not exact item skins
for every entry in the loot catalog.
Real equipped appearances override the starter appearance in their slot.
The body atlas layers remain ordered so robes override the trouser geoset.
Appearance cache keys include class, item slot, and armor type.
`src/ui/CharacterPreview3D.tsx` passes the saved player's equipped inventory
items into the same renderer used in the dungeon.
Loaded preview attachments request a bounds refit when their optional models
finish loading, so larger native staffs stay inside the roster preview.
## RoM
The native shared-skeleton character GLBs contain original RoM starter
garments. `scripts/runewaker-pipeline/recipes/player-starter-appearance.tsv`
selects `cloth010-001` for torso, hands, legs, and feet instead of the bare
`body000-001` defaults. This common starter outfit is currently shared across
classes; individual RoM armor drops do not yet replace those modular parts.
Rebuild all five supported race/gender rigs with
`npm run runewaker:players:avatars`.
`src/avatar/runewakerEquipment.ts` resolves original RoM starter sword, mace,
shield, staff, bow, and dagger props from
`public/assets/equipment/runewaker-v1/`. Equipped weapon types select the
appropriate representative source prop. Exact skins for arbitrary equipped
RoM weapons are not implemented. WoW texture atlases and WoW item models must
not be applied to the native RoM rigs.
Rebuild the props with:
```text
node scripts/runewaker-pipeline/build-population.mjs --recipe scripts/runewaker-pipeline/recipes/runewaker-starter-weapons.json --actors-only
```
The generated import manifest records the source ROS path, source SHA-256,
output SHA-256, bounds, and triangle count for each prop. Converted source
props retain the RoM socket frame; the WoW-to-RoM procedural fallback rotation
must not be applied to them on native rigs. The bow retains its native facing
on RoM rigs. On the basic human fallback, its source Y axis is aligned to the
bow socket before applying the inverse socket adaptation, keeping the string
toward the archer. Other props retain their source orientation.
Weapon selection follows RoM class identity even when the optional character
pack is absent. The basic human body retains its WoW clothing and shoulders,
but its hands receive original RoM props with the inverse socket adaptation.
The optional character pack is not required to see authentic RoM weapons.
## Packaging and validation
All equipment files belong to the bundled `core:equipment` content pack.
RoM character rigs belong to the optional `characters:runewaker-v1` pack.
Refresh local content with `npm run content:publish` after regenerating assets.
Existing installations must refresh their content packs to receive changed rigs.
Each optional item retains its own Suspense/error boundary and procedural hand
fallback. Missing item assets cannot hide the body or other equipment.
- `npm test -- --run src/avatar`
- `npm run build`
- `node scripts/playtest-party-equipment.cjs` after building and refreshing content
- `node scripts/playtest-party-equipment.cjs --rom-only --basic-only` checks the missing-character-pack path
- Review roster and dungeon screenshots in `playtest-artifacts/party-equipment/`
- Record visual findings in `PLAYTEST_NOTES.md`
- `npm run release:check`