jesse badba0f7a4 Fix support columns: cylinder axis transposition + floating ramp piers
Two structural bugs found by measuring built parts, not by eye.

1. PierColumn (pre-existing, all 80 instances). Enum.PartType.Cylinder
   puts the circular faces on the local X axis, so Size.X is the length
   ALONG the axis and Size.Y/Z are the diameter. The code passed
   Size = (8, colH, 8) and then rotated 90deg about Z -- building a disc
   8 studs long and colH wide. Measured: world vertical extent 8.0 studs
   for a column that should stand 35.4, leaving every viaduct pier
   floating with a 13.7-stud gap down to the ground. Only the Size
   components were transposed; the rotation was already right.
   After: extent 35.4, base Y=0.0.

2. PARampPillar. Two problems.
   a) Built as 6x6 square blocks. The underside footage (honmoku_jct
      sheet3 -- mislabeled, it is actually shot beneath Daikoku itself)
      shows every column carrying the ramp decks is a smooth cylindrical
      concrete pier. Now Cylinder, same axis convention as PierColumn.
   b) Height was always segMid.Y - (ringY - 1), cutting the column off
      at Y=45, the underside of the PA apron slab. Correct only while
      the ramp is over the slab; the measured helix climbs up to 1182
      studs beyond the slab edge, where nothing exists at Y=45. Base is
      now chosen per-pillar: apron level over the slab, ground (Y=-1)
      beyond it, matching the established viaduct Pillar convention.
      After: all bases at Y=-1, 0 pancakes, min height/width ratio 1.7.

Ramp geometry, chevron alignment and gore zebra all unchanged:
0 misaligned panels (worst 0.06/0.08 studs), 832 gore bars, merge
mouths 24.0/23.8 studs from the nearest bar.
2026-08-03 06:33:59 -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%