Files
2026-08-14 15:56:39 -04:00

178 lines
7.7 KiB
Markdown

# RuneWaker dungeon pipeline
This pipeline converts preserved RuneWaker `.ros` dungeon assets into the same
browser-facing GLB roles used by HealerMan's WoW dungeon pipeline:
1. the preserved Rune engine reads the WDB entity table and exports the primary ROS as an OBJ/MTL bridge;
2. Microsoft `texconv` decodes the legacy DDS textures to PNG;
3. Blender converts the Y-up source to textured visual and chunked collision GLBs;
4. glTF Transform optimizes the visual asset with meshopt;
5. HealerMan's Recast stage bakes navigation and the Khronos validator gates every GLB.
Run the Forsaken Abbey pilot from the HealerMan root:
```powershell
npm run runewaker:forsaken
```
Optional environment variables:
- `RUNEWAKER_ROOT`: preserved backup root containing `Resource` and `Tools`
- `BLENDER_BIN`: Blender 5 portable executable
- `TEXCONV_BIN`: Microsoft DirectXTex `texconv.exe`
- `MSVC_V142_ROOT`: portable MSVC v142 root used by the native build script
The shipping environment is written to
`src/assets/game/dungeons/forsaken-abbey` and registered as a playable
dungeon. The build reads all 184 WDB entity descriptors,
uses the primary ROS placement as the server-to-local anchor, reads the entrance
from `Resource/luascript/03242.lua`, and requires that entrance to project within
2 meters of the generated navmesh.
Population and creature assets are separate, offline-capable stages:
```powershell
npm run runewaker:forsaken:actors
npm run runewaker:forsaken:population
```
Only an explicit forensic refresh connects to the isolated development SQL
instance:
```powershell
npm run runewaker:forsaken:population:refresh
```
The normal population build consumes the checked-in 251-row Zone 102 snapshot
and never connects to SQL Server. It packages 150 combat spawns, eight boss
objectives, and nine authentic native-animation creature GLBs. The remaining 101 rows are
retained in the source report for later quest-object, door, transport, script,
and treasure passes.
## All configured instances
The generalized batch now packages and registers all 30 configured RuneWaker
instances (Forsaken Abbey plus 29 generated definitions). The normal workflow is
fully local and does not use SQL:
```powershell
npm run runewaker:prepare:all
npm run runewaker:build:all
npm run runewaker:register:all
```
`runewaker:prepare:all` consumes the portable forensic JSON already under
`runewaker-export-work`. `runewaker:build:all` is resumable and writes a result
after every dungeon. `runewaker:register:all` exposes only instances whose full
validation report is green.
Creature animation policy is audited separately:
npm run runewaker:audit:animations
The audit opens every referenced creature GLB, checks its glTF header and
animation table, resolves every spawn and entity in all 30 runtime definitions,
and exercises the available native or procedural state paths. Pasper's Shrine
is the compact direct-mesh reference package. The full batch now uses original
GR2 skeletons and sampled RAS clips for validated direct actors, while runtime
paperdoll containers are assembled into exact image-specific actors from a
portable appearance snapshot. Genuinely unsupported pose-only or triangle-free
displays remain explicit exceptions rather than silently claiming native motion.
See [ORIGINAL_ANIMATION_IMPORT.md](./ORIGINAL_ANIMATION_IMPORT.md) for the
reproducible conversion and rollout process, and
[RUNEWAKER_ANIMATION_AUDIT.md](./RUNEWAKER_ANIMATION_AUDIT.md) for the package
historical baseline and current all-dungeon status.
Paperdoll appearance recovery is an explicit forensic refresh, separate from
normal builds:
~~~powershell
npm run runewaker:paperdolls:refresh
npm run runewaker:build:all -- --phase actors,population --force
~~~
The refresh restores `ObjectEdit.bak` under a temporary read-only database,
exports only combat-template image rows, writes the checked-in portable
`runewaker-paperdoll-appearances.json`, and drops the temporary database in
`finally`. Normal actor builds, tests, production builds, and browser play use
that JSON and packaged GLBs with SQL stopped. Appearance provenance preserves
component names and color layers; any unresolved composite-mask color bake is
reported explicitly in the actor manifest.
## Portable populations, source spells, and objective routes
NPC spell evidence is exported from the preserved read-only RuneWaker client
catalogs into a checked-in portable snapshot:
~~~powershell
npm run runewaker:spells:refresh
npm run runewaker:build:all -- --phase population --force
npm run runewaker:audit:gameplay
~~~
The existing all-instances runner starts a separate Node population-builder
process for each of the 29 generalized packages. Forsaken Abbey keeps its
special pilot builder. Both builders emit ordinary TypeScript definitions and
JSON reports; the browser never opens the original client catalogs or SQL
backups.
Spell conversion is deliberately fail-closed. Only a MagicObject component
positively classified as direct HP damage becomes an executable HealerMan
attack. Buffs, healing, summons, plot hooks, and unknown effects remain
evidence-only. The portable mapping preserves source spell identity, name,
damage family, school, range, and cooldown. The current 0.85 damage coefficient
is HealerMan-authored and is not represented as the original RuneWaker formula.
The gameplay audit also:
- verifies every executable attack.spellId against both its source template
assignment and the portable spell catalog;
- rejects evidence-only spell IDs if they enter runtime combat data;
- reuses the live party-navigation graph to inspect boss approach points
projected to the retained surface within 6m;
- validates native animation families, with Rune Device's missing locomotion
documented as a stationary-device exception while its attack/activation
clips remain mandatory.
The generated
[RUNEWAKER_GAMEPLAY_CONTENT_REPORT.md](./RUNEWAKER_GAMEPLAY_CONTENT_REPORT.md)
is the current cross-dungeon content baseline. The generalized population
builder currently falls back to straight-line distance from the entrance when
ordering bosses. That fallback is labeled `healerMan-distance-derived`: an
unreachable heuristic leg is navigation/order review evidence, not a claimed
source-authored structural failure. A future explicit recipe order must include
preserved local source evidence before it can become authoritative. The builder
accepts that reviewed override only as `bossObjectiveOrder: { kind:
"source-authored", spawnIds: [...], evidence: [...] }`; it rejects missing
evidence, duplicates, or an order that does not account for every boss spawn.
Run the component-level navigation review separately:
~~~powershell
npm run runewaker:audit:navigation
~~~
It writes
[RUNEWAKER_NAVIGATION_GAP_REPORT.md](./RUNEWAKER_NAVIGATION_GAP_REPORT.md),
measures every unreachable heuristic leg against all raw Recast components,
and records reviewed source evidence for support-pad environments, authored
room placements, doors, drops, and teleports. It never writes navigation links.
No automatic links are currently approved: the observed gaps either depend on
mechanics/order evidence or on modular environment assembly, so bridging them
would bypass gates or cross missing geometry.
The forensic source refresh is intentionally separate:
```powershell
npm run runewaker:refresh:all
```
It requires the isolated `HEALERMAN_RW` SQL service to be running, restores both
backups read-only under temporary names, exports all configured zones, drops the
temporary databases in `finally`, and regenerates the portable snapshots. Stop
the SQL service again before running the normal build or game.
See [INSTANCE_IMPORT_GUIDE.md](./INSTANCE_IMPORT_GUIDE.md) for provenance,
coordinate rules, special WDB cases, mechanics review, validation, and the
step-by-step process for adding future instances.