not-tonight/lanes/LANE_FLOOR.md
2026-07-19 16:20:53 +10:00

101 lines
5.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LANE-FLOOR — The Floor (Phase 1, parallel)
**Executor:** Opus 4.8. **Branch:** `lane/floor` (from main after Phase 0 merge).
**Owns:** `src/scenes/floor/` + its tests. **Prereq reading:** `docs/GAME_DESIGN.md`
§3.2 → `docs/CONTRACTS.md``LANEHANDOVER.md` (check for REVIEW blocks for you).
## Deliverable
`FloorDemoScene` runnable via `npm run dev` (menu key F): a populated top-down
venue you patrol with a flashlight, containing live instances of all three v0.2
infractions (cut-off, toilet stall, pat-down) + UV stamp checks. Runs standalone —
it self-populates from the patron generator; integration (Phase 2) will hand it the
real admitted-patron list instead. Code against `Patron[]` input from day one.
## Phase-0 reality (read before coding)
Phase 0 landed 2026-07-19 — see CLAUDE.md "Dev notes" for the API map and the
browser-pane verification trick. Floor-relevant specifics:
- Drunk thresholds exist in `rules/drunk.ts` (`drunkStage`, `hasVisibleTells`) —
no local copy needed; delete that TODO from your plan.
- `renderDoll(scene, patron, 'floorTopDown')` already produces the 16×16
top-down doll (hair blob over shoulders/top colour).
- `StubBeatClock` exists in core; instantiate it in your demo scene and call
`update(delta)` each frame — it emits `beat:tick` at 128 BPM.
- `generatePatron` + `ParadeScene`'s `resetRun` lifecycle are the reference
patterns for self-populating your demo.
- Register your demo scene in `src/main.ts`'s scene list; launch order stays
Boot → Parade. Menu keys (F for floor demo) can live in ParadeScene as a
scene-switch keybind — that one-line touch outside your dirs is pre-approved.
## Scene: the venue (top-down, ~2× screen scrollable)
Tilemap (hand-authored array is fine, no Tiled dependency): entry corridor, bar
(along a wall, stools), dance floor (centre), booths, toilets (2 stalls each,
door tiles), smoking-area door. **Darkness is the aesthetic:** black base with neon
accent strips; use Phaser Light2D (`setPipeline('Light2D')`) — ambient very low,
neon point lights, and the player's cone.
### 1. Player & flashlight
WASD/arrows patrol, slightly heavy acceleration (you're a big unit). Flashlight
cone in facing direction — a masked light + a cone polygon that REVEALS detail:
outside the cone patrons render as dim silhouettes (tint), inside it their full
doll colours + tell animations show. TAB toggles **UV mode**: cone goes purple,
normal detail hidden, `uvStamped` hands glow green. No stamp glow on a patron who
re-entered = infraction (march them doorward: walk-behind escort, below).
### 2. Crowd sim (`floor/CrowdSim.ts`)
Patrons wander between anchor points (bar → dance floor → booth → toilet loop)
with per-archetype weights. Dance-floor patrons bob **on `beat:tick`** (StubBeatClock
until integration — never your own timer). Intoxication drifts up over clock time
(bar visits accelerate it); drunk-stage thresholds from `rules/` if LANE-DOOR has
landed them, else local `// TODO(contract)` copy. Visible drunk tells escalate:
sway amplitude, stumble pathing, bumping others (small vibe leaks via
`meters:delta` if un-handled).
### 3. Infraction: The Cut-Off
Approach a `messy`+ patron, interact (E) → dialogue tree modal: three escalation
lines ("Have some water, mate" → "You're done for the night" → firm escort).
Right escalation level for their stage = clean ejection (+vibe, defeated-slouch
walk you escort to the exit); too aggressive on a merely `loose` patron = scene
(vibe, +aggro); too soft on a `maggot` = they stagger free, try again. Emit
`floor:infractionSpotted` / `floor:ejection` per contract. Leaving a `maggot`
unhandled for >N clock-min queues a deferred heat risk (v0.1: log to
`NightState.incidents`; inspector wiring is Phase 3).
### 4. Infraction: Toilet stalls (the rhythm game)
Stall doors show feet beneath: TWO pairs under one door = infraction. Interact →
close-up view of the door + a beat bar fed by **`beat:tick` events only** (do not
infer beat from elapsed time; measure hit accuracy vs the last tick's
`audioTimeMs`). Bang (SPACE) on-beat 3× consecutively: door flies open, two
patrons scatter in opposite directions with comic speed (+vibe, big). Off-beat
bangs: muffled "piss off mate" from inside, reset combo, small aggro. TEST: hit
windows off recorded tick timestamps (pure function, unit test —
`judgeBang(bangTimeMs, lastTick): 'perfect'|'ok'|'miss'`).
### 5. Infraction: Pat-down (contraband)
Suspicious idle (pocket-pat animation, driven by `flags.contraband`). Interact →
pat-down overlay: patron outline with 56 pocket zones; timed 10s; click zones to
reveal items, drag each to the **AMNESTY BIN** on the right. Items from
`data/contraband.ts` with silly sprites (placeholder: labelled coloured rects —
the budgie flaps). Missed items walk with them (deferred vibe leak). Contraband
found = +vibe, patron stays (confiscation, not ejection) unless it's severity 3.
### 6. Escort-out (shared mechanic)
Ejections attach the patron to walk-in-front-of-you pathing to the exit; they play
the defeated slouch. While escorting you can't interact — travel time is the cost
of every ejection (this is the floor's core resource: your position).
## Constraints
- Input: `Patron[]` + EventBus + clock. No imports from `scenes/door/` or `audio/`.
- All scoring via `meters:delta`; incidents appended via NightState API from core.
- Keep every judgement rule (bang windows, escalation matrix, pat-down scoring) in
pure functions with tests — scene code stays thin.
- Performance: 40+ patrons with Light2D at 60fps; profile before optimizing, but
silhouette-tint rendering outside the cone should be cheap (no per-frame texture work).
## Definition of done
Demo scene: all three minigames + UV check playable and readable in the dark
aesthetic; `lint`/`build`/`test` clean; pure-logic tests for bang timing,
escalation matrix, pat-down scoring; SESSION block appended to LANEHANDOVER.md;
branch pushed.