Commit Graph

79 Commits

Author SHA1 Message Date
Brian Fertig ce26b38df9 Add quests console with live progress tracking and claimable rewards
- Introduce QuestState ledger (granted/claimed ids) persisted via SaveData, with safe fromJSON validation that drops unknown ids and enforces claimed ⊆ granted
- Define the starter quest "Start Your Journey" in data/quests.json with four live checks: research node, lifetime asteroid mining, home tether level, and discovered world count
- Add totalMined counter tracked on each ore event to support the mining requirement independently of cargo hold
- Build QuestWindow (full-screen console at depth 80) with video feed, category tabs (Main Story live, Side Quests standby), quest list, detail plate with checklist and CLAIM REWARD action
- Wire QUESTS slot into both flight and surface command decks right of SHIP; SurfaceScene delegates snapshot/claim to the sleeping GameScene while rendering its own console notes
- Grant starter quest on first boot with delayed toast; announce "QUEST READY" once per quest when all checks complete
- Update research-builds tests for seven-slot deck layout; add dev/quests.test.mjs covering data contract, ledger behavior, save round-trip, and deck slot placement
2026-09-08 09:32:12 -06:00
Brian Fertig b1ae21e95e Changes to Research Areas 2026-09-07 23:10:47 -06:00
Brian Fertig 1c5767b095 Add deep-space station variants with spritesheet art and landing support
- Introduce StationFrames.js galaxy-wide pass that spreads spacestations.png
  variant frames across the galaxy, avoiding collisions among neighbor stars
- Stamp settlement.stationFrame in SystemGenerator so content carries the
  assigned variant (lazy === eager)
- Render deep-space stations from the spritesheet when available; keep
  procedural fallback for waypoints and missing textures
- Extend comms target with isStation/frame and allow REQUEST LANDING on
  deep-space stations, passing station flag into SurfaceScene
- Add landing.stationVideos entries and music.stationFrames slots keyed by
  variant frame; surface/shop clips degrade gracefully until authored
- Add dev tooling: station-shot page/runner for world/panel/land/deck states
  and a Node test asserting variant spread beats naive random assignment
2026-09-07 22:23:12 -06:00
Brian Fertig 568b1feaf2 Add route/destination visualization to map console
- Draw the active SET DESTINATION path in orange on galaxy lanes and circle the destination star with a breathing ring
- On the current-system chart, circle the destination object when it is in this system, or show the route exit gate plus a dashed ship-to-gate line when the destination is elsewhere
- Carry `route` edge keys and `destinationId` through `buildGalaxySnapshot`, `mapChartSnapshot`, and `systemChartSnapshotFor` so views can render the course
- Add dev screenshot harnesses (route-shot, exit-gate-shot) and extend galaxy-map tests to cover route/destination flags
- Document the new visualization in PROJECT_NOTES.md and add a takeoff video asset
2026-09-07 21:48:50 -06:00
Brian Fertig bfd85c8e1f Extend route compass to mark the destination object as final stop
- In the destination system, the orange compass arrow now points at the
  destination OBJECT (not just the next gate), so the "where to fly next"
  marker persists across the last hop into the system.
- Add `_checkDestinationReached` per-frame check: clears the destination and
  fires REACHED only when the ship is within the object's keep-out rim,
  replacing the old jump-time clear for destinations with a specific object.
- Route compass entries (`route:`/`dest:` ids) are now resolvable by
  `autopilotTo`, fixing the ship aiming at the star instead of the gate.
- New `alwaysFull` flag on compass targets keeps route waypoints at full
  readout (arrow + type + name) regardless of distance; add tests.
- Add `route.destTypeLabel` config key and update docs/PROJECT_NOTES.md.
2026-09-07 20:36:11 -06:00
Brian Fertig a5152590db Add SET DESTINATION route plotting with compass guidance
- New `js/galaxy/Route.js` derives the unique path between systems over the spanning-tree jump network (Dijkstra), exposing `planRoute` / `nextSystem`; pure and Node-tested in `dev/route.test.mjs`.
- Persist only the destination (`systemId`, `objectId`) in save data; the route itself is recomputed from the current system, so following it shortens automatically and a detour re-plots.
- Compass marks the route's next gate in orange (shown even while undiscovered) and suppresses that gate's ordinary cyan entry.
- On jump, resolve arrival / on-course / detour before `captureState` and queue REACHED / RE-PLOTTED notices to surface after the destination scene spawns.
- Map console SYSTEM tab now charts a charted star's system; confirming an object sets the destination and closes the map.
- Fix galaxy stars bleeding through the system chart: plate culling respects overall visibility, fog skips when no tethers anchor it, and the boot reveal finalizes to full alpha on tab switch.
- Add `assets/videos/ss-land-03.mp4` and document the route feature in PROJECT_NOTES.
2026-09-07 20:10:15 -06:00
Brian Fertig 6609df2736 Fix SET DESTINATION button overflow in shared ConfirmOverlay
- Add per-show width/height overrides so the SYSTEM tab's longer
  "SET DESTINATION" label gets a wider dialog than AUTOPILOT's ENGAGE
- Grow each button panel to fit its label (_fitBtn) and re-flow title,
  body and buttons into the bottom band (_layout) instead of using fixed
  positions that let long text run past the panel edge
- Record baseWidth so a grown button never stays wide for the next dialog
- Wire map.json systemConfirm/confirm size config through MapWindow
- Add ss-takeoff-02.mp4 asset
2026-09-07 19:23:18 -06:00
Brian Fertig efe17f3d2e Add SYSTEM tab and zoom-bloom star art to the map console
- New "System" socket in MapWindow: a charted star's chart drawn by the
  same painter as Current System (no ship/tethers), armed until the player
  picks that star on the Galaxy tab, then wakes with its map.
- Galaxy tab click flow changes: a visited star opens its chart in the
  System tab (onStarOpen) instead of confirming a jump; uncharted stars
  are readouts only and a lit lane to an uncharted star pops nothing.
- Zoom-bloom star art (GalaxyChart.starArtSpec + GalaxyView blit):
  diffraction spikes, per-type crowns (granulation, prominences, binary
  companion, habitable rings, nebula disc, void horizon) and a surface
  wobble fade in as you zoom; all angles/phases seeded per system.
- Star hit-testing now scales with the dot size and includes a crowded
  cluster dead band so lanes/empty space between stars no longer trigger
  hover.
- New systemChartSnapshot() in SystemChart.js plus tests covering shape,
  coverage, discovery flags, stats and determinism.
- Set Destination dialog (System tab) acknowledges the pick via
  onSetDestination; destination model is still being defined.
- Added spacestation image/video assets for future use.
2026-09-07 18:56:48 -06:00
Brian Fertig 22c2ccfcd2 Add GALAXY tab to the MAP console with whole-galaxy chart, jump lanes, a
- New `GalaxyView` renders glowing stars per archetype (pulsing heartbeat),
  the jump-lane web (traveled/frontier/unexplored), the charted region's
  convex hull, HOME/SHIP markers, hover readouts, and CONFIRM JUMP on a
  live lane (reuses the existing gate transport).
- `GalaxyChart.js` provides the pure model + geometry: edgeKey, snapshot
  builder, convex hull / padded polygon, star pulse/color, and plate
  clipping (Liang-Barsky + Sutherland-Hodgman) — all Node-testable.
- Run's footprint (`visitedSystems`, `usedGates`) is captured/restored/
  reset in SaveData; legacy saves default to "current system charted,
  nothing traveled".
- MapWindow gains tab switching between the system chart and the galaxy
  view, with shared stats/legend/status chrome per mode.
- Two dev tests cover the galaxy model, save round-trip, hull geometry,
  plate clipping, and a regression for the star-label blink bug.
2026-09-07 15:59:47 -06:00
Brian Fertig a846562782 Fix gate facing so gates sit on the destination side of system center
- Sort gate candidates by destination-side before tier, so an on-ray point behind the center loses to any destination-side aimed/scan point
- Add a new soft "facing from the center" check in tests: when some anchor's tether circle reaches the destination side (maxProj + tether > 0), the gate must lie there; a single far planet may still take the best aimed point
- Prefer a destination-side aimed candidate in the clearance fallback
2026-09-07 14:37:21 -06:00
Brian Fertig 963b2b5bc2 Redesign galaxy as sparse 60-system spanning-tree maze without rendered
- Shrink the roster from 200 to 60 systems and drop spiral arms / core bulge for a uniform-in-area sparse disk (data/galaxy.json)
- Turn the jump network into a pure spanning tree (shortcuts off): exactly one route between any two systems, barren systems become single-gate dead-end leaves
- Remove the rendered Star entity; non-home system centers are now empty space with the star kept only as invisible dossier flavor
- Gate anchors restricted to planets (stations no longer anchor) and every non-barren system guaranteed ≥1 planet so a buildable world always exists
- Give barren dead ends 1–2 asteroid clusters drifting inside their gate's level-1 tether as the stop's only payload
- Bump save format to 2 and reject legacy format-1 saves with a clear toast message
- Update tests, docs, and README to reflect the maze layout, leaf dead ends, empty centers, and new barren cluster rules
2026-09-07 14:12:40 -06:00
Brian Fertig 8f6e7bf539 Fix menu sub-bar anchor to rest on deck top edge, not button
- The sub-bar was anchored to the MENU button's center + half-height, which
  made it spill over the command deck's top rail (buttons are inset below
  the bar's top edge). Anchor y is now the deck's top edge so the bar's
  bottom edge sits on the deck.
- Update landing.json rocky land-02/03 entries to reference their own
  rocky surface/takeoff/shop videos instead of reusing gasgiant/terran
  assets, and add the new rocky-shop-03.mp4 video.
- Temporarily disable per-class planet tints in GameScene (option still
  accepted by Planet for when we re-enable it).
2026-09-07 12:23:50 -06:00
Brian Fertig 546e5c9bf3 Add Mining research category and ship-scoped build upgrades
- New `data/research/mining.json` tree (Improved/Advanced Mining Arm, Improved Storage) as blueprints that unlock matching builds
- Three new ship-scoped builds in the console's Mining tab: mining arm rate 1.5/2.0 minerals/s and hold cap 350; MAX-guarded effects applied to `ship.stats`
- Tether Level 3 promoted from research-direct effect to a build (tether-l3) gated on L2 tether, consistent with L2 blueprint pattern
- `BuildState.isBuiltAnywhere` + `isShipScoped` so ship upgrades count as built wherever the ship lands (no re-buy), records still key the planet
- `GameScene._restoreMiningUpgrades` re-derives ship mining stats from build records on load; `_applyMiningUpgrade` handles rate/capacity with toasts and HUD refresh
- New procedural icons: tether3, mining, mining2, storage
- Updated tests (builds, research-builds), diagnostics (BuildDiag v4), docs, README, manifest
2026-09-07 11:50:36 -06:00
Brian Fertig 146dc207df Add compact far-display mode to the discovery compass
- Targets beyond `farDistance` from the ship fold to a small text-less chip with a shrunken arrow, reducing visual clutter for distant objects
- Hovering a far chip expands it to the full readout after an intent delay; hovering off folds it back only after a grace period, so quick flicks don't pop or yank it
- Assign per-type compass accent colors: green for planets (data/planets.json), red for stations (data/stations.json), gray for asteroid clusters (already present)
- Export `isFarTarget` and `syncEntryMode` as pure helpers for Node testing; add far-display coverage to dev/discovery.test.mjs
- Add a headless integration driver (dev/compass-far.html + .mjs) that boots GameScene, parks the ship between near and far targets, and exercises the hover-intent lifecycle end-to-end
- Pass the ship position into `compass.refresh()` from GameScene so the compass can compute per-target far/near state each frame
2026-09-07 11:07:20 -06:00
Brian Fertig aa8cf8e091 Add autopilot confirm dialog and wheel zoom / drag pan to the map consol
- Clicking a charted object now opens an ENGAGE AUTOPILOT confirm before
  committing: CONFIRM plots the course and closes the console; CANCEL,
  scrim click, or ESC leave the map untouched (ESC is routed to the dialog
  first in GameScene).
- Wheel zoom (1x-8x) re-renders the chart crisp about the cursor, drag pans
  the zoomed view with frame-edge clamping, and double-tap on empty plate
  resets to 1x; each system remembers its last view.
- Fix ConfirmOverlay steady-state so it holds open values instead of
  collapsing to a 2px line once the open animation lands.
- Fix Phaser v4 hit-area space (unscaled frame coords) and hover/course-line
  destination offset by the plate origin so the full plate is clickable and
  decor draws at the correct world position.
- Add dev/map-click.mjs coverage for dialog, zoom, pan, and real-input paths;
  add rocky takeoff/landing video assets.
2026-09-07 10:27:29 -06:00
Brian Fertig 94cc87a177 Fix map tooltip ghosting by parenting it to the window container
- ttPlate/ttName/ttSub/ttHint were created as bare scene objects at depth 5, so they painted behind the map window (depth 80) and were never hidden on close, leaving a lingering "TAP TO PLOT COURSE" button on the world
- Add them to the ttCont container (which is inside MapWindow) so they paint with the window, fade with its close tween, and hide with ttCont
- Add dev/map-click.html + dev/map-click.mjs regression harness that opens the map, hovers/clicks a discovered object, verifies autopilot targeting, and checks no tooltip lingers after close
- Add rocky-surface-02.png asset
2026-09-07 08:35:53 -06:00
Brian Fertig ebd26ad7ba Stop thrusting ship dead when it hits an obstacle or the tether rim
- constrainShip on Planet, Star, Station, JumpGate, and AsteroidCluster now
  returns a contact boolean (true only when position/velocity/acceleration
  actually changed) so the scene can distinguish "touched" from "no-op".
- GameScene.onPostUpdate reads those flags and, if the ship is in its
  Shift+click thrust state, calls stop() + setState('normal', 'contact')
  the first frame any solid or the tether rim touches it — the hold ends
  and the ship rests on the rim instead of driving through.
- Non-thrust ships are left alone by the rule; their existing arrival/brake
  logic still owns their stop.
- dev/contact.test.mjs: headless tests covering no-contact outside the
  keep-out, contact + push-out + inward-motion strip on approach, no
  spurious contact while sliding off the rim, the full thrust-into-planet
  stop-dead-on-rim integration, and that the rule only fires in thrust.
- dev/smoke-game.mjs: add a third thrusttest check (c) verifying a
  Shift+click straight into the planet stops it dead on the rim.
2026-09-07 00:21:30 -06:00
Brian Fertig 75c9f99ecb Add Shift+click throttle lock for committed-heading flight
- Ship gains a `thrust` state and `thrustToward()` that commits to the heading toward the click point and holds full throttle past it, until a plain click or stop steers out.
- GameScene pointer handler branches on `pointer.event.shiftKey`: Shift+click locks the heading (raw aim), plain click still flies to the clamped stop point.
- Mining teardown no longer stomps the ship state when the player has already moved it into `thrust`/`normal`.
- Update hint text and add unit tests (tests 7–10) plus a live-scene smoke harness (`?thrusttest=1`) verifying past-click flight, steer-back arrival, stop braking, and mining-exit signaling.
2026-09-07 00:06:57 -06:00
Brian Fertig be6e9fc558 Add MAP console with system chart and fog-of-war
- Introduce MapWindow (js/ui/MapWindow.js): full-screen cartography overlay
  with a left video feed, CURRENT SYSTEM / GALAXY(standby) tabs, a canvas
  system chart (discovered planets/stations/gates/rock fields, tether union
  boundary, fog-of-war dim outside the tether), and a discovery/resources
  readout with segmented bars + legend. Clicking a discovered object plots
  the course via autopilot.
- Add SystemChart.js (js/galaxy/SystemChart.js) with pure geometry/stats:
  chartBounds, fitToRect, navDiscoveryStats, resourceStats — Node-testable
  in dev/system-chart.test.mjs.
- Wire MAP into the deck (ActionBar + GameScene): new 'map' slot right of
  SHIP, full-screen open/close contract, ESC handling, snapshot polling,
  and video preload for assets/videos/map.mp4.
- Add data/map.json (manifest entry) driving all map colors, tabs, stats,
  legend, sweep, glitch, hover, and click copy.
- Two-beat menu intro synced to the mainmenu track crescendo: beat 1 shows
  console chrome + subtitle; beat 2 (revealDelay, default 3200 ms) reveals
  title, bloom, buttons, seed decode, and a signature glitch.
- Fix rocky landing surface/takeoff assets in data/landing.json to point at
  the new rocky-surface-01.mp4 / rocky-takeoff-01.mp4 clips.
- Dev tooling: dev/map-shot.{html,mjs} (headless screenshot driver),
  dev/menu-intro-test.{html,mjs} (intro verification), and updated
  research-builds.test.mjs for the new MAP slot ordering.
2026-09-06 23:43:35 -06:00
Brian Fertig d78b7ad505 Add gate comm window and sprite-based jump gate rendering
- Replace direct-click-to-jump with a shared comms panel variant that shows LINK ACTIVE/DORMANT status, REQUEST JUMP (disabled while dormant), and CANCEL
- Render gates from the new 256x256 spritesheet (frame 0 body, frame 1 active swirl) with procedural fallback when the texture is missing
- Active gate swirl spins clockwise and breathes alpha between configurable bounds; dormant gates keep the body at full alpha with the swirl hidden
- Wire CommsPanel to a dynamic primary-button action id so the same panel serves world and gate variants
- Add dev probe page (dev/gate-comms.html/.mjs) and update jumpgate/jump-travel tests for the new sprite path, fallback renderer, and comm-window flow
2026-09-06 20:26:06 -06:00
Brian Fertig 0950b143f5 Add stars as central bodies of non-home systems and fix home-system iden
- Introduce Star entity (procedural texture per spectral class) drawn at the origin of every non-home system; only the starting system's central body is the home world
- Freeze `homeSystemId` at roster build so lazily generated content for newly arrived systems no longer misreads as home and deals a second home world
- Anchor tether-l1 builds on newly discovered worlds (effects.tether in data/builds.json) and re-materialize installed tethers after jump cuts / scene rebuilds
- Discovery now reports the central body in every system ("Home World" vs. spectral-class star label); stars are solid but not comms targets
- Add dev tools: nav-reach-probe (soft-lock analysis), star unit tests, tether-newworld browser test; fix landing video references and Phaser stubs
2026-09-06 19:34:49 -06:00
Brian Fertig 507d00f818 Add full-screen warp clip to gate jumps
- Play a cover-scaled video between systems on jump, with an opaque backdrop so the source doesn't show through
- Double-click skips the remaining clip; single press is swallowed while it plays
- Fall back to the short jumpDelayMs cut when no video is configured or missing
- Guard against stalled/overlong playback with a grace and duration cap before restarting
- Add assets/videos/jump.mp4 and document the new behavior in gates.json and PROJECT_NOTES.md
2026-09-06 18:08:29 -06:00
Brian Fertig ff557f87ba Fix jumpgate activation bug and add NAV chart diagnostics
- `_applyResearchEffects` now receives the node id explicitly instead of
  reading `node.id`, which is undefined (the id is the key in the tree's
  `nodes` map, not a field on the object) — this was silently skipping
  `activateGates` so researched jumpgates stayed dark
- Add `systemIdOfGatesNode()` as the pure inverse of `systemNodeId()` for
  the gates node, with round-trip tests
- Reconcile gate activation in `_onEnterSystem()`: if the gates tech is
  already unlocked, re-run `_activateSystemJumpgates` (idempotent) so a
  missed activation self-heals on the next entry/jump/reload
- Make `_activateSystemJumpgates` idempotent by tracking fresh keys and
  early-returning when everything is already online
- Add `navPoints()` and `navChart()` to SystemCategory.js as pure,
  testable cores for the jumpgate unlock condition (discovered/missing
  split over all NAV points)
- Add `js/dev/NavDiag.js` with `orbitNav()` / `orbitNavBrief()` console
  commands that print the live NAV chart and which objects are still
  undiscovered, installed by `main.js` on every page load
- Update `data/landing.json` to reference the correct gasgiant surface/shop
  videos for slot 03
- Add tests for `navPoints`, `navChart`, and `systemIdOfGatesNode`
- Document the activation wiring bug, the `orbitNav()` diagnostic, and the
  new pure functions in PROJECT_NOTES.md
2026-09-06 17:41:29 -06:00
Brian Fertig 5a67dbb206 Implement gate jump travel between systems
- Add JumpTravel.js with pure arrival geometry (return-gate lookup, spawn point past keepout) and wire it into GameScene.jumpThroughGate to re-stage the run via the save pipeline and scene restart
- Add gate hit-test (gateAt) so active gates trigger the jump on click while dormant ones show a console nudge and fall through to fly-here
- Add jump config block to gates.json (feature switch, arrival gap, delay, toast templates) and update landing.json gasgiant shop clips
- Add dev/jump-travel.test.mjs covering config, geometry, real-galaxy coverage, and determinism; refresh PROJECT_NOTES for the new mechanic
2026-09-06 16:37:48 -06:00
Brian Fertig a3a229a72d Add per-system research category that unlocks jump gates
- Introduce a dynamic "system" research category built at runtime with two techs: `{System} Map` (granted on entry) and `Unlock {System} Jumpgates` (researchable once every NAV point is discovered).
- Wire gate activation through the research effects seam so completing the jumpgate tech activates the system's gates plus linked return gates, anchors level-1 tethers at each activated gate, and saves/restores via a new `activatedGates` set.
- Extend ResearchModel with optional tree hooks (`available`, `lockNote`) so dynamic categories can gate research on live world state without adding static requires.
- Add map and gate procedural icons, update tests for the new category contract and icon roster, and document the system category in project notes.
2026-09-06 15:56:38 -06:00
Brian Fertig cb82da4935 Decouple comms panel from fly-to and add double-click clip skip
- Clicking a planet or station now opens the comms panel without moving the ship; world clicks are no longer fly-here targets, keeping mining beams live during panel interaction
- Add double-click (350 ms) skip for landing and takeoff clips in SurfaceScene so players can cut to the deck or flight world immediately
- Push restored mineral hold through the upper-right HUD on load so the readout matches the saved value instead of staying at zero
- Replace removed Phaser v4 Container.removeChildren() with removeAll(true) in JumpGate and Station destroy paths
- Update landing.json shop entries for terran frames 2–3 and document the new skip behavior
- Add dev harnesses for surface-skip, hold-restore, scene-restart, container-probe, and import probes; extend comms-click and saves-ui tests to cover the new interactions
2026-09-06 15:08:32 -06:00
Brian Fertig 0b92cb7b98 Galaxy refactor: 200 systems, object-composition, dormant gates, frame diversity
- Galaxy shrunk to 200 systems (data/galaxy.json) — always fully known,
  generation ~15 ms; roster/content two-level design unchanged.
- Object composition replaces planetCount (data/systems.json → objectCount):
  10% barren (jump-gate-only), else 2/3/4/5 objects (planets + free-space
  stations) at 15/30/30/15. One unified roll (rollSystemComposition) shared
  by the content generator and the frame pass.
- Barren systems: no planets, no stations, no asteroid clusters; their
  single gate sits on the star→destination ray at barrenDistance (8192 px).
  Strong connectivity keeps them reachable.
- Jump gates are DORMANT by default: every gate record carries
  active:false, the entity renders dim with a still field. Activation is
  the seam for the tether mechanic (an activated gate anchors a level-1
  tether). data/gates.json gains barrenDistance.
- Frame diversity (js/galaxy/PlanetFrames.js): one galaxy-wide pass spreads
  (class, frame) across the galaxy — fixed spatial order, least-used face
  among already-assigned nearest stars, seeded tie-breaks. Stamps
  planet.frame + content.homeFrame, read by GameScene.
- Tests: dev/frames.test.mjs added; jumps/galaxy/discovery/jumpgate/asteroids
  suites updated to the new rules (composition buckets, barren gates,
  active flags, frame determinism/spread, 5-object max, index clamps).
- Docs (README, PROJECT_NOTES) and stale 40k references updated.
2026-09-06 13:06:29 -06:00
Brian Fertig a1aa25b5ba Add jump gate network and in-system gate placement
- Introduce data/gates.json + js/galaxy/JumpNetwork.js: a strongly-connected, degree-limited spanning tree over the nearest-star graph (plus local shortcuts) so every system holds 1–3 gates, all jumps are local, and no system is closed or trapped
- Place each gate on the tether circle of an anchor (planet / space station / home world), facing its destination star; enforce radius band, clearance from anchors, and gap between gates in SystemGenerator.layoutGates
- Add the JumpGate entity (procedural twin-pylon portal) with the same solid contract as Planet/Station, discoverable in cyan, listed in the HUD dossier; wire into GameScene solids + discovery
- Guarantee every system holds at least one gate anchor (barren systems get a deep-space station); cap the home system at 3 objects so it fits the tighter band
- Rework solar-system layout to a full pairwise band [minSpacing, maxSpacing] with rotation tuned toward gate bearings; update tests and docs accordingly
2026-09-06 11:56:26 -06:00
Brian Fertig ed890a35c3 Fix text centering and close-button click passthrough in UI windows
- Center the ✕ close glyph and "IN PROGRESS" labels via setOrigin(0.5, …);
  Phaser Text defaults to origin (0,0), so they were anchored top-left
  and sat off-center on their plates
- Widen detail buttons from 152 to 190 px so the widest label
  ("IN PROGRESS 88%") no longer bleeds past the plate edges
- Treat 'closing' as open in isOpen so a close tap is consumed by the
  window while it fades out, instead of leaking through as a world click
2026-09-06 09:28:22 -06:00
Brian Fertig 09dfd00dd3 Make every planet settled and simplify system planet counts to a global
- Planet count is now a single global rule (20% barren, else 2–4 planets)
  instead of per-type spreads; the starting system always holds a gas giant
  plus a rocky world beside the home world.
- Every planet hosts one settlement by class (habitable rocky → colony, other
  rocky/ice/lava → mining station, gas → cloud base); free-space stations and
  beacons still roll per archetype with the core→rim gradient.
- Old probabilistic planet-settlement path kept behind allPlanetsSettled flag.
- Layout max drops to 6 objects (4 planets + 2 stations); the 11-object
  two-orbit case remains as a defensive fallback.
- Update tests, docs, and add rocky-land video asset.
2026-09-05 20:31:24 -06:00
Brian Fertig 4fd1f05359 Bump tether radius growth to 2× and refresh HUD on build completion
- Change radiusGrowth from 1.25 to 2.0 so level N doubles the previous
  level (L2 = 10240, L3 = 20480, L4 = 40960 px)
- Update all data descriptions, docs, and test defaults to match
- Add refreshHudTetherLevel() in SurfaceScene so the HUD line re-decodes
  when a tether build completes while on-surface
- Rename rocky-planet-02 asset (typo fix), add 03-a/03-b variants,
  point rocky frames at indices 6–8 in planets.json
- Add dev/tether-flow harness to exercise the full L2 build flow end-to-end
2026-09-05 19:52:54 -06:00
Brian Fertig 1d1cb2c150 Add build console with tether-l2 install, dev server, and diagnostics
- Introduce the BUILD deck slot on planet surfaces: full-screen BuildWindow
  (looping feed video, category tabs, build list, dossier + cost + BUILD
  button) backed by pure BuildModel/BuildState rules
- Move tether level 2 from a research effect to a one-off planet build
  (200 minerals, 20 s, requires L1 tether on the world); home world starts
  with tether-l1 pre-installed as a rule re-asserted after load
- Add `node dev/server.mjs` static server sending Cache-Control: no-store to
  stop browsers heuristically caching ES modules (the "new data + old JS" bug)
- Fix world-name casing leak: CommsPanel keeps canonical spelling in the
  landing payload; GameScene.startLanding normalizes via WorldNames.canonicalPlanetName
  so name-keyed build/tether lookups match
- Add in-game diagnostics (orbitDiag/orbitDiagBrief), dev/build-check.html
  self-check page, and Node tests for builds, world names, and save staging
- Persist builds (built records + in-flight remaining time) in the save bank;
  tick on the game-loop clock so a build survives takeoff mid-build
2026-09-05 18:55:29 -06:00
Brian Fertig d7f8e2101f Add shop clip toggle to surface deck
- SHOP button now swaps the looping surface clip for the world's `shop`
  video (e.g. terran-shop-01.mp4); pressing again swaps back. The slot
  relabels between "Shop" and "Leave Shop" via a new ActionBar.setLabel.
- data/landing.json gains a per-frame `shop` entry; worlds without one get
  a console note instead of a clip.
- SurfaceScene: toggleShop/leaveShop manage the shop video (pause/resume,
  visibility), error handling falls back to the surface loop, and cleanup
  on takeoff/shutdown disposes the new video and note glyphs.
- ActionBar: slots store their base fontSize so setLabel can shrink-to-fit
  long labels; paintSlot re-asserts hover state after relabeling.
2026-09-05 15:50:09 -06:00
Brian Fertig 70f4954c69 Wire research→build unlocks and add first tether-l2 build entry
- Define the two-sided unlock contract: research nodes declare `unlocks.builds`/`unlocks.research`, builds declare `requires` as "category/node id" (authoritative gate); ResearchModel exposes `unlocksOf`, `buildDefs`, `unlockIssues`, `buildIssues`
- Add `tether-l2` build entry (planet/station targets, credits+minerals cost, level-2 tether effect) and link it from `exploration/tether_l2`
- Show an UNLOCKS line in the research dossier so the console surfaces what a tech opens
- Extend dev/research-builds.test.mjs to validate both sides of the gate and the new model helpers
- Update data/builds.json, research.json, exploration.json `_comment`s and PROJECT_NOTES to document the contract
2026-09-05 15:15:08 -06:00
Brian Fertig 7138d153fa Add research console with Exploration tech tree and save persistence
- Full-screen RESEARCH window: looping archive feed, category tabs, branching
  DAG tech tree (top-down layout), per-tech dossier + RESEARCH button, deck
  progress bar
- Pure rules layer (ResearchModel / ResearchState) is Node-testable; the
  window is a passive view and GameScene owns effects, toasts, and saves
- First category **Exploration** (Tether Level 1–4, Tether Anchoring, Signal
  Amplification) lives in data/research/exploration.json; adding a category
  = one JSON file + one registry line + one manifest line
- Effects seam: `tether.level` grows the home tether via TetherField.setLevel;
  `capability` flags land on scene.researchCapabilities for future systems
- Save/restore round-trips an in-flight project (remainingMs captured at save,
  startedAt rebuilt on load); old saves without research still load
- Dev tooling: dev/cdp-shot.mjs (CDP screenshot with readiness wait),
  dev/research-shot.html/.mjs (boots the console + starts a run for a shot)
- Assets: gasgiant planet frame 03, takeoff/landing clips, research-computer
  feed; planets.png/.psd updated
2026-09-05 14:59:27 -06:00
Brian Fertig 407f6d6175 Add Continue button to main menu for resuming newest save
- SaveManager.latest() picks the filled slot with the newest savedAt
  (unparseable timestamps count as oldest; ties break to the higher slot)
- MenuScene wires a Continue button above New Game, grayed out while the
  bank is empty, that stages the restore via prepareLoad and cuts into
  GameScene without a confirmation beat
- Shift menu layout down to make room and park the Reroll button fully
  outside the seed field so its edge no longer bites the field
- Cover latest() behavior in dev/saves.test.mjs and update README and
  PROJECT_NOTES to reflect the finished save/load feature
2026-09-05 12:30:16 -06:00
Brian Fertig ee2e874f41 Replace tether HUD with live mineral hold readout bar
- Add MineralHud component (js/ui/MineralHud.js) showing "MINERALS n / N"
  plus a fill bar in the upper-right corner, replacing the old tether
  stack. One tween drives both the counting number and the bar so they
  never drift; a cyan flash ripples on landings; amber at capacity.
- Wire Mining to emit an onOre(gained, hold) seam per extraction tick and
  per fragment landing so the HUD fills live as the rock shrinks, not
  only at the batch 'absorbed' event.
- Remove refreshTetherHud / fmtRange from GameScene; instantiate MineralHud
  in create(), feed it via refreshMineralHud() from ore seams and mining
  events, destroy on shutdown.
- Add data/mineralhud.json config (corner pad, bar geometry, count-up and
  flash tuning) and register it in the manifest.
- Tests: new dev/mineral-hud.test.mjs covering layout, count-up/bar sync,
  superseded-tween guard, capacity/clamping, teardown; extend
  dev/mining.test.mjs to assert onOre ticks; drop tether-HUD checks from
  dev/system-hud.test.mjs; add setOrigin/setScrollFactor no-ops to the
  Phaser stub.
2026-09-05 12:12:18 -06:00
Brian Fertig 520cba85f6 Add mining economy: rock shrink, split/shatter, and mineral hold
- Extract minerals from the latched asteroid at ratePerSec × miningSpeed; each mineral shrinks the rock by 1 px so the beam stays latched to its rim.
- Break rocks that lose ~1/3 of their original size: large ones halve in place (beam keeps mining one half), small ones shatter into pieces that fly home and load the hold.
- Add ship.minerals hold with addMinerals/setMinerals capped at stats.mineralStorage; a full hold ends the run instead of grinding the rock away.
- Persist the hold in save/restore (captureState writes ship.minerals, applyRestore restores it) and keep legacy saves working when the field is absent.
- Play new mining_split sfx on each break and surface split/absorbed/storageFull events as console toasts.
- Expose AsteroidCluster rock surgery (setSize/addRock/removeMember) for runtime splits, and add headless Phaser stub + loader plus a mining test suite covering extraction, halving, shattering, full-hold stop, and the hold API.
2026-09-05 11:18:35 -06:00
Brian Fertig fdd5f8a506 Small adjustments to prepare for mining. 2026-09-05 10:29:02 -06:00
Brian Fertig 9ca0fa55a8 Add music system, UI SFX, and ship base stats
- New shared audio voices: js/utils/Sfx.js (playSfxOn/stopSfxOn/sfxPlayingOn)
  and js/utils/Music.js (loop voice + shuffle playlist), both with v4 guard
  rails (cache.audio.has, stopByKey, isPlaying) so missing assets never throw.
- data/music.json: menu loop, shuffled deep-space soundtrack for GameScene,
  and per-world surface loops keyed by planets.png frame; new mp3 assets in
  assets/music/.
- data/sfx.json: add ui_hover/ui_click/ui_window/ui_close/mining_loop and a
  dedicated scan track; wire UI components (buttons, panels, popups, save
  vault) to the shared voice via scene.playSfx seam.
- GameScene: start/stop the shuffle on create/shutdown, stop both soundtrack
  and mining hum on 'sleep' (landing launch+sleep) and resume on 'wake';
  mining hum loops while beam is live and stops quietly on 'stopped'.
- SurfaceScene: preload and loop the world's track from landing through
  takeoff; fix landing frame hand-off to pass sheetFrame instead of the
  texture Frame object.
- MenuScene: preload SFX + menu music, start the menu hum in create, stop it
  on the 'shutdown' event (v4 never calls shutdown() on transition).
- data/ship.json → stats: hullIntegrity/shields/cargoHold/mineralStorage,
  exposed as ship.stats for future combat/trading/mining systems.
- Tests: dev/sfx.test.mjs and dev/music.test.mjs cover the shared voices,
  guards, and data contracts; ship-behavior and system-hud tests extended
  for base stats and the mining hum lifecycle.
2026-09-05 10:10:18 -06:00
Brian Fertig cf999a14fa Add signal compass UI for scan-revealed undiscovered objects
- New js/ui/SignalCompass.js renders a faint ring around the ship with soft radio-signal markers at each undiscovered in-region object's bearing, with full→linear-fade envelope and per-id pulse phase
- Signals track live ship position each frame, drop on discovery, and re-emit on rescan; scene drives state, renderer is stateless
- data/signalCompass.json configures radius, lifetime (20s full + 5s fade), colors, signal/ripple/pulse/ring geometry with enabled gate
- dev/signal-compass.test.mjs unit-tests the pure signalAlpha envelope, bearingAngle math, and config sanity via Node
- dev/signal-compass-flow.{html,mjs} headless browser flow test boots real GameScene, presses SCAN, and verifies emission, fade, expiry, and discovery-drop behavior
2026-09-05 00:29:49 -06:00
Brian Fertig d0bd840dbc Add deep-scan sonar pulse replacing the Build action button
- Swap the command deck's "Build" slot for a "Scan" slot that fires an
  omnidirectional sonar pulse from the ship across the tether region.
- The wavefront is clipped to the union of tether circles: it is absorbed
  at the rim (bright absorbing arc + TetherField.excite shiver) instead of
  flying into empty space.
- Objects inside the region ring as the front crosses them (shock rings,
  RGB ghost, scale pulse); the starfield ripples and the camera thumps /
  rolls with the wave, then restores itself on completion or cancel.
- New modules: js/scan/ScanPulse.js (rendering + lifecycle),
  js/scan/ScanGeometry.js (pure circle-circle window math).
- All tuning lives in data/scan.json; the one SFX is the new "scan" key
  in data/sfx.json. Results are a seam for now — finishScan logs the
  in-region objects and reports the count in the console slot.
- Tests: dev/scan.test.mjs (geometry unit tests) and
  dev/scan-test.html/.mjs (headless flow test driving the real scene).
- Add Terran shop placeholder assets (two PNGs + one MP4).
2026-09-05 00:29:17 -06:00
Brian Fertig cd4d751edd Add upper-left surface HUD showing planet name, type, and tether level
- GameScene now passes the world's type label and tether level into the SurfaceScene launch payload; new tetherLevelFor() resolves a world's anchored tether (by label or anchor position) for that line.
- SurfaceScene builds/decodes a two-line HUD (Ethnocentric name in the menu title shade with black stroke, Centauri line below) while the surface clip loops, driven by the shared scramble decode; it is torn down on take-off and shutdown.
- landing.json gains a hud config block for margins, fonts, spacing, strokes, and colors.
- Added dev-only harnesses (surface-hud.html/.mjs test page and surface-hud-shot.html/.mjs screenshot probe) to verify the HUD styling, decode settle, payload, and teardown in headless Firefox.
2026-09-04 23:23:41 -06:00
Brian Fertig 1cbbf502df Add take-off clip to surface scene before resuming flight
- Introduce a `takeoff` video entry in landing.json for each world; missing/
  null entries leave the surface instantly (no regression)
- SurfaceScene.takeOff now plays the one-shot take-off clip full-screen,
  hides the deck, and only then stops the scene and wakes GameScene
- Guard against a clip that never starts or runs past its duration so the
  player is never stranded; finishTakeoff is idempotent
- Update surface-flow/surface-shot dev harnesses to assert and screenshot
  the new take-off stage
- Re-map gas giant frames in planets.json from [0,1,2] to [3,4,5] to match
  their sheet positions
2026-09-04 22:44:51 -06:00
Brian Fertig 69875c1ff0 Fix video sizing and replace fixed landing timeout with playback-aware g
- Introduce `attachClip` to set volume, cover-fit, and re-fit on the first presented frame (`created`) so clips no longer render ~3.4× zoomed in due to v4 placeholder sizes.
- Use `setScale` instead of `setDisplaySize` in `fitCover`, which is stable across frame swaps that preserve scale rather than size.
- Drop the blanket 8s safety valve that cut ~15s landing clips in half; replace with two targeted guards: a 5s stalled check (no playback progress) and a duration-based cap (duration + 5s margin).
2026-09-04 22:34:10 -06:00
Brian Fertig dd7000638a Add SurfaceScene with landing video and surface deck
- New SurfaceScene overlays GameScene when the player requests landing:
  plays a one-shot landing clip, then a looping surface clip behind a
  dedicated command deck (Shop/Build/Ship + Take Off + Menu).
- Wire comms panel "Request Landing" / "Land" buttons to launch the
  surface; TAKE OFF stops SurfaceScene and wakes GameScene so the run
  resumes exactly where it left off.
- ActionBar accepts an optional `buttons` override so scenes can supply a
  different slot list while sharing layout/colors/animation.
- SavePanel gains a `stateScene` option so saves from the surface read
  state from the paused GameScene underneath.
- Add data/landing.json (per-frame video map) and four placeholder
  surface clips; CommsPanel now passes its full target payload through to
  onAction so landing metadata survives the round-trip.
- Add dev harnesses: headless-Firefox screenshot helper, click-path test
  for the real user flow, and a surface-flow assertion suite with parked
  screenshot pages.
2026-09-04 21:25:44 -06:00
Brian Fertig d933914ac3 Add comms panel and free-space station entities
- New CommsPanel UI: world-anchored rusty-metal/green-phosphor console that opens on planet or station click, showing name decode, reputation bar (41 marks, -20 to +20), and REQUEST LANDING / LAND / CANCEL buttons
- New Station entity with procedural rendering (deep-space station ring + solar wings, or waypoint beacon), solid collision, and comms-target support
- data/stations.json configures station kinds, sizes, ship clearance; added to manifest
- GameScene wires click-to-fly + panel open together, handles button/outside/ESC close race, ESC priority, and commsAction seam for future landing logic
- Reputation.marksFor() computes lit-mark count for the gauge; covered by new unit tests in dev/reputation.test.mjs
- Dev tooling: comms-click (real-input interaction test), comms-shot (screenshot states), wdshot setup-step logging
2026-09-04 19:45:12 -06:00
Brian Fertig 0c30985588 Add reputation data layer with stable place identity
- Introduce Reputation module (js/reputation/Reputation.js) tracking player standing on planets and space stations on a −20…+20 scale, with the home world pinned at +20
- Add data/reputation.json config for scale bounds, neutral default, and home-world standing
- Assign stable seed-deterministic ids to planets (<systemId>-p<ordinal>) and settlements (<systemId>-s<n>) in SystemGenerator so saved standing lines up with regenerated galaxies
- Wire reputation into the save system (captureState/prepareLoad/resetRunState) with backward-compatible loading of pre-reputation saves as all-neutral
- Add faction-check placeholder: standingFor() resolves home → stored → owner/faction → neutral, with factionStanding() stubbed for the upcoming factions layer
- Register a single Reputation instance in GameScene via the shared registry (same pattern as Discovery)
- Add dev/reputation.test.mjs covering scale clamping, home pinning, serialization round-trips, legacy/corrupt record handling, save integration, and place-id stability
2026-09-04 18:37:44 -06:00
Brian Fertig 75767dc5a5 Add ship state machine and let movement break the mining sequence
- Introduce `Ship.state` ('normal' | 'mining') with `setState()` and an
  `onStateChange` callback so the scene can react to state exits.
- Any player-initiated movement (world click or compass autopilot) now
  drops the ship back to 'normal', which ends the mining sequence via the
  scene's handler; Mining.update() enforces the gate as a belt-and-braces.
- Rename `Mining.isLocked` to `isActive` and update GameScene click logic:
  clicks no longer hold during extension — they move the ship and abort the
  arm's reach.
- Tighten the popup-button swallow window from 300 ms to 20 ms and add a
  `containsScreen()` hit-test so only the exact button press is consumed,
  not subsequent deliberate clicks on the panel area.
- Expand the headless mining test to cover the new movement-abort contract:
  world click mid-extension breaks the arm, autopilot retracts the beam,
  and ship state transitions are asserted at every stage.
2026-09-04 18:06:33 -06:00
Brian Fertig cff8fa335e Fix mining popup width and layout to fit real font metrics
- Widen the data-driven base width and clamp the panel to at least the widest button plus padding, since MenuButton measures itself in the live web font and won't shrink below its label.
- Rewrite layout() with a top-edge-relative p() helper so the header/MINE/CANCEL order stays consistent whether the popup opens above or below the anchor.
- Add dev/popup-shot.html/.mjs to boot the game headless, await the typefaces (same contract as js/main.js), open the mining menu on a deterministic cluster, and report panel/button geometry plus fit booleans.
- Extend dev/wdshot.mjs with an optional settleMs argument so pages with top-level awaits (font loading) can finish their async boot before the setup script runs.
2026-09-04 17:16:56 -06:00