243 lines
11 KiB
Markdown
243 lines
11 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 every WDB descriptor and exports each unique ROS once into a normalized-path cache validated by the source SHA-256;
|
|
2. Microsoft `texconv` decodes each cached resource's legacy DDS textures to PNG;
|
|
3. Blender converts the Y-up resources to reusable visual and collision GLBs;
|
|
4. the assembler applies every placement's full translation/quaternion/scale transform relative to the reviewed primary WDB anchor;
|
|
5. glTF Transform instances and optimizes the assembled visual with meshopt;
|
|
6. HealerMan's Recast stage bakes static 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 only as the server-to-local coordinate anchor, reads the entrance from
|
|
`Resource/luascript/03242.lua`, and requires that entrance to project within 2
|
|
meters of the generated navmesh.
|
|
|
|
All valid ROS placement resources are assembled by default. Use `--primary-only`
|
|
only for a deliberate compatibility/debug build. The build writes
|
|
`wdb-placement-manifest.json` with stable placement IDs, source TRS, the complete
|
|
primary-local Three.js matrix, resource-cache keys, bounds, flags, asset status,
|
|
and reviewed dynamic-object metadata. Static placements enter visual, collision,
|
|
and navigation assets. Explicit dynamic placements ship separately so runtime
|
|
state can move, hide, or replace them without baking their collision into the
|
|
static world.
|
|
|
|
Audit the checked-in WDB coverage without regenerating GLBs:
|
|
|
|
```powershell
|
|
npm run runewaker:audit:environment-assembly
|
|
```
|
|
|
|
See
|
|
[RUNEWAKER_ENVIRONMENT_ASSEMBLY_REPORT.md](./RUNEWAKER_ENVIRONMENT_ASSEMBLY_REPORT.md)
|
|
for unsupported types and dynamic candidates that still need source review.
|
|
|
|
Population and creature assets are separate, offline-capable stages:
|
|
|
|
```powershell
|
|
npm run runewaker:forsaken:actors
|
|
npm run runewaker:forsaken:population
|
|
```
|
|
|
|
Source-shaped combat coefficients and boss loot are refreshed independently:
|
|
|
|
```powershell
|
|
npm run runewaker:spells:refresh
|
|
npm run runewaker:loot:refresh
|
|
```
|
|
|
|
See [RUNEWAKER_FORMULA_AND_LOOT.md](./RUNEWAKER_FORMULA_AND_LOOT.md) for the exact formula mapping boundary and [RUNEWAKER_LOOT_IMPORT_REPORT.md](./RUNEWAKER_LOOT_IMPORT_REPORT.md) for every boss's loot status.
|
|
|
|
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:bosses:refresh
|
|
npm run runewaker:build:all -- --phase population --force
|
|
npm run runewaker:forsaken:population
|
|
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, cooldown, source power fields, and source-code
|
|
formula provenance. Live damage uses a labeled HealerMan baseline adapter because
|
|
the required native ATK/MATK, DEF/MDEF, weapon, resistance, critical, level-rate,
|
|
and global-rate inputs are not packaged; it is not represented as source-exact.
|
|
|
|
`runewaker:bosses:refresh` first rebuilds that portable spell snapshot, then
|
|
statically follows each packaged boss's preserved AutoPlot/template callbacks
|
|
and writes modular `rw-<dungeon>-<entity-id>` kits to
|
|
`dungeon-pipeline/boss-mechanics.json`. Each special is an independent record
|
|
with stable ID, trigger, target, effects, and explicit circle, cone, or line
|
|
telegraph geometry. Both population builders copy those IDs into
|
|
`combat.mechanicIds`, so the same runtime loadout boundary is shared by
|
|
Runewaker and WoW encounters and can later support reviewed randomization.
|
|
|
|
Source-backed records identify the RuneWaker Lua and spell evidence they came
|
|
from. If the preserved scripts expose only encounter-progression hooks, the
|
|
importer creates a conservative playable mechanic marked
|
|
`source.kind: "healer-man-source-gap"`; it never labels that fallback as an
|
|
original RuneWaker ability. Edit or append a boss kit in the shared catalog,
|
|
then rerun the population build and gameplay audit to update an encounter.
|
|
|
|
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;
|
|
- requires every boss objective to resolve a modular catalog kit and validates
|
|
its source label, telegraph, timed trigger, and health trigger;
|
|
- 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.
|
|
|
|
The same gameplay audit also regenerates the deterministic
|
|
[RUNEWAKER_ENCOUNTER_IMPLEMENTATION_REPORT.md](./RUNEWAKER_ENCOUNTER_IMPLEMENTATION_REPORT.md)
|
|
and its exhaustive JSON companion. The ledger records all deferred source spawn
|
|
rows and direct mechanics evidence with stable IDs, source files and hashes,
|
|
fidelity, implementation status, blocker, next work, and a clearing test.
|
|
Category totals are overlapping review labels, never a claimed count of unique
|
|
mechanics. Unproven behavior remains `deferred-source-gap` instead of being
|
|
silently inferred from a name or regex match.
|
|
|
|
Run only that ledger and its pipeline tests with:
|
|
|
|
~~~powershell
|
|
npm run runewaker:audit:encounters
|
|
~~~
|
|
|
|
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.
|