Commit Graph

6 Commits

Author SHA1 Message Date
alexpaynex
ad5ac0861d Task #23: Workshop session mode UI — fund once, ask many
## What was done
- **`the-matrix/js/session.js`** (new module): Full session mode UI lifecycle:
  - Create session flow: amount presets → POST /api/sessions → deposit invoice step
  - Deposit payment: stub simulate → 2s polling until state=active
  - macaroon + sessionId stored in localStorage (`timmy_session_v1`)
  - Request submission: intercepts input bar when session active → POST /api/sessions/:id/request
    → Timmy speech bubble shows result, balance updates in HUD
  - Low-balance (< 50 sats): paused state, low-balance notice shown, topup quick-button
  - Topup flow: preset amount → POST /api/sessions/:id/topup → topup invoice → stub pay → poll
  - Restore from localStorage on page reload: validates session via GET, restores full UI state
  - Session expiry / 401 macaroon rejection: clears storage, resets to unfunded state
- **`the-matrix/js/ui.js`**: Added `setSessionSendHandler(fn)` + `setInputBarSessionMode(active, placeholder)` exports; send() routes to session handler when active, falls back to WS visitor_message
- **`the-matrix/index.html`**:
  - `#top-buttons` flex container: " SUBMIT JOB" (blue) + " FUND SESSION" (teal) side-by-side
  - `#session-hud` balance line in HUD (green, hidden until session active)
  - `#session-panel` left-side slide-in panel: fund / invoice / active / topup steps
  - `.session-amount-btn` presets (200, 500, 1000, 2000, 5000 sats) with active state
  - `#visitor-input.session-active` CSS: green border + 3s pulse keyframe animation
  - `#low-balance-notice` strip above input bar with Top Up quick-button
  - `.primary-green` / `.muted` panel button variants for session panel theme
  - `#session-panel` inherits shared `.panel-btn`, `.invoice-box`, `.copy-btn` with green overrides
- **`the-matrix/js/main.js`**: Import + call `initSessionPanel()` in firstInit block

## Verification
- `npm run build` in the-matrix → clean build (0 errors)
- Full testkit: 27/27 PASS (all session tests 11–16, 22 still green)
2026-03-19 03:50:34 +00:00
alexpaynex
0419ada6e2 Add ragdoll physics and reactive camera shake for satisfying slaps
Implement ragdoll physics for agent interactions, including a state machine for falling, getting up, and counter-attacks. Introduce camera shake based on slap impact and export camera shake strength from agents.js. Update main.js to apply camera shake around the renderer.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 418bf6f8-212b-4bb0-a7a5-8231a061da4e
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: b80e7d8c-b272-408c-8f8f-e4edd67ca534
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/9f85e954-647c-46a5-90a7-396e495a805a/418bf6f8-212b-4bb0-a7a5-8231a061da4e/Q83Uqvu
Replit-Helium-Checkpoint-Created: true
2026-03-19 03:40:41 +00:00
alexpaynex
35babd2400 Task #22: Slap/ragdoll physics on Timmy
## What was done
- agents.js: spring physics (stiffness=7, damping=0.8, clamp ±0.44 rad) on
  timmy.group.rotation.x/z via slapOffset/slapVelocity integrated per-frame with
  proper dt (capped at 50ms for tab-background safety)
- agents.js: applySlap(hitPoint) — computes XZ impulse direction from hit point
  relative to TIMMY_POS, adds angular velocity, triggers pip startle + crystal flash
- agents.js: _playBoing() — lazy AudioContext, sine oscillator 260→90 Hz with
  exponential gain decay (0.38s)
- agents.js: Pip startle — 3s decay timer, random scatter direction offset, 4x
  spin speed while startled, boosted pip light intensity
- agents.js: Crystal ball hit flash — hitFlashTimer=0.5s, intensity spikes to 10
  and fades; normal crystalLight/cbMat logic when not flashing
- agents.js: getTimmyGroup() export for raycaster target
- interaction.js: registerSlapTarget(group, applyFn) — stores targets
- interaction.js: _onPointerDown capture-phase listener — raycasts against
  timmyGroup recursively, calls applySlap on hit, suppresses OrbitControls drag
  for 220ms via stopImmediatePropagation + controls.enabled toggle
- main.js: imports getTimmyGroup, applySlap, registerSlapTarget; wires
  registerSlapTarget(getTimmyGroup(), applySlap) after initInteraction

## Verification
- Vite build: clean, 14 modules, 0 errors
- /tower HTTP 200
- Testkit: 27/27 PASS
2026-03-19 03:31:01 +00:00
a70898e939 feat(epic222): Workshop — Timmy as wizard presence, world state, WS bootstrap (#31) 2026-03-18 22:15:46 -04:00
e088ca4cd8 feat(integration): WS bridge + Tower + payment panel + E2E test [10/10 PASS] (#26) 2026-03-18 21:20:51 -04:00
83a2ec19e2 fix(testkit): macOS compat + fix test 8c ordering (#24) 2026-03-18 21:01:13 -04:00