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
This commit is contained in:
2026-07-21 23:30:53 -04:00
commit 9a2f2d4dc9
24 changed files with 1986 additions and 0 deletions
+142
View File
@@ -0,0 +1,142 @@
--!strict
--[[
MapBuilder.luau (SERVER)
Builds the MVP "Tokyo expressway" vertical slice entirely from code so the
game is playable with ZERO manual Studio building. This is a straight,
banked-guardrail highway segment with a start pad, a finish line, neon-ish
side pylons, and invisible kill walls so you can't drive off the edge.
Later you replace this with a proper modeled map; the rest of the game
(spawns, races) reads named parts so it keeps working.
]]
local Workspace = game:GetService("Workspace")
local MapBuilder = {}
local ROAD_WIDTH = 60
local SEGMENT_LENGTH = 400
local NUM_SEGMENTS = 6 -- total length = 2400 studs of highway
local WALL_HEIGHT = 20
local function part(props: { [string]: any }): Part
local p = Instance.new("Part")
p.Anchored = true
p.TopSurface = Enum.SurfaceType.Smooth
p.BottomSurface = Enum.SurfaceType.Smooth
for k, v in pairs(props) do
(p :: any)[k] = v
end
return p
end
function MapBuilder.build(): Folder
local existing = Workspace:FindFirstChild("Map")
if existing then
existing:Destroy()
end
local map = Instance.new("Folder")
map.Name = "Map"
local roadFolder = Instance.new("Folder")
roadFolder.Name = "Expressway"
roadFolder.Parent = map
local totalLength = SEGMENT_LENGTH * NUM_SEGMENTS
-- Road deck (segmented so you can later bank/curve individual pieces) ------
for i = 0, NUM_SEGMENTS - 1 do
local z = -(i * SEGMENT_LENGTH) - SEGMENT_LENGTH / 2
local road = part({
Name = "Road_" .. i,
Size = Vector3.new(ROAD_WIDTH, 2, SEGMENT_LENGTH),
Position = Vector3.new(0, 0, z),
Color = Color3.fromRGB(28, 28, 34),
Material = Enum.Material.Asphalt,
})
road.Parent = roadFolder
-- Center lane line
local line = part({
Name = "Lane_" .. i,
Size = Vector3.new(1, 2.1, SEGMENT_LENGTH),
Position = Vector3.new(0, 0.1, z),
Color = Color3.fromRGB(230, 200, 60),
Material = Enum.Material.Neon,
})
line.Parent = roadFolder
end
-- Guardrails + invisible kill walls on both sides -------------------------
for _, side in ipairs({ -1, 1 }) do
local x = side * (ROAD_WIDTH / 2)
local rail = part({
Name = "Guardrail_" .. (side == -1 and "L" or "R"),
Size = Vector3.new(1.5, 4, totalLength),
Position = Vector3.new(x, 2, -totalLength / 2),
Color = Color3.fromRGB(180, 180, 190),
Material = Enum.Material.Metal,
})
rail.Parent = map
-- Invisible wall: solid, tall, non-rendered — the "can't leave" barrier.
local wall = part({
Name = "KillWall_" .. (side == -1 and "L" or "R"),
Size = Vector3.new(2, WALL_HEIGHT, totalLength),
Position = Vector3.new(x + side * 2, WALL_HEIGHT / 2, -totalLength / 2),
Transparency = 1,
CanCollide = true,
})
wall.Parent = map
-- Neon pylons for that cyberpunk Tokyo glow (cheap: one every 200 studs)
for i = 0, NUM_SEGMENTS * 2 do
local pylon = part({
Name = "Pylon",
Size = Vector3.new(1, 14, 1),
Position = Vector3.new(x + side * 3, 7, -(i * 200)),
Color = side == -1 and Color3.fromRGB(255, 40, 120) or Color3.fromRGB(40, 160, 255),
Material = Enum.Material.Neon,
})
pylon.Parent = map
end
end
-- Spawn pad (where cars appear) at the start ------------------------------
local pad = part({
Name = "SpawnPad",
Size = Vector3.new(ROAD_WIDTH - 6, 1, 40),
Position = Vector3.new(0, 1.5, -20),
Color = Color3.fromRGB(20, 220, 120),
Material = Enum.Material.Neon,
Transparency = 0.4,
})
pad.Parent = map
-- Finish line at the far end ----------------------------------------------
local finish = part({
Name = "FinishLine",
Size = Vector3.new(ROAD_WIDTH, 1, 6),
Position = Vector3.new(0, 1.5, -totalLength + 30),
Color = Color3.fromRGB(240, 240, 240),
Material = Enum.Material.Neon,
Transparency = 0.3,
})
finish.Parent = map
-- A floor far below to catch anything that clips through (safety net) ------
local floor = part({
Name = "SafetyFloor",
Size = Vector3.new(ROAD_WIDTH * 4, 2, totalLength + 400),
Position = Vector3.new(0, -60, -totalLength / 2),
Transparency = 1,
CanCollide = true,
})
floor.Parent = map
map.Parent = Workspace
return map
end
return MapBuilder