FTUE / Onboarding¶
Source: PROJECT_CONTEXT.md §8.6;
config.jsextraction(tutorialIncoming,tutorialBoard),loot.inRunInventory;game.jsTUTORIAL,buildTutorialMap,tutorialDriver,raidIntroDriver. Status: ✅ Implemented
What it is¶
The first-time player experience for new (gearless) players. A fixed, no-repeat sequence of 6 scripted tutorial stages teaches one mechanic group each, leading with stealth (the core pillar) and framing ranged combat as the fallback. Graduation unlocks the real raid; there is no tutorial-wrapped procedural raid.
How it works¶
- Gearless start.
defaultSave→emptyLoadout();save.tutorial = {stage, done}. The order is stealth-first, loot before combat — mirroring the engine rule that you only auto-fire once an enemy spots you. - The 6 stages (hand-authored fixed layouts from the
TUTORIAL[]data table →buildTutorialMap): - First Steps — tap-to-move, double-tap sprint (+stamina), swipe dodge-roll, pickups, extract.
- Loot & Explore — looting + tactical map: a bigger square map with obstacles + corner hidden chests; first chest is on-path (mandatory crack), exploring is rewarded. No enemy. (Inspect/equip + dump/Safe-Pocket steps are flag-gated on
loot.inRunInventory; while parked, cracking auto-collects and the kit auto-equips on extract.) - Unseen — STEALTH: echo-sense blips, vision cones, "you don't fire until spotted", silent backstab (ignores front armor; 🗡 tell on approach). A held goblin (clean first backstab) + a pacing warden; grants Fawn Boots.
- Heard — NOISE: crack a chest near an unaware sentry → it pulls in (
huntOnNoise). "Loud draws." - Open Combat — the whole fight, once: forced through a divider choke into the emberball's cone; front-armor → rear weak-point; dodge the telegraph (
dodgedTelegraph); then heal 🧪 / shield 🔋 (arrivestartHurtso the patch-up is usable). - The Vault — high-risk objective: hunt the roaming Keykeeper for the 🔑, force the locked gate (behind walls), loot the legendary prize.
buildTutorialMapbuilds the walled vault room (vault{tx,ty,w,h,door,loot},door:"s"faces you). - Per-stage coach + non-skippable gate. Each stage carries a coach script (
steps:[{text, done(G)}], driven bytutorialDriver, shown in#coach) and acanExtract(G)gate that blocks portal calling until the lesson is done. The shared gatetutAtFinalStep= every teaching step complete (the last step is always the free "go extract" line), so a stage can't be skipped. Per-frame action flags (sprinted/dodged/dodgedTelegraph/inspected/equipped/swapped/dumped/safed/healed/shielded/backstabbed/mapOpened) drive step predicates. Optional one-shothints:[{id,when,text}]banners teach without ever blocking extraction. - Scripted, readable AI patterns — tutorial enemies use predictable behavior (vs random roam) so the player can read and time around them; each is cleared the instant it's triggered, then acts normally:
hold:true(m.tutHold) — posted, fixed facing (clean backstab setups, the Heard sentry, Open-Combat choke guards).scan:true(m.tutScan,scanDir ±1) — posted but slowly sweeping its cone one direction (the sentry you route around).patrol:[{tx,ty},…](m.tutPatrol,tutPatrolMove) — paces a fixed waypoint loop (the Unseen warden, a moving backstab target).- (no flag) — full roam: stage 6 Keykeeper and the real raid.
- Systems per stage (
systems:{fog,timer,storm}→G.fogOn/timerOn/stormOn): fog is ON for every stage (learn "you only see what's near" from step one); timer + storm stay off until the real raid. Difficulty ramps: stages ≤5 use postedholdenemies; stage 6 + the real raid let enemies roam (Heard/Open Combat keephold). - Vertical orientation — every scripted stage is taller-than-wide (portrait fit); spawn at the bottom, travel up to the top exit. Map size is per-run (
MAP_W/MAP_Harelet, set viasetMapSize). - Fast tutorial portals (
extraction.tutorialIncoming/tutorialBoard) — no dead-wait; the rotating#tipis hidden during the tutorial (the coach replaces it). - Graduation → real raid. Clearing stage 6 flips
tutorial.doneand unlocks "Enter the Raid" (the real game IS the graduation). The first real raid shows a one-time intro coach (G.raidIntro→raidIntroDriver, gated bysave.tutorial.firstRaidShown): rivals (360° sight, no backstab), threat arrows, timer/storm, no-gear-loss. Every later raid shows a random reminder fromTIPS[]in the#tipstrip. - Lobby coachmark — one-time hint bar (
#invTip) in the Loadout screen after graduating, pointing at the equip/upgrade/scrap meta loop (save.tutorial.lobbyTipShown); the graduation result also names it. - Sandbox (Developer section) — runs the full procedural raid anytime; on a gearless save it borrows a non-persistent starter kit (
G.devKit, not banked on extract). Existing saves migrate totutorial.done=true(skip onboarding).
Tunables¶
| Key | Default | Meaning |
|---|---|---|
extraction.tutorialIncoming |
0 |
FTUE portal travel time (s); 0 = opens instantly, no dead-wait |
extraction.tutorialBoard |
4 |
FTUE presence time to board (s); trimmed from the raid's 9s |
loot.inRunInventory |
false |
Master toggle for the Loot Station / field-equip / bag UI; off = chests auto-collect, kit auto-equips on extract, and the inspect/equip + dump/Safe-Pocket FTUE steps are hidden |
Design intent¶
Teaches the pillars in the order that defines the game: Hide-and-kill and Route over reflexes come first (stages 3–4 are stealth/noise before stage 5's open fight), so combat reads as the fallback, not the default. The non-skippable canExtract gate plus scripted, readable AI (hold/scan/patrol) make each lesson land in a controlled best-case before the real raid removes the rails — serving Accessible extraction: all the suspense, none of the punishment, taught gently.
Open questions / deltas¶
- The inspect/equip + dump/Safe-Pocket lessons are parked alongside the in-run inventory (
loot.inRunInventory=false, §8.7); they reappear automatically if it's switched on. Whether the in-run inventory ships on/off is still a pending design call. - Unity port: the scripted-AI palette, per-stage
systemstoggles, and vertical-portrait stage layouts are JS-prototype conventions to re-author rather than port verbatim.