jesse f4f95ec9cc Daikoku PA: replace straight ramps with measured helix ramps
The PA on/off ramps were straight sloped decks running directly from the
ring gate to the mainline. Two measured problems:

  1. Grade. Straight ramps came out at 10.6% (entry) and 13.6% (exit).
     Japanese expressway ramps are held to roughly 6% maximum.
  2. Shape. The real Daikoku ramps are helixes -- they spiral down around
     a vertical axis. That is the interchange's single most recognisable
     feature and it was entirely absent.

Radii are measured, not chosen: an OSM Overpass pull of the interchange's
curved ways, each fitted with a Kasa circle fit. The two cleanest fits
(rms < 1.5 m, i.e. genuinely circular rather than merely curved) are
147 m and 124 m -> 525 and 443 studs at 3.571 studs/m.

Construction leaves the mainline tangentially (no step change in heading
at speed), wraps the circle while descending, then runs the tangent line
from circle to ring gate. Junction resolution now also captures the
mainline heading, which the tangential join requires.

Measured on the built geometry in Studio:

           segs   path            drop   grade   rotation
  entry     84    3775 studs      56     1.48%   344 deg
  exit      64    2866 studs      56     1.95%   282 deg

Grade drops 10.6% -> 1.48% and 13.6% -> 1.95%. Continuity is clean
(max Y step 0.99 / 1.31 studs across seams). Verified collision-free
against all mainline samples and the PA ring: closest approach to the
PA centre is 414 / 406 studs against PA_RADIUS 260.

Also adds red shoulder chevrons on the outside of each curve (72 parts),
which is what makes a helix legible from inside the car, and fixes the
kerb loop's merge-mouth test, which referenced the now-removed STEPS.
2026-08-03 03:11:06 -04:00

Tokyo Wangan Racing

A Roblox game where you cruise a neon Tokyo expressway at night in cool cars — starting with a real 1993 Mazda RX-7. The driving feel comes first; everything else layers on top of it. See docs/ROADMAP.md for what comes next.

Status: Playable. Spawn → drive → switch cars → respawn, plus the full three-mode Wangan loop. CI green on a self-hosted Gitea runner. Built code-first — nothing to hand-build in Studio.

The Daikoku loop (how you play)

Daikoku Futo PA is the hub, exactly like Tokyo Xtreme Racer. You are never "joining a match" — you park, pick how you want to run, and drive out.

        IN THE PA  ──►  pick a mode  ──►  cross the exit gate  ──►  RUNNING
             ▲                                                        │
             └──────────────── pull back into the PA ─────────────────┘
Mode 日本語 What it is
CRUISE 流し Free roam. Bank kilometres, meet other drivers. Rivals can pull alongside and challenge you.
DUEL バトル Hunt rivals. First to open a ~350-stud gap and hold it for 3s wins. No laps, no checkpoints — who breaks first.
TIME ATTACK タイムアタック Solo flying lap with 4 sector splits and a saved personal best. Rivals can't interrupt you.

Cruise and Duel both allow challenges, so a cruise can turn into a battle organically — pull alongside someone and the prompt appears for both of you. Time Attack deliberately opts out so a hot lap is never ruined.

Kilometres, lap times and duel records all persist via ProfileStore.


Prerequisites

Toolchain is managed by Rokit. With Rokit on your PATH:

rokit install     # rojo, wally, selene, stylua at pinned versions
wally install     # restores ProfileStore into ServerPackages/
Tool Purpose
rojo Sync/build code ↔ Roblox place
wally Package manager (ProfileStore)
selene Static analysis / linter
stylua Code formatter

Build & run

rojo build --output build.rbxl   # standalone place file to open in Studio
# OR live-sync into an open Studio place (install the Rojo Studio plugin):
rojo serve

In Studio press Play. You spawn on the expressway in your car. Bottom bar: CARS (switch car) and RESPAWN (re-spawn if you flip). The RX-7 only appears for allowlisted accounts.

Quality gates (CI enforces these on every push)

stylua --check src/     # formatting
selene src/             # lint
rojo build --output build.rbxl   # must compile

CI runs on a self-hosted Gitea Actions runner on UNRAID-1 (Ubuntu 24.04 job container — rojo's binary needs glibc 2.39). Workflow: .gitea/workflows/ci.yml.


Architecture (server-authoritative)

Clients request, the server decides. The RX-7 allowlist and anti-cheat are server-side.

ReplicatedStorage/Shared     GameConfig, Cars, ProfileTemplate, Remotes
ServerScriptService/Server   init.server + managers (below)
ServerScriptService/ServerPackages  ProfileStore (Wally)
StarterPlayerScripts/Client  init.client (HUD + car picker)
Module Responsibility
DataManager Wraps ProfileStore — session locking, reconcile, Studio mock. Remembers your last car.
CarManager Spawns the equipped car (VehicleSeat-driven placeholder) and enforces the RX-7 allowlist.
MapBuilder Procedurally builds the expressway, spawn pad, neon pylons, kill walls.
AntiCheat Movement sanity check (speed/teleport) — a speed bump, not a fortress.

The RX-7 demo-lock: GameConfig.RX7AllowedUserIds holds the owner's + son's Roblox UserIds; only they can select/drive the RX-7 (enforced in CarManager and the EquipCar remote).

Replacing the placeholder RX-7 with the real mesh

One function changes: CarManager.buildCarModel. Full step-by-step in docs/MESH_SWAP.md. Reference photos live on the NAS at unraid-1:/mnt/user/data/yy-roblox-games/0-tokyo-wangan-racing/001-1993 Mazda RX-7/.

S
Description
Tokyo Wangan Racing — Roblox street-racing sim. Cruise, duel, or time-attack the Wangan from Daikoku Futo PA. Rojo + Wally + ProfileStore.
Readme
12 MiB
Languages
Luau 92.7%
Python 7.1%
PowerShell 0.2%