Commit Graph
21 Commits
Author SHA1 Message Date
jesse 3ae71f9dd3 fix(client): level-triggered watchdog arms chassis on cold start
CI / quality (push) Failing after 53s
The drive loop was armed purely edge-triggered from
humanoid:GetPropertyChangedSignal("SeatPart") plus a one-shot catch-up
applySeat() at init. On cold boot the server seats the player AFTER that
catch-up runs, so the edge is lost, startDriving() never connects, and all
four wheel motors stay at MotorMaxTorque = 0 - the car is completely
undrivable until the player manually gets out and back in.

Replace the one-shot with a 0.5s level-triggered watchdog: if seated in a
DriveSeat with no live heartbeat connection, arm it; if not seated with a
live connection, stop it. Immune to any ordering of bootstrap vs seating.

Verified on cold boot (no manual reseat): all 4 motors uniform, poisoned
torque values restored within 0.6s, car accelerates to MaxSpeed 163 studs/s,
holds it upright, and engine-brakes 163 -> 0.
2026-07-31 15:52:12 -04:00
jesse 45069188be fix(CarManager): repair car torn apart on spawn by client-owned character
Sit() dragged the seat's body assembly ~15,700 studs to the client-owned
character while the knuckle/wheel assemblies stayed at the spawn pad,
tearing the car apart; wheels then fell out of the world.

Server-side character:PivotTo() does not stick (client has authority) --
it holds one frame and snaps back, so the pre-seat teleport could not fix
this. Instead: record each part's offset from the body while the model is
intact, take server network ownership, let Sit() and the snap-back settle,
then reassemble every assembly around the body (forced level) and hand
ownership back to the driver.

Verified in Studio: max part separation 6.42 studs (exhaust, normal),
up-vector 1.00, driver seated, drove 98.6 studs at 41 studs/s intact.
2026-07-31 13:00:33 -04:00
jesse d45f35736a fix: car now drives - collision groups, rigid hubs, pad spawn, anticheat grace
Four independent bugs kept the car immobile at the world origin:

1. Wheels collided with their own chassis. Wheel inner edge sits at 2.80
   vs body edge 3.00, and wheel top -0.20 vs body bottom -0.70. The
   overlap is intentional styling, but in one collision group the wheels
   ground against the body: motors spun ~1 rad/s against 20,000 torque.
   Wheels now use a CarWheel group that ignores CarChassis.

2. Suspension exploded on spawn. PrismaticConstraint+SpringConstraint
   between a 0.6-stud hub and the ballasted body was unstable enough to
   fling knuckles ~10,000,000 studs out, past FallenPartsDestroyHeight,
   deleting the wheels. Replaced with a rigid welded hub mount.

3. Car spawned at world origin, not the pad. MapBuilder made a SpawnPad
   part but no SpawnLocation, so characters spawned at (0,0,0) and Sit()
   dragged the car to them. Added a real SpawnLocation and the model is
   now pivoted after parenting, with the character teleported first.

4. AntiCheat snapped that legitimate spawn teleport back. An ~8,500-stud
   server move reads as a teleport hack. Added AntiCheat.grant() so
   server-initiated moves are exempt for a short grace window.

Verified in Studio: 881 studs in 6s, 496 studs/s top speed, 152 deg
steering, braking 33 -> 0 studs/s, chassis stays upright.
2026-07-31 10:04:47 -04:00
jesse 766fce5088 test: add automated map verification harness
Eight geometric assertions against the built map, runnable from Linux over
the Studio MCP bridge. Each check tests the world that exists rather than
trusting that a build reported success.

Check 1 is the important one: it fresh-requires Circuit and asserts
823/200/474. Studio caches ModuleScripts, so a stale Circuit will happily
build a plausible-looking map of the wrong circuit -- which is exactly what
happened before. The shape checks are meaningless without it.

Found and fixed while writing this: a Sound with a doubled rbxassetid://
prefix in the imported CarLibrary chassis.

Probe note: pillar tops are flush with the deck by design (0.00 clearance),
so the car-envelope probe must ride fully above the road surface or it
reports its own supports as intrusions.
2026-07-31 08:25:57 -04:00
jesse 0dbd7420d4 map: signature crossings + fix skyline setback clipping the road
buildBridges() adds the two landmark structures the generated road was
missing, driven off the existing per-sample tunnel/bridge flags in
Circuit.luau (200 tunnel / 474 bridge samples, recorded at trace time):

  * NihonbashiViaduct  - box girder carried on piers over the historic
    stone bridge, the C1's most recognisable stretch.
  * Shiodome cable-stayed span - twin H-towers with fanned stays.

Also fixes buildSkyline() placing geometry inside the racing surface:

  * the setback test compared the building CENTRE against 220 studs, so a
    220-wide tower still reached 110 studs inward - through the tunnel
    bore walls. Now tests the outer face (near - w/2) against
    ROAD_WIDTH/2 + 60.
  * it strided samples by 3, skipping the closest approach on tight
    corners. Now tests every sample.
  * NeonSign hangs off the +X face and was never clearance-checked at
    all; it now gets its own test.

Verified in Studio against a full rebuild (823 samples -> 2468 road
parts): 400 tunnel walls / 200 ceilings for the 200 flagged samples,
621 buildings placed, and raycasts over every road part report 0
headroom and 0 lateral obstructions. Minimum building clearance 47.8
studs.
2026-07-31 02:13:55 -04:00
Hermes 1f888b3693 map: rebuild circuit on real Shuto C1 geometry from OpenStreetMap
CI / quality (push) Successful in 56s
Replace the invented rounded-rectangle circuit with the actual Shuto
Expressway Inner Circular Route (relation 4256008) traced from OSM and
projected to studs at 1 stud = 0.28 m.

- Circuit.luau: 823 evenly-spaced samples (60 studs), 49,388 studs /
  13.83 km lap. Real junction names (Tanimachi, Miyakezaka, Kasumigaseki,
  Ginza, Kyobashi, Edobashi, Hitotsubashi), real tunnel + viaduct
  sections. Deck height smoothed to max 4.3% grade.
- MapBuilder.luau: builds road, guardrails, kill walls, lit tunnel bores,
  viaduct pillars, junction gantry signs, Daikoku-style PA, and Tokyo
  landmarks (Tower, Skytree, Imperial Palace moat, Station, Ginza,
  Shiodome, Roppongi Hills, National Diet) at true relative positions.
- Contract names (SpawnPad, FinishLine, KillWall) unchanged, so gameplay
  code is untouched.
2026-07-30 21:26:49 -04:00
jesse be52290093 Add three-mode Wangan loop; rename project to Tokyo Wangan Racing
CI / quality (push) Successful in 1m18s
Daikoku Futo PA becomes the hub (Tokyo Xtreme Racer structure): park, pick a
mode, drive out the exit gate to start the run, pull back into the PA to end it.

Modes:
- CRUISE      free roam, banks session + lifetime kilometres
- DUEL        gap-based battle: hold 350 studs for 3s to win
- TIME ATTACK solo flying lap, 4 sector splits, saved personal best

New shared modules:
- Circuit.luau  one source of truth for loop geometry. progressOf(pos) gives
                lap distance, which drives lap detection, sectors and duel gaps
                alike, so the map and gameplay can never drift apart.
- Modes.luau    mode definitions + duel/time-attack tuning constants

Server-authoritative throughout: ModeManager samples the car real position on
Heartbeat and the client never reports distance, lap time or gap. Teleport and
respawn jumps are rejected from distance accumulation.

ProfileTemplate v3 adds DistanceStuds, BestLapTime, BestSectors, DuelsWon and
DuelsLost; ProfileStore Reconcile migrates existing saves.

Rename: repo, wally package, local dir and stale NAS asset paths all move off
the old fnf-sim name. NAS folder was already 0-tokyo-wangan-racing, so those
doc paths were broken before this.
2026-07-30 20:16:04 -04:00
Hermes 681c3462c6 Rename: Tokyo Wangan Racing (was Fast & Furious: Tokyo Expressway)
- Title in README + GDD, UI/log prefixes FnF -> Wangan
- Rojo project name -> TokyoWanganRacing
- Fix undefined `H` in CarManager seat CFrame (selene error) -> Chassis.BODY_SIZE.Y
2026-07-30 20:03:52 -04:00
jesse e0bee80795 CarBody: sculpted per-car visual body kits (cars-first priority)
CI / quality (push) Successful in 1m5s
- New src/server/CarBody.luau: wedge noses, raked glass, pop-up lights (RX-7),
  spoilers (lip/wing/GT), tail styles, exhaust tips, underglow, accent neon,
  alloy rims. All parts Massless+welded: zero physics impact.
- CarManager: replaced the old glass-cube cabin with CarBody.build().
2026-07-22 08:50:19 -04:00
jesse 0fc0d0ae22 Map v3: Shuto Night Loop — Tokyo landmark circuit
CI / quality (push) Successful in 55s
The straight strip becomes a closed rounded-rect loop (~7,400 studs/lap)
built from centerline samples, Shuto-C1 style. Landmark zones:

- Daikoku Futo PA: drivable meet lot off the south straight (guardrail
  gap entrance), painted bays, flood-light towers, bilingual sign —
  cars now SPAWN at Daikoku like a proper meet
- Rainbow Bridge over the east straight: white suspension towers with
  beacons, cross beams, rainbow-colored rail lights
- Odaiba beyond the bridge: blocky Unicorn Gundam (glowing eyes, horn,
  pink psycho-frame strips) + 16-cabin neon ferris wheel
- Yamate-style tunnel enclosing the whole north straight
- Tokyo Tower replica (orange/white tiers, two lit decks, antenna) west
- Tatsumi PA overlook pad NE
- City-core skyline inside the loop + outer ring skipping landmark zones
- Bilingual green highway signs via SurfaceGui (JP + EN)

Gameplay contract preserved: SpawnPad/FinishLine/KillWall names intact,
kill walls hug every road edge except the Daikoku entrance.
2026-07-22 02:38:47 -04:00
jesse dae30fd22e RX-7 audio v2: turbo whistle + exhaust from the action-cam library
CI / quality (push) Successful in 1m4s
- Scanned b-action-cam-footage/clipchamp (99GB, 5 videos of the FD):
  extracted audio NAS-side via linuxserver/ffmpeg container (stream-copy),
  scanned 69min return drive per-second for engine tonality + whistle
  prominence (1.5-9kHz peak vs band median)
- New rev loop: 985-993s highway pull — 0.0Hz pitch drift over 8s,
  whistle ~1.7kHz at +33dB, exhaust + turbo captured together (seam 0.001)
- New whistle-only loop: same pull high-passed 1.2kHz — isolated spool
- SoundController: optional per-car Whistle layer that rides boost
  (throttle held at speed): fades in past 25% speed, pitch 0.9->1.35
- ROTARY_SOUND.md updated; three .ogg uploads needed in Studio now
2026-07-22 02:26:45 -04:00
jesse 1891f3f11d RX-7 rotary loops: extracted from the owner's real car footage
CI / quality (push) Successful in 49s
- Sourced from c-finished-videos/2026-07-10 sessions (the actual FD)
- Scanned 6 min of audio per-second for RMS/dominant-freq/spectral
  flatness; picked the most tonally-stable stretches (idle: 272-288s
  @ ~99Hz flatness<0.02; rev: 319.5-327s @ ~105Hz, louder)
- Zero-crossing trim + 150ms equal-power tail-to-head crossfade =
  seamless loops (seam jump 0.001 / 0.005); normalized to -3dBFS
- Shipped as assets/audio/rx7_idle_loop.ogg + rx7_rev_loop.ogg (236KB);
  wav masters mirrored to NAS 001-1993 Mazda RX-7/sound/
- ROTARY_SOUND.md updated: only Studio upload + 2 asset IDs remain
2026-07-22 01:59:29 -04:00
jesse b2cc917942 Sound: two-layer engine architecture + rotary pipeline for the RX-7
CI / quality (push) Successful in 43s
- SoundController rebuilt around idle+rev loop crossfading (real racing
  game approach): idle layer barely pitch-shifts (keeps engine character),
  rev layer carries the speed range; crossfade window 5%-45% of top speed
- Per-car CAR_SOUNDS table so the RX-7 gets real 13B rotary loops while
  other cars keep the generic set
- docs/ROTARY_SOUND.md: full record->loop->upload pipeline for capturing
  the owner's REAL RX-7 (extract audio from video, zero-crossing cut +
  equal-power crossfade seam, normalize, ogg, Studio upload, wire IDs)
- Toolbox rotary rips evaluated and rejected: unauditionabe off-platform,
  short/unloopable, murky rights; the real car beats any rip
2026-07-22 01:57:16 -04:00
jesse 2ae3bf8bdb M1/M2: engine + tyre audio, night-city ambience
CI / quality (push) Successful in 56s
SoundController (client):
- Looping engine sound on the car body: pitch 0.7->1.9 tracks speed
  (curved so low speed feels torquey), volume swells with throttle
- Tyre squeal loop faded by lateral slip (velocity along body RightVector)
  and hard braking from speed; always playing at 0 volume to avoid pops
- 3D sounds with rolloff so other players hear cars pass
- Asset IDs from safe sources (Roblox Resources engine loop,
  ProSoundEffects squeal); swap in SOUNDS table after audition

Ambience (server):
- Atmosphere (purple-grey haze, glare) so neon reads in the air
- BloomEffect for neon pop + subtle cool ColorCorrection
- Slow ClockTime ping-pong 22:00->03:00 over 10 min: always night,
  but the sky breathes
2026-07-22 01:52:30 -04:00
jesse e94bb8fcda M1/M2: chase camera + expressway map v2
CI / quality (push) Successful in 52s
CameraController (client):
- Scriptable chase cam only while in the DriveSeat; restores default on exit
- Frame-rate independent damped follow with look-ahead aim point
- Flat horizon (ignores car pitch/roll) so bumps don't shake the view
- Speed-based FOV kick (quadratic ramp) for sense of pace
- Cleans up on Died/despawn

MapBuilder v2:
- Highway extended 2400 -> 3200 studs with distinct feature zones
- Gantry arches (seg 2), enclosed neon-lit tunnel (seg 3), jump ramp +
  landing pair on the right lane (seg 4, left lane stays flat)
- Procedural neon skyline towers flanking both sides (deterministic seed,
  same city every server)
- End kill-wall so you can't sail off the far edge
2026-07-22 01:09:44 -04:00
jesse b3a1044df6 M1: constraint chassis (springs, servo steering, motor wheels)
CI / quality (push) Successful in 54s
- New shared Chassis.luau: geometry constants + per-car tuning from stats
- CarManager.buildCarModel rebuilt: prismatic+spring suspension per corner,
  servo-hinge steering on front knuckles, motor-hinge driven wheels,
  hidden dense ballast for anti-roll; VehicleSeat kept as input device only
- New client ChassisController: drives motors/servos from seat
  ThrottleFloat/SteerFloat per Heartbeat; speed-sensitive steering lock;
  engine braking on throttle release
- Driver gets network ownership of every unanchored part (constraint
  assemblies are separate; missing one causes stuttery physics)
- Docs: MESH_SWAP.md rewritten for shell-on-chassis workflow; ROADMAP updated
2026-07-22 00:20:59 -04:00
jesse 07a67204ca Scope cut: drive-only MVP (remove racing + economy)
CI / quality (push) Successful in 1m1s
Per user direction, the MVP is now simply driving cars on the expressway.
- Removed RaceManager and Economy modules entirely
- Slimmed Remotes to DataUpdated / SpawnCar / EquipCar
- ProfileTemplate now just remembers the last driven car (v2)
- Cars: dropped price/rep/upgrade fields; kept identity + driving stats
- CarManager: stat-based tuning only; RX-7 allowlist via GameConfig.canDrive
- DataManager: assign default car on join; downgrade RX-7 if de-allowlisted
- Client: replaced garage/economy UI with a simple car picker + respawn
- Docs: GDD/ROADMAP/README rewritten for drive-only; added docs/MESH_SWAP.md
- Gates: stylua clean, selene 0/0, rojo builds
2026-07-22 00:11:11 -04:00
jesse 5fc03d611d CI: run on ubuntu-24.04 (rojo 7.5.1 needs glibc 2.39, 22.04 has 2.35)
CI / quality (push) Successful in 1m11s
2026-07-22 00:04:37 -04:00
jesse ceece10a86 Add owner + son Roblox UserIds to RX-7 allowlist
CI / quality (push) Failing after 14m51s
2026-07-21 23:53:00 -04:00
jesse e9aec28af3 Restrict RX-7 to allowlisted UserIds (owner + son demo lock)
CI / quality (push) Failing after 1m0s
- GameConfig: RX7AllowedUserIds allowlist + isRX7Allowed/starterCarFor helpers
- ProfileTemplate: no hard-coded starter; granted per-player by UserId
- DataManager: grants RX-7 to allowlisted players, public car to everyone else
- Economy.buyCar + CarManager.spawn: server-side refuse RX-7 for non-allowlisted
- Cars: RX-7 flagged Restricted; client dealership hides it from non-owners
- Gates: stylua clean, selene 0/0, rojo builds
2026-07-21 23:39:59 -04:00
jesse 9a2f2d4dc9 Initial MVP: drivable RX-7 vertical slice + server-authoritative systems
CI / quality (push) Failing after 5m53s
- Rojo + Wally project; ProfileStore (loleris) for safe saves
- Shared: GameConfig, Cars (RX-7 free starter), ProfileTemplate, Remotes
- Server: DataManager, Economy, CarManager, RaceManager, MapBuilder, AntiCheat
- Client: neon HUD + Garage/Dealership UI (buy/equip/upgrade), race/daily
- Procedural Tokyo expressway (spawn pad, finish line, neon pylons, kill walls)
- CI workflow (Gitea/GitHub), Makefile, selene+stylua clean, rojo builds
- Docs: README, GDD, realistic solo ROADMAP
2026-07-21 23:30:53 -04:00