Skip to content

FTUE / Onboarding

Source: PROJECT_CONTEXT.md §8.6; config.js extraction (tutorialIncoming, tutorialBoard), loot.inRunInventory; game.js TUTORIAL, 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. defaultSaveemptyLoadout(); 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 🔋 (arrive startHurt so 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. buildTutorialMap builds 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 by tutorialDriver, shown in #coach) and a canExtract(G) gate that blocks portal calling until the lesson is done. The shared gate tutAtFinalStep = 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-shot hints:[{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 posted hold enemies; stage 6 + the real raid let enemies roam (Heard/Open Combat keep hold).
  • 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_H are let, set via setMapSize).
  • Fast tutorial portals (extraction.tutorialIncoming/tutorialBoard) — no dead-wait; the rotating #tip is hidden during the tutorial (the coach replaces it).
  • Graduation → real raid. Clearing stage 6 flips tutorial.done and unlocks "Enter the Raid" (the real game IS the graduation). The first real raid shows a one-time intro coach (G.raidIntroraidIntroDriver, gated by save.tutorial.firstRaidShown): rivals (360° sight, no backstab), threat arrows, timer/storm, no-gear-loss. Every later raid shows a random reminder from TIPS[] in the #tip strip.
  • 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 to tutorial.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 systems toggles, and vertical-portrait stage layouts are JS-prototype conventions to re-author rather than port verbatim.