233 lines
10 KiB
Markdown
233 lines
10 KiB
Markdown
# Healer Man
|
||
|
||
A standalone React Three Fiber dungeon game using the exact Wailing Caverns
|
||
layout extracted from the local 3.3.5a client. The runtime includes the textured
|
||
WMO, all 3,381 active default-set doodad placements, reconstructed WMO water,
|
||
separate collision, authoritative entrance/encounter anchors, and a responsive
|
||
exploration HUD modeled after the architecture of `i-want-to-heal-mmo`.
|
||
|
||
## Run
|
||
|
||
```powershell
|
||
npm install
|
||
npm run dev
|
||
```
|
||
|
||
For online-account testing, run `npm start` in a second terminal so Vite can
|
||
proxy `/api` to the local Node/SQLite server on port `4173`. Then open the local
|
||
URL printed by Vite. Offline roster play does not require the second process.
|
||
|
||
The game starts at the Healer Man account gate. Online accounts authenticate
|
||
through the combined Node server and synchronize character rosters to its
|
||
persistent SQLite database. A separate device-local offline roster remains
|
||
available when the server cannot be reached. Server passwords are stored as
|
||
salted scrypt verifiers rather than plaintext.
|
||
|
||
For a production-style local run after building:
|
||
|
||
```powershell
|
||
npm run db:init
|
||
npm start
|
||
```
|
||
|
||
The TrueNAS checkout, persistent-data mount, reverse-proxy cutover, update,
|
||
backup, and Gitea APK release procedures are documented in
|
||
[`DEPLOYMENT.md`](DEPLOYMENT.md).
|
||
|
||
Verification:
|
||
|
||
```powershell
|
||
npm test
|
||
npm run build
|
||
```
|
||
|
||
## Conquest of Azeroth classes
|
||
|
||
All 21 CoA classes use a checked-in live Vol'Jin catalog generated from
|
||
Ascension's builder API and class database, then joined to the extracted
|
||
realm-specific `area-52/patch-D` `Spell.dbc` and `SkillLineAbility.dbc` files,
|
||
plus the spell support tables from `patch-S`. The snapshot includes 91 trees,
|
||
3,612 selectable nodes, all 3,929 node-rank spell IDs and descriptions, 5,444
|
||
class-page spell rows, 556 skill-line-specific spell chains, and 8,034 unique
|
||
spell records with complete DBC matches. Runtime spell ranks are selected from
|
||
character level; tree abilities remain locked until their exact node and rank
|
||
are purchased.
|
||
|
||
CoA progression starts at level 10 and alternates class-tree Ability Essence
|
||
and specialization-tree Talent Essence, reaching the live 26/25 split at level
|
||
60. Node costs, level locks, tree-investment gates, prerequisites, connections,
|
||
coordinates, passives, and rank tooltips come directly from the live payload.
|
||
|
||
Refresh the snapshot and locally extracted icons with:
|
||
|
||
```powershell
|
||
npm run coa:sync:live
|
||
npm run coa:icons
|
||
```
|
||
|
||
`coa:sync:live` maintains a resumable tooltip cache because the public database
|
||
occasionally returns transient gateway errors. `npm run coa:sync` refreshes the
|
||
builder/class data and reuses that cache without crawling every spell-detail
|
||
page. Icon export includes all ability, talent, and class-selection icons; the
|
||
current extraction completes without question-mark fallbacks.
|
||
|
||
## Boss loot
|
||
|
||
Boss loot is authored in SQLite-compatible SQL under
|
||
[`data/loot/`](data/loot/README.md), not in combat or scene code. Run
|
||
`npm run loot:generate` after changing the schema or seed data. The generator
|
||
validates the relational data and ships both a browser-safe JSON catalog and
|
||
`public/data/healer-man-loot.sqlite`, whose `boss_loot_browser` view is ready
|
||
for a future loot-browser screen.
|
||
|
||
Every Wailing Caverns boss rolls one item when it dies. The item instance
|
||
captures the player's level at the killing blow, remains on the corpse until
|
||
looted, and is then saved in that character's inventory. The SQL loot source
|
||
contains the original 3.3.5a attributes, ratings, armor, block, weapon damage,
|
||
weapon speed, regeneration, and spell-power values for each item. A scaled
|
||
drop preserves that original stat distribution instead of replacing it with a
|
||
generic item-power budget.
|
||
|
||
The equipment runtime uses the Wrath primary attributes and itemizable combat
|
||
stats. Strength, Agility, Stamina, Intellect, Spirit, Attack Power, Spell
|
||
Power, weapon damage, Hit, Critical Strike, Haste, Expertise, Armor
|
||
Penetration, defensive ratings, block, regeneration, resilience, and magical
|
||
resistances feed the player and AI-party combat calculations. Combat ratings
|
||
use the level- and class-specific conversion data from the local 3.3.5a client.
|
||
The Inventory & Equipment screen exposes the resulting Attributes, Offense,
|
||
and Defense sheets for the player and every current party member.
|
||
|
||
The reusable dungeon pipeline (global WMO and ADT/hybrid) is documented in
|
||
[`dungeon-pipeline/README.md`](dungeon-pipeline/README.md). Its entry points are:
|
||
|
||
```powershell
|
||
npm run dungeon:discover -- <slug>
|
||
npm run dungeon:extract -- <slug>
|
||
npm run dungeon:convert -- <slug>
|
||
npm run dungeon:optimize -- <slug>
|
||
npm run dungeon:creatures -- <slug>
|
||
npm run dungeon:navmesh -- <slug>
|
||
npm run dungeon:build -- <slug>
|
||
npm run dungeon:validate -- <slug>
|
||
npm run dungeon:enable -- <slug>
|
||
```
|
||
|
||
World and creature GLBs ship with KTX2/Basis GPU textures. On Windows, install
|
||
the pinned Khronos encoder into the project-local `.tools` directory and audit
|
||
the checked-in visual assets with:
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File scripts/asset-pipeline/bootstrap-ktx.ps1
|
||
npm run assets:ktx2:visuals
|
||
npm run assets:ktx2:audit
|
||
```
|
||
|
||
The dungeon, Manastorm, and Runewaker environment optimizers apply the same
|
||
KTX2 step to future visual outputs. The production build also runs the audit so
|
||
an accidentally reintroduced PNG/JPEG world texture fails before deployment.
|
||
|
||
## Controls
|
||
|
||
- Move: WASD, arrow keys, or left stick
|
||
- Jump: Space or L3
|
||
- Look: hold the right mouse button for mouse look, or use right stick
|
||
- Base abilities: keyboard 1–8; controller Cross, Square, Triangle, Circle,
|
||
R1, R2, D-pad Left, and D-pad Right
|
||
- Secondary abilities: hold Shift or L1 while pressing an ability control
|
||
- Tertiary abilities: hold Alt or L2 while pressing an ability control
|
||
- Hostile target: Tab or R3
|
||
- Friendly target: click a party/player frame or use D-pad Up/Down to cycle
|
||
living allies and yourself
|
||
- Party orders: F1 Attack, F2 Defend, F3 Stop
|
||
- Companion screen on a one-screen PC: C or gamepad Back/Select
|
||
- Map: M; Spellbook: P; Talents: N
|
||
- Pause: Escape or gamepad Start
|
||
|
||
Menus support keyboard, mouse/touch, and controller navigation. Use the D-pad
|
||
or left stick to move, Cross to select, and Circle to go back. Open
|
||
**Ability controls** from the pause menu to customize all 24 Base/L1/L2
|
||
bindings. Bindings save independently for each character and may be empty or
|
||
reuse the same class ability.
|
||
|
||
## Displays
|
||
|
||
Healer Man uses one authoritative game runtime and one WebGL canvas:
|
||
|
||
- AYN Thor top display: dungeon renderer and primary menus (`960 x 540` CSS).
|
||
- AYN Thor bottom display: roster, character details, and tactical UI
|
||
(`620 x 540` CSS). It never creates a second dungeon renderer.
|
||
- PC: the same lower-screen UI opens as an overlay with C or Select; normal
|
||
Tab navigation remains available throughout the menus.
|
||
|
||
Preview both Thor surfaces in a desktop browser at:
|
||
|
||
```text
|
||
http://localhost:5173/?layout=thor-preview
|
||
```
|
||
|
||
The Android host uses two Capacitor WebViews, Android `DisplayManager`, and a
|
||
secondary `Presentation`; state and semantic commands cross screens through a
|
||
rate-limited `BroadcastChannel`.
|
||
|
||
## Android / AYN Thor
|
||
|
||
Install JDK 21 and Android SDK Platform 36, set `JAVA_HOME` and
|
||
`ANDROID_SDK_ROOT`, then run:
|
||
|
||
```powershell
|
||
npm run android:apk
|
||
```
|
||
|
||
The debug APK is written under `android/app/build/outputs/apk/debug/`. To build
|
||
and install directly onto a connected device, use `npm run android:install`.
|
||
|
||
Android uses a separate compact `dist-android` build. It bundles the client,
|
||
interface, equipment, and Wailing Caverns starter content while optional
|
||
dungeons, character packs, and Manastorm stages are downloaded into app-private
|
||
storage. Installed content and local saves remain playable without a server
|
||
connection and survive APK updates. See `CONTENT_UPDATES.md` for the update
|
||
contract and `DEPLOYMENT.md` for TrueNAS publishing and signed Gitea releases.
|
||
|
||
## Runtime details
|
||
|
||
- The player is a dynamic capsule against a separate static Rapier trimesh.
|
||
- Physics uses a fixed 60 Hz timestep.
|
||
- The real entrance is `[163.49, -73.66, 132.9]` in Three.js coordinates.
|
||
- Source coordinates convert one-to-one as
|
||
`Three(x,y,z) = (-WoW.x, WoW.z, WoW.y)`.
|
||
- Repeated props use `EXT_mesh_gpu_instancing`: 3,348 placements are grouped
|
||
into 71 batches.
|
||
- The population uses 16 locally extracted, skinned creature GLBs with native
|
||
Stand, locomotion, attack, wound, cast, and death libraries; distant static
|
||
mobs and roaming packs are unmounted beyond the proximity gate. Background
|
||
animation runs at 30 Hz or 15 Hz by distance and freezes safely behind the
|
||
camera, while bosses, targets, combatants, and nearby actors stay full-rate.
|
||
- Production world and creature textures use KTX2/Basis transcoding to remain
|
||
compressed in GPU memory instead of expanding to uncompressed RGBA textures.
|
||
- Missing production GLBs activate a small cave proxy; malformed assets activate
|
||
the recoverable scene-error screen.
|
||
- The controller action HUD displays only the active eight-slot layer. Its
|
||
face-button diamond, shoulders, and D-pad keep the physical controller layout
|
||
visible without showing all 24 bindings over the playfield.
|
||
|
||
The navigation GLB is generated offline with pinned Recast settings. Party
|
||
leaders project onto its route graph, including separately-authored off-mesh
|
||
links, while collision/floor checks reject wall shortcuts. Followers replay the
|
||
leader's breadcrumb trail to avoid cutting corners. A disconnected route makes
|
||
the party hold safely and reports `Route blocked`; player movement continues to
|
||
use the collision GLB directly.
|
||
|
||
## Structure
|
||
|
||
- `src/game/`: serializable state, combat/loot simulation, input mapping, coordinates, and area math
|
||
- `data/loot/`: authoritative SQL loot schema and dungeon seed data
|
||
- `src/app/`: local accounts, character rosters, creation catalog, and shell state
|
||
- `src/platform/`: single/dual display routing and Thor synchronization
|
||
- `src/scene/`: R3F Canvas, Rapier bridge, camera, player, and dungeon loaders
|
||
- `src/ui/`: responsive HUD, encounter map, loading, pause, and error surfaces
|
||
- `src/assets/game/dungeons/wailing-caverns/`: shipping GLBs and anchor metadata
|
||
|
||
Wailing Caverns remains the global-WMO regression fixture. Deadmines is the
|
||
gated ADT/hybrid pilot and cannot be enabled without authoritative server data
|
||
and green automated/visual reports.
|