546 lines
29 KiB
Markdown
546 lines
29 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
|
|
|
|
### Environment texture and lighting quality
|
|
|
|
The visual optimizer uses `lib/environment-optimization.mjs`. RoM architecture
|
|
keeps its source triangles and atlas UV interpolation: `--simplify false` is
|
|
required because generic mesh simplification collapses UVs on large planar
|
|
walls and floors. Meshopt compression and instancing remain enabled. Native
|
|
water and source-detail variant carriers disable joining, pruning and attribute
|
|
pruning so auxiliary maps and their mappings survive optimization.
|
|
`--texture-compress false` also prevents the optimizer's default
|
|
2048-pixel image resize; the separate KTX2 pass encodes the source dimensions.
|
|
|
|
`src/game/runewakerDungeonEnvironment.ts` supplies reviewed fallback palettes
|
|
for all 30 registered base dungeons. The registry applies this adapter before
|
|
creating Bite-Sized derivatives. A separate WDB zone exporter and
|
|
`DungeonLighting.tsx` now own recovered ambient/directional lighting and fog;
|
|
this is not embedded GLB light-component preservation. Native Standard shadows
|
|
follow player footing and High follows the camera. Fallback profile Standard
|
|
targets the entrance; WoW retains its existing lighting path.
|
|
|
|
Native entrance directions pass through the same primary-placement frame as
|
|
source points. `transformSourceHeadingToPrimaryThree` applies inverse primary
|
|
rotation and component scale, bridges source handedness, and normalizes XZ
|
|
before deriving runtime yaw. Preserve the Lua direction in source provenance;
|
|
using it directly as local yaw faces the wrong way in rotated WDB assemblies.
|
|
|
|
The selective texture compressor applies UASTC to explicitly reviewed base-color
|
|
basenames. Its initial eight-name policy covered 16 images in nine packages;
|
|
the current list also covers Barren's exact native atlas/floor crops and HOTO's
|
|
four stone/cliff maps and Origin's exact `elves_vine` cutout. Read
|
|
`compress-environment-textures.mjs` for the current
|
|
list. Those targets use UASTC level 2 with Zstandard 18 and RDO disabled,
|
|
retaining source dimensions and the complete mip chain; other images retain the
|
|
existing ETC1S path. Pass explicit GLBs or directories so the compressor never
|
|
scans the workspace implicitly:
|
|
|
|
```powershell
|
|
node scripts/runewaker-pipeline/compress-environment-textures.mjs <rom-glb-or-directory> --report <report.json>
|
|
```
|
|
|
|
Run the source-resolution, sampler and floor/wall UV diagnostics with:
|
|
|
|
```powershell
|
|
npm run runewaker:audit:environment-quality
|
|
node --test scripts/runewaker-pipeline/environment-optimization.test.mjs scripts/runewaker-pipeline/audit-environment-quality.test.mjs scripts/runewaker-pipeline/rom-visual-uv-adaptations.test.mjs
|
|
```
|
|
|
|
The generated `RUNEWAKER_ENVIRONMENT_QUALITY_REPORT.md` covers every registered
|
|
RoM visual. Density and UV-rank measurements identify candidates for review,
|
|
rather than certifying every polygon. The initial 30-dungeon hotspot dispositions
|
|
are recorded in
|
|
`artifacts/playtest/rom-environment-quality/rom-texture-pipeline-triage/uv-hotspot-triage.md`.
|
|
The later production review supersedes Barren's whole-atlas repeat with exact
|
|
floor islands and native wall detail. HOTO retains cliff gradients while adding
|
|
source-rock detail. Durable recipe opt-ins are implemented in
|
|
`lib/rom-surface-quality-policies.mjs`; current evidence is under
|
|
`artifacts/playtest/rom-deep-review/uv-stretch-review/` and
|
|
`docs/ROM_ENVIRONMENT_REVIEW_2026-10-06.md`.
|
|
|
|
Exact native atlas crops carry `texture.extras.romSourcePixelCrop`. The quality
|
|
audit verifies the native PNG hash and DDS dimensions, crop rectangle, canonical
|
|
PNG's exact RGBA bytes, shipped island dimensions and full mip chain through
|
|
`lib/source-pixel-crop-proof.mjs`. Verified island dimensions are reported
|
|
separately from the full native atlas; this does not exempt resized images.
|
|
`verify-native-uv-source-layout.mjs` independently compares hierarchy/TRS and
|
|
expanded ordered triangle attributes while allowing presentation UV1 and
|
|
primitive/material regrouping. Original source images must remain byte-identical.
|
|
|
|
`src/scene/runewakerSurfaceDetailMaterial.ts` supports source-pinned static rock
|
|
detail carried by named `KHR_materials_variants` materials. `useGameGLTF.ts`
|
|
registers it and `productionDungeonMaterials.ts` preserves it through cloning.
|
|
Triplanar sampling uses real world metres and inverse-transpose normals,
|
|
including instance transforms. Mean-normalized source textures modulate diffuse
|
|
RGB within bounded strength. Reviewed metadata can reduce wall base contrast
|
|
around the source mean and blend rotated tile samples to soften repetitions.
|
|
`floorBaseStrength` permits a verified full stone/moss tile to supply floor RGB
|
|
directly at the chosen world scale; it must not repeat a mixed cliff atlas.
|
|
Original UV0, base-map alpha and lighting semantics remain intact. Texture
|
|
uniforms participate in existing filtering/disposal. Carrier
|
|
variants require the reviewed optimizer's join/prune protections. These detail
|
|
scales are browser presentation adaptations, not reconstructed native UVs.
|
|
HOTO v2 migrates only complete source-pinned v1 metadata, verified carriers and
|
|
all 72 variant mappings; reapplication is idempotent. Its reviewed continuation
|
|
uses `promote-hoto-surface-v2.mjs`: the default mode verifies immutable candidates,
|
|
source/layout/codec proofs and screenshot hashes without writing. `--apply`
|
|
creates a new exclusive backup before replacing only HOTO's three visual GLBs
|
|
and current metadata. All non-JSON chunks are byte-identical to v1; historical
|
|
codec reports retain their original GLB hashes.
|
|
Sand Vortex uses nine native WDB terrain
|
|
chunks selected from authoritative encounter bounds, with the original per-chunk
|
|
indices, visibility, vertex normals, two DXT1 splat maps, five source tile DDS
|
|
layers, and their native tile scales. Runtime material blending normalizes the
|
|
source RGB weights and samples the full-resolution layer textures at their
|
|
source scales; this replaces the old flat, untextured arena fallback.
|
|
|
|
Sand Vortex opts into source-scaled side projection on steep terrain through
|
|
`source.nativeTerrain.cliffProjection`. The runtime retains native XZ sampling
|
|
on level ground and blends height-aware side sampling only on slopes. It uses
|
|
the original smooth normals, layer scales, and splat weights; topology and
|
|
flat-floor UVs remain unchanged. The asset-root inverse transform keeps this
|
|
projection stable through package placement, quantization, and instancing.
|
|
|
|
The Origin now recovers all 256 WDB terrain chunks selected by the full source
|
|
manifest. Four source DDS layers, their per-layer tile scales, and both DXT1
|
|
splat maps feed the same linear runtime blend. The previous `[2,2]` chunk
|
|
review was only an early ground probe and is not the current coverage claim.
|
|
|
|
The independent native-water builder decodes all 126 selected version-3 WDB
|
|
water layers with exact GUID descriptor joins. It recreates source visibility
|
|
masks, vertex color and alpha, and packages the 30-frame animated normal
|
|
sequence as exact top-mip PNG carriers. The runtime applies those frames as
|
|
animated source normal maps and samples transformed source-world coordinates;
|
|
the glTF `TEXCOORD_0` on water layers is a source-world XZ validator carrier
|
|
only. The original DDS files and all mip hashes remain in the source audit
|
|
cache. Source-enabled non-DIRECT water now uses a bounded browser adaptation of
|
|
AquaFX camera reflection and pre-water refraction, with the native first-vertex
|
|
split planes, bump scale and Fresnel coefficients. The serialized
|
|
`waterDesc:full:enable` Boolean selects this branch even for the Origin's raw
|
|
effect value 4; its enum name is not inferred. Up to four active 512-pixel target
|
|
pairs share a ten-capture-per-second budget per tagged asset root. Old invisible
|
|
planes release their slots; additional active planes and below-plane views use
|
|
the lit animated fallback. Source reflect-class filtering and the original
|
|
water SH shader remain unsupported. Water remains visual-only and is not added
|
|
to source collision.
|
|
|
|
`export-native-lighting.mjs` decodes all 30 dungeons' exact WDB environment
|
|
settings and zone triggers into `src/game/generated/runewakerNativeLighting.generated.ts`.
|
|
`src/game/runewakerNativeLighting.ts` resolves source zones from runtime player
|
|
coordinates; `src/scene/DungeonLighting.tsx` applies their linear ambient and
|
|
three directional colors, directions, and camera-scaled fog. Time/weather
|
|
groups default deterministically to 0/0. Missing zones retain the dungeon's
|
|
reviewed presentation profile (including Grafu's entrance). The browser supplies
|
|
Rune's unoccluded SH constant-band energy as ambient fill (4/17) and uses the
|
|
remaining 13/17 in Three.js directional lighting. Angular diffuse response and
|
|
PBR specular remain browser adaptations, not the complete original SH/specular
|
|
shader. Standard shadows follow the player's footing and High shadows follow
|
|
the camera; WoW retains its existing presentation path.
|
|
|
|
Build all water-bearing chunks, or restrict water to the exact coordinates in
|
|
an existing ground manifest whose WDB hash matches:
|
|
|
|
```powershell
|
|
node scripts/runewaker-pipeline/build-native-water.mjs
|
|
node scripts/runewaker-pipeline/build-native-water.mjs --ground-manifest runewaker-export-work/the-origin/native-terrain-source/terrain-native-source.json
|
|
node scripts/runewaker-pipeline/build-native-water.mjs --ground-manifest runewaker-export-work/the-origin/native-terrain-source/terrain-native-source.json --audit-cache-root runewaker-export-work/the-origin
|
|
```
|
|
|
|
The builder writes `native-water-visual.glb`, `conversion-report.json`, and a
|
|
per-descriptor archive of the source DDS frames and lossless PNG carriers under
|
|
`runewaker-export-work/<slug>/native-water-source` by default. Use `--recipe`,
|
|
`--source-root`, and `--wdb-report` to select its local recipe and source
|
|
inputs; `--output-root` must remain inside the active project workspace.
|
|
The optional `--audit-cache-root` writes exact, hash-verified aliases named from
|
|
each GLB texture/variant into `raw/textures` and `prepared/textures` under that
|
|
root, allowing the quality audit to resolve water DDS and PNG source pixels.
|
|
|
|
Recipes may opt into pipeline integration with
|
|
`source.nativeWater.kind: "runewaker-wdb-water-layer"`. This mode requires
|
|
`source.nativeTerrain` and a full WDB assembly. The environment builder always
|
|
passes the selected native-terrain manifest to the water builder, so water
|
|
chunks follow the same reviewed source-ground selection. It merges the result
|
|
as a visual-only WDB record; no water geometry is added to source collision or
|
|
navigation.
|
|
|
|
Three reviewed primary-only recipes use `source.primaryNativeCollision` to
|
|
replace imported collision with an options-aware query of the exact primary ROS
|
|
plus source-coordinate support geometry. The reusable candidate producer hashes
|
|
the current recipe, import metadata, ROS/WDB sources, placement reports, and
|
|
native extractor; it invokes the native collision query in
|
|
`respect-options` mode or accepts a query cache only when its provenance
|
|
sidecar matches those inputs. It regenerates support boxes from the recipe and
|
|
resolved primary WDB transform rather than reading a previously transformed
|
|
GLB. The proof file names the full collision candidate (which the build splits
|
|
to the configured per-GLB triangle limit), the native-core/overlapping-support
|
|
Recast input, and the baked navigation candidate and report.
|
|
|
|
Run the candidate producer directly for one of its configured recipes with:
|
|
|
|
```powershell
|
|
node scripts/runewaker-pipeline/build-native-core-support-candidate.mjs aeternal-circle --respect-options
|
|
```
|
|
|
|
Use `--stage-only` to write only the source-verified collision inputs and proof
|
|
before Recast, or `--output-root=runewaker-export-work/<slug>/<new-directory>`
|
|
to select a fresh artifact directory under that dungeon's work folder. A second
|
|
run consumes staged inputs only after rechecking their source and GLB hashes.
|
|
The Aeternal entry-support omission is independently ray-checked against the
|
|
current option-enabled native collision query each run. Remote support pads
|
|
remain separate navigation components; when present, the report declares
|
|
`navigationComponentPolicy: "all-components"` without inventing links.
|
|
|
|
`recipes/the-origin.json` keeps the Lua-authored spawn `[828,263,963]` and
|
|
direction `343` as source provenance. The reviewed runtime entrance instead
|
|
uses source path graph 1026 node 854, projected to the recovered ground and
|
|
navigation. Current native collision selection honors serialized collision
|
|
options and Trekker's water/foliage exclusion mask: 865,100 eligible triangles
|
|
across 20 collision chunks. The current Recast/Detour artifact contains
|
|
103,582 triangles and 24,612 polygons. In that graph, node 854 reaches Life Leecher;
|
|
Life Leecher and node 854 both terminate in partial routes to Holy Tree
|
|
Falynum. That early collision-graph review covered only two short entrance walking
|
|
legs (2.85 m, with all three samples grounded). A later final v5 material review
|
|
walked 19/19 legs along the connected Life route (48.56 m, all 42 samples grounded).
|
|
Neither certifies a full clear or an approach route to Falynum; evidence and
|
|
scope are in `docs/ROM_ENVIRONMENT_REVIEW_2026-10-06.md`.
|
|
Rebuild with:
|
|
|
|
```powershell
|
|
npm run runewaker:build:all -- --only the-origin
|
|
npm run runewaker:register:all
|
|
```
|
|
|
|
The base Demon Stronghold recipe opts into
|
|
`rom-demon-stronghold-derived-support-entrance-floor-02` through
|
|
`lib/rom-derived-support-styling-file.mjs`. Exact ROS, DDS, and converted PNG
|
|
hashes gate the native entrance-floor texture applied to its 186 generated
|
|
support boxes. Added UV1 preserves every existing geometry accessor and uses
|
|
the native floor scale/phase at the entrance; vertical box faces retain full
|
|
UV rank. This is explicitly a derived support fallback, not native floor
|
|
recovery throughout the dungeon. Demon Stronghold 125 has no such opt-in.
|
|
|
|
`scripts/playtest-rom-visual-routes.cjs --dist=<build-directory>` can freeze an
|
|
isolated production build for ordinary UI entry and walking QA when the shared
|
|
`dist` directory is locked. Its runtime telemetry is read-only.
|
|
|
|
Native ROS material alpha provenance is captured by
|
|
`native/runewaker_model_exporter.cpp` and applied by
|
|
`blender/native_material_alpha.py` through `blender/convert-runewaker.py`. The
|
|
export report records material/lighting types, diffuse source-channel identity,
|
|
and native alpha-test/blend parameters; the builder stamps the exact ROS
|
|
`sourceResourceSha256` before Blender conversion. The converter only applies
|
|
those flags when source hash, model, material index and diffuse texture identity
|
|
all match. Normal translucent alpha maps to glTF `BLEND`; alpha-tested images
|
|
with cutout pixels map to `MASK` with the native threshold, while fully opaque
|
|
images stay `OPAQUE`. Exact native `SRCALPHA:ONE` materials are recorded as
|
|
additive and use glTF `BLEND`; the runtime applies additive blending only when
|
|
that conversion provenance is complete. Unknown or incomplete native modes stay
|
|
unsupported. Exact native prelit materials receive `KHR_materials_unlit` before
|
|
the optimizer runs, so deduplication keeps them separate from standard-lit
|
|
materials sharing the same map. Resource-cache validation includes exporter,
|
|
converter and alpha-policy hashes so a semantics change forces re-conversion.
|
|
`lib/native-alpha-cache-validation.mjs` also requires the current ROS hash,
|
|
complete native alpha parameters and diffuse-channel joins, and identical raw
|
|
and prepared material reports. A matching old cache stamp alone is insufficient.
|
|
The prelit annotation removes Blender's unused `KHR_materials_specular` metadata
|
|
from those same verified materials, avoiding an incompatible glTF extension pair.
|
|
Protect alpha matching with
|
|
`python scripts/runewaker-pipeline/blender/test_native_material_alpha.py`, the
|
|
pre-optimizer semantics with
|
|
`node --test scripts/runewaker-pipeline/lib/native-material-semantics.test.mjs`,
|
|
and runtime behavior with
|
|
`npm test -- --run src/scene/dungeonMaterialAudit.test.ts`.
|
|
|
|
The environment builder runs terrain extraction and GLB generation as part of
|
|
the Sand Vortex recipe. Rebuild and register that package with:
|
|
|
|
```powershell
|
|
npm run runewaker:build:all -- --only sand-vortex
|
|
npm run runewaker:register:all
|
|
```
|
|
|
|
The extraction and terrain GLB stages are also available directly for inspection:
|
|
|
|
```powershell
|
|
node scripts/runewaker-pipeline/sand-vortex/extract-native-terrain.mjs
|
|
node scripts/runewaker-pipeline/sand-vortex/build-native-terrain.mjs
|
|
```
|
|
|
|
`src/scene/runewakerTerrainMaterial.ts` owns native splat-layer blending in the
|
|
browser. `src/game/runewakerDungeonEnvironment.ts`, applied through
|
|
`src/game/dungeonRegistry.ts`, owns the runtime lighting profiles; these lights
|
|
remain approximations because static imported GLBs contain no authored light
|
|
records.
|
|
|
|
`scripts/playtest-rom-visual-routes.cjs` checks normal offline entry, ordinary
|
|
keyboard movement, footing, and Standard/High graphics options using read-only
|
|
production telemetry. Pass explicit RoM slugs with `--dungeon=...`, optional
|
|
waypoints with `--routes=<json>`, or `--entry-only` for graphics-only captures.
|
|
It freezes the production distribution for each run and requires the geometry
|
|
loading state to settle before collecting evidence. These checks do not certify
|
|
combat, every route, or a full dungeon clear.
|
|
|
|
Repackage existing converted visuals without rebuilding collision or navigation:
|
|
|
|
```powershell
|
|
node scripts/runewaker-pipeline/reoptimize-environment-visuals.mjs
|
|
node scripts/runewaker-pipeline/reoptimize-environment-visuals.mjs --apply-staged
|
|
npm run runewaker:register:all
|
|
```
|
|
|
|
The first command stages every configured environment; the second validates all
|
|
staged hashes before replacing shipped visuals and their metadata. Forsaken
|
|
Abbey's authored visual descriptor must also match its updated import metadata.
|
|
|
|
For repeatable rendered review, start Vite on port 4207, run
|
|
`node scripts/playtest-rom-environments.cjs`, then
|
|
`node scripts/runewaker-pipeline/make-environment-review-sheets.mjs`. The preview
|
|
uses the shipped GLBs/KTX2, production material preparation and lighting
|
|
palettes at entrance, middle/final boss and reverse entrance viewpoints. Captures
|
|
and results live in `artifacts/playtest/rom-environment-quality`. This isolated
|
|
asset review does not simulate movement, collisions or combat; supplement it
|
|
with ordinary in-dungeon checks for runtime changes.
|
|
|
|
### Configured package workflow
|
|
|
|
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.
|