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
This commit is contained in:
2026-07-22 00:11:11 -04:00
parent 5fc03d611d
commit 07a67204ca
14 changed files with 347 additions and 781 deletions
+12 -30
View File
@@ -1,13 +1,11 @@
--!strict
--[[
Cars.luau
The car catalogue. Table-driven so adding a car = adding a row.
MVP ships with the RX-7 starter + a few tier examples so the dealership
and progression have something to show. Expand freely later.
The car catalogue. MVP scope (just driving): a car is an identity + driving
feel + look. No prices, no rep gates, no upgrades. Add a car = add a row.
Stat scale: 0-100 (relative feel, not real units). Speed maps to top speed,
Acceleration to how fast it gets there, Handling to grip/turn-in.
Price is in cash. RepRequired gates purchase behind reputation.
Stat scale 0-100 (relative feel): Speed = top speed, Acceleration = how fast
it gets there, Handling = grip/turn-in. These drive the VehicleSeat tuning.
]]
export type CarStats = {
@@ -20,31 +18,24 @@ export type Car = {
Id: string,
Name: string,
Model: string, -- real-world reference
Tier: number, -- 1 Junk .. 5 Exotic
Price: number,
RepRequired: number,
Tier: number, -- 1 Junk .. 5 Exotic (display/flavour only in MVP)
Stats: CarStats,
Color: { number }, -- {r,g,b} 0-1 for the placeholder body until real mesh exists
Color: { number }, -- {r,g,b} 0-1 for the placeholder body until a real mesh exists
Description: string,
Starter: boolean?, -- true = granted free on first join
Restricted: boolean?, -- true = allowlist-only; hidden from dealership for others
Restricted: boolean?, -- true = allowlist-only (the RX-7 demo lock)
}
local Cars = {}
-- Ordered list (dealership browses this in order) ---------------------------
Cars.List = {
{
Id = "rx7_fc",
Name = "Chick3n's RX-7",
Model = "1993 Mazda RX-7 (FD)",
Tier = 2,
Price = 0,
RepRequired = 0,
Stats = { Speed = 62, Acceleration = 58, Handling = 70 },
Color = { 0.85, 0.15, 0.12 }, -- classic RX-7 red until the real mesh is imported
Description = "The one that started it all. A rotary-hearted FD RX-7 — light, balanced, and iconic. Your daily driver and first weapon on the expressway.",
Starter = true,
Description = "The one that started it all. A rotary-hearted FD RX-7 — light, balanced, iconic.",
Restricted = true, -- demo-locked to the owner + son during testing
},
{
@@ -52,48 +43,39 @@ Cars.List = {
Name = "City Runabout",
Model = "90s econobox hatchback",
Tier = 1,
Price = 800,
RepRequired = 0,
Stats = { Speed = 34, Acceleration = 40, Handling = 48 },
Color = { 0.5, 0.5, 0.55 },
Description = "Cheap, cheerful, and slow. A backup beater for when you want to grind pocket change.",
Description = "Cheap, cheerful, and slow. The public default cruiser.",
},
{
Id = "silv_s15",
Name = "Night Slider",
Model = "Nissan Silvia S15",
Tier = 3,
Price = 12000,
RepRequired = 50,
Stats = { Speed = 74, Acceleration = 70, Handling = 78 },
Color = { 0.1, 0.35, 0.85 },
Description = "A drift-bred coupe with serious mid-corner poise. The natural step up from the RX-7.",
Description = "A drift-bred coupe with serious mid-corner poise.",
},
{
Id = "gtr_r34",
Name = "Godzilla",
Model = "Nissan Skyline GT-R R34",
Tier = 4,
Price = 45000,
RepRequired = 180,
Stats = { Speed = 88, Acceleration = 86, Handling = 82 },
Color = { 0.15, 0.6, 0.95 },
Description = "AWD, twin-turbo, legendary. When you show up in this, people notice.",
Description = "AWD, twin-turbo, legendary. People notice when you show up in this.",
},
{
Id = "hyper_x",
Name = "Apex Phantom",
Model = "Exotic hypercar (stylized)",
Tier = 5,
Price = 250000,
RepRequired = 600,
Stats = { Speed = 100, Acceleration = 98, Handling = 90 },
Color = { 0.05, 0.05, 0.06 },
Description = "Endgame flex. Millions of yen of carbon fibre and neon. The top of the food chain.",
Description = "Top of the food chain. Carbon fibre and neon.",
},
}
-- Fast lookup by Id (built once) --------------------------------------------
Cars.ById = {} :: { [string]: Car }
for _, car in ipairs(Cars.List) do
Cars.ById[car.Id] = car