# Roadmap — realistic solo-dev plan Assumes **one part-time developer learning as they go**. The MVP is intentionally tiny — *just driving* — so there's a fun, testable thing FAST. Everything else is layered on only after the driving feels good. > Expect **months, not weeks** to a polished full game. That's normal. This order > guarantees you always have something that runs. --- ## ✅ M0 — Drive-only MVP (DONE — this repo) Spawn on the neon expressway, drive a car, switch cars, respawn. RX-7 demo-locked to owner + son. Cars persist between sessions. CI green on a self-hosted runner. ## M1 — Make driving feel GOOD (the real work, do this next) - [x] Adopt a **constraint chassis** for real suspension/grip instead of the raw VehicleSeat: springs + prismatic suspension, servo steering (speed-sensitive lock), motor-driven wheels, engine braking, ballast anti-roll. Shared tuning in `src/shared/Chassis.luau`; client-side `ChassisController` drives it (driver owns network physics). **Needs a Studio playtest to tune feel.** - [ ] Import the **real RX-7 mesh**; weld the shell onto the chassis `Body`. See `docs/MESH_SWAP.md` for the exact steps (needs Studio for asset upload). - [ ] Tune acceleration curve and grip (after first playtest). - [x] **Chase camera**: scriptable follow cam while seated — damped chase with look-ahead, flat horizon (ignores car pitch/roll), speed-based FOV kick. `src/client/CameraController.luau`. Tune constants after playtest. - [x] Sound: two-layer engine (idle + rev loops crossfaded by speed — keeps engine character instead of chipmunking one loop) + tyre squeal on lateral slip / hard braking. `src/client/SoundController.luau` with per-car sound sets (`CAR_SOUNDS`). - [ ] **RX-7 rotary audio**: record the REAL car's 13B (owner has it + video), process into idle/rev loops on the workstation, upload, fill `CAR_SOUNDS`. Full pipeline: `docs/ROTARY_SOUND.md`. Generic loop is the stand-in. **Exit test:** the RX-7 is genuinely fun to just drive around. Ship nothing else until this is true. ## M2 — More cars + polish (still no racing) - [ ] Import a few more real car meshes. - [x] Better map v2: 3200-stud expressway with gantry arches, a neon-lit tunnel, jump ramps (right lane; left stays flat), end wall, and a procedural neon skyline flanking the route. - [x] Day/night, weather mood: `src/server/Ambience.luau` — Atmosphere haze catching the neon, bloom + cool color-correction post effects, and a slow 22:00→03:00 clock drift (10-min ping-pong) so the night sky breathes. ## M3 — Racing (the first "game" layer) - [ ] Checkpoints + timing (a new RaceManager — the old one was removed in M0). - [ ] Personal best times. - [ ] Simple point-to-point and drag modes. ## M4 — Progression & economy (only once racing is fun) - [ ] Money from races, a garage, buying/unlocking cars, upgrades, reputation. (These systems existed as scaffolding and were cut for the MVP; reintroduce them deliberately when they have a purpose.) ## M5 — Systems hardening & monetization - [ ] Leaderboards, anti-cheat pass 2, DataStore backup drill. - [ ] Performance pass (StreamingEnabled, part budget, mobile). - [ ] Fair gamepasses/products — never pay-to-win. ## M6 — Traffic AI (deferred hardest system) - [ ] Spline-following dummy cars first (cheap). True AI only if perf allows. --- ## Standing engineering rules - Every change must pass `stylua --check`, `selene`, and `rojo build` — CI on the self-hosted Gitea runner enforces all three on every push. - Keep the client dumb: it requests, the server decides. The RX-7 allowlist and anti-cheat live server-side. - Add tunables to `GameConfig`, not scattered magic numbers. - Add a save key by adding it to `ProfileTemplate` (auto-reconciles); never remove a key without a migration (bump `ProfileStoreName` `_vN` in dev to wipe). - Test in Studio after every server change (ProfileStore uses a mock store there).