Files
tokyo-wangan-racing/src/server/MapBuilder.luau
T
Hermes 681c3462c6 Rename: Tokyo Wangan Racing (was Fast & Furious: Tokyo Expressway)
- Title in README + GDD, UI/log prefixes FnF -> Wangan
- Rojo project name -> TokyoWanganRacing
- Fix undefined `H` in CarManager seat CFrame (selene error) -> Chassis.BODY_SIZE.Y
2026-07-30 20:03:52 -04:00

708 lines
21 KiB
Luau

--!strict
--[[
MapBuilder.luau (SERVER)
v3 — "Shuto Night Loop": a Tokyo-expressway-inspired CIRCUIT, still built
100% from code. The straight strip is gone; the road is now a closed
rounded-rectangle loop (~7,400 studs/lap) modelled on the Shuto C1 vibe,
with real-Tokyo landmark zones:
SOUTH straight — Daikoku Futo PA: the legendary meet spot. A big
drivable parking area off the expressway with painted
bays, light towers, and the spawn pad. Cars spawn HERE.
EAST straight — Rainbow Bridge: white suspension towers, cross beams,
rainbow-lit rails. Odaiba sits beyond it: a blocky
Unicorn-Gundam-style statue + a giant neon ferris
wheel (Palette Town wheel).
NORTH straight — Yamate-style tunnel: long enclosed bore with strip
lights (the C1/Yamate underground feel).
WEST straight — City skyline run past a Tokyo Tower replica
(orange/white, twin decks, antenna).
Everywhere — procedural neon skyline inside and outside the loop,
Tatsumi-PA-style overlook pad (visual, NE).
NOT geographically accurate — it's a themed driving loop, not a map of
Tokyo. Gameplay parts keep their contract names (SpawnPad, FinishLine,
KillWall_*) so nothing else changes.
]]
local Workspace = game:GetService("Workspace")
local MapBuilder = {}
-- Loop geometry ----------------------------------------------------------------
local ROAD_WIDTH = 60
local HX = 1200 -- half-extent X
local HZ = 800 -- half-extent Z
local CORNER_R = 300
local STEP = 60 -- straight sample spacing
local ARC_STEPS = 12 -- samples per 90-degree corner
local WALL_HEIGHT = 26
local NEON_PINK = Color3.fromRGB(255, 40, 120)
local NEON_BLUE = Color3.fromRGB(40, 160, 255)
local NEON_TEAL = Color3.fromRGB(40, 230, 200)
local RAINBOW = {
Color3.fromRGB(255, 60, 60),
Color3.fromRGB(255, 160, 40),
Color3.fromRGB(250, 230, 60),
Color3.fromRGB(80, 230, 90),
Color3.fromRGB(60, 150, 255),
Color3.fromRGB(170, 90, 255),
}
local UP = Vector3.new(0, 1, 0)
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
-- Deterministic pseudo-random for scenery (same city every server) ------------
local function det(seed: number): number
local x = math.sin(seed * 12.9898) * 43758.5453
return x - math.floor(x)
end
-- Green highway sign with bilingual text ---------------------------------------
local function makeSign(text: string, cf: CFrame, parent: Instance)
local board = part({
Name = "Sign",
Size = Vector3.new(30, 9, 1),
CFrame = cf,
Color = Color3.fromRGB(18, 90, 60),
Material = Enum.Material.SmoothPlastic,
})
board.Parent = parent
local gui = Instance.new("SurfaceGui")
gui.Face = Enum.NormalId.Front
gui.CanvasSize = Vector2.new(600, 180)
gui.Parent = board
local label = Instance.new("TextLabel")
label.Size = UDim2.fromScale(1, 1)
label.BackgroundTransparency = 1
label.Font = Enum.Font.GothamBold
label.TextColor3 = Color3.new(1, 1, 1)
label.TextScaled = true
label.Text = text
label.Parent = gui
end
-- Centerline samples ------------------------------------------------------------
type Sample = { pos: Vector3, piece: string }
local function genSamples(): { Sample }
local samples: { Sample } = {}
local sx = HX - CORNER_R
local sz = HZ - CORNER_R
local function push(pos: Vector3, piece: string)
table.insert(samples, { pos = pos, piece = piece })
end
local function arc(cx: number, cz: number, a0: number, piece: string)
for i = 1, ARC_STEPS do
local a = a0 + (i / ARC_STEPS) * (math.pi / 2)
push(Vector3.new(cx + CORNER_R * math.sin(a), 0, cz + CORNER_R * math.cos(a)), piece)
end
end
-- South straight (Daikoku side), heading +X
local x = -sx
while x <= sx do
push(Vector3.new(x, 0, HZ), "south")
x += STEP
end
arc(sx, sz, 0, "corner_se")
-- East straight (Rainbow Bridge), heading -Z
local z = sz - STEP
while z >= -sz do
push(Vector3.new(HX, 0, z), "east")
z -= STEP
end
arc(sx, -sz, math.pi / 2, "corner_ne")
-- North straight (Yamate tunnel), heading -X
x = sx - STEP
while x >= -sx do
push(Vector3.new(x, 0, -HZ), "north")
x -= STEP
end
arc(-sx, -sz, math.pi, "corner_nw")
-- West straight (Tokyo Tower run), heading +Z
z = -sz + STEP
while z <= sz do
push(Vector3.new(-HX, 0, z), "west")
z += STEP
end
arc(-sx, sz, 3 * math.pi / 2, "corner_sw")
return samples
end
-- Daikoku PA entrance gap on the south straight's OUTER side -------------------
local DAIKOKU_GAP_HALF = 270
local function isDaikokuGap(mid: Vector3, piece: string, outer: boolean): boolean
return piece == "south" and outer and math.abs(mid.X) < DAIKOKU_GAP_HALF
end
-- The loop road itself ----------------------------------------------------------
local function buildLoop(map: Folder, samples: { Sample })
local roadFolder = Instance.new("Folder")
roadFolder.Name = "Expressway"
roadFolder.Parent = map
local n = #samples
for i = 1, n do
local a = samples[i]
local b = samples[(i % n) + 1]
local delta = b.pos - a.pos
local len = delta.Magnitude + 2
local mid = (a.pos + b.pos) / 2
local dir = delta.Unit
local right = dir:Cross(UP) -- always points OUTWARD on this loop
local cf = CFrame.lookAt(mid, mid + dir)
local road = part({
Name = "Road_" .. i,
Size = Vector3.new(ROAD_WIDTH, 2, len),
CFrame = cf,
Color = Color3.fromRGB(28, 28, 34),
Material = Enum.Material.Asphalt,
})
road.Parent = roadFolder
local line = part({
Name = "Lane_" .. i,
Size = Vector3.new(1, 2.1, len),
CFrame = cf * CFrame.new(0, 0.1, 0),
Color = Color3.fromRGB(230, 200, 60),
Material = Enum.Material.Neon,
})
line.Parent = roadFolder
local inTunnel = a.piece == "north"
for _, side in ipairs({ -1, 1 }) do
local outer = side == 1
if isDaikokuGap(mid, a.piece, outer) then
continue
end
local off = right * (side * (ROAD_WIDTH / 2))
local rail = part({
Name = "Guardrail",
Size = Vector3.new(1.5, 4, len),
CFrame = CFrame.lookAt(mid + off, mid + off + dir) * CFrame.new(0, 2, 0),
Color = Color3.fromRGB(180, 180, 190),
Material = Enum.Material.Metal,
})
rail.Parent = map
local woff = right * (side * (ROAD_WIDTH / 2 + 2))
local wall = part({
Name = "KillWall",
Size = Vector3.new(2, WALL_HEIGHT, len + 6),
CFrame = CFrame.lookAt(mid + woff, mid + woff + dir) * CFrame.new(0, WALL_HEIGHT / 2, 0),
Transparency = 1,
CanCollide = true,
})
wall.Parent = map
-- Rainbow rail lights on the bridge; neon pylons elsewhere (not in tunnel)
if a.piece == "east" then
local lamp = part({
Name = "BridgeLight",
Size = Vector3.new(1.2, 1.2, 1.2),
CFrame = CFrame.new(mid + off + Vector3.new(0, 4.6, 0)),
Color = RAINBOW[(i % #RAINBOW) + 1],
Material = Enum.Material.Neon,
})
lamp.Parent = map
elseif not inTunnel and i % 3 == 0 then
local pylon = part({
Name = "Pylon",
Size = Vector3.new(1, 14, 1),
CFrame = CFrame.new(mid + right * (side * (ROAD_WIDTH / 2 + 3)) + Vector3.new(0, 7, 0)),
Color = outer and NEON_PINK or NEON_BLUE,
Material = Enum.Material.Neon,
})
pylon.Parent = map
end
end
-- Yamate tunnel bore over the north straight -----------------------------
if inTunnel then
local h = 22
for _, side in ipairs({ -1, 1 }) do
local woff = right * (side * (ROAD_WIDTH / 2 + 1.5))
local wallT = part({
Name = "TunnelWall",
Size = Vector3.new(3, h, len + 2),
CFrame = CFrame.lookAt(mid + woff, mid + woff + dir) * CFrame.new(0, h / 2, 0),
Color = Color3.fromRGB(38, 38, 46),
Material = Enum.Material.Concrete,
})
wallT.Parent = map
end
local ceiling = part({
Name = "TunnelCeiling",
Size = Vector3.new(ROAD_WIDTH + 6, 2, len + 2),
CFrame = cf * CFrame.new(0, h + 1, 0),
Color = Color3.fromRGB(30, 30, 38),
Material = Enum.Material.Concrete,
})
ceiling.Parent = map
if i % 2 == 0 then
local strip = part({
Name = "TunnelLight",
Size = Vector3.new(ROAD_WIDTH * 0.5, 0.6, 2),
CFrame = cf * CFrame.new(0, h - 0.5, 0),
Color = i % 4 == 0 and NEON_BLUE or NEON_TEAL,
Material = Enum.Material.Neon,
})
strip.Parent = map
end
end
end
end
-- Daikoku Futo PA ----------------------------------------------------------------
local function buildDaikoku(map: Folder)
local folder = Instance.new("Folder")
folder.Name = "DaikokuPA"
folder.Parent = map
local z0 = HZ + ROAD_WIDTH / 2 -- pad starts at the road's outer edge
local depth = 220
local halfW = 260
local pad = part({
Name = "DaikokuPad",
Size = Vector3.new(halfW * 2, 2, depth),
CFrame = CFrame.new(0, 0, z0 + depth / 2),
Color = Color3.fromRGB(34, 34, 40),
Material = Enum.Material.Asphalt,
})
pad.Parent = folder
-- Painted parking bays (two rows, like the real lot's herringbone rows)
for row = 0, 1 do
local zRow = z0 + 70 + row * 90
for bx = -5, 5 do
local lineP = part({
Name = "BayLine",
Size = Vector3.new(1, 2.1, 22),
CFrame = CFrame.new(bx * 42, 0.1, zRow),
Color = Color3.fromRGB(230, 230, 235),
Material = Enum.Material.SmoothPlastic,
})
lineP.Parent = folder
end
end
-- Light towers (the tall lot floods) + perimeter kill walls
for _, corner in ipairs({
{ -halfW + 20, z0 + 30 },
{ halfW - 20, z0 + 30 },
{ -halfW + 20, z0 + depth - 20 },
{ halfW - 20, z0 + depth - 20 },
}) do
local px, pz = corner[1], corner[2]
local pole = part({
Name = "LightPole",
Size = Vector3.new(2, 34, 2),
CFrame = CFrame.new(px, 17, pz),
Color = Color3.fromRGB(120, 120, 130),
Material = Enum.Material.Metal,
})
pole.Parent = folder
local head = part({
Name = "LightHead",
Size = Vector3.new(8, 1.5, 8),
CFrame = CFrame.new(px, 34.5, pz),
Color = Color3.fromRGB(255, 240, 200),
Material = Enum.Material.Neon,
})
head.Parent = folder
end
-- Perimeter walls (invisible) on the three non-road sides
local wallDefs = {
{ Vector3.new(halfW * 2 + 4, WALL_HEIGHT, 2), CFrame.new(0, WALL_HEIGHT / 2, z0 + depth + 1) },
{ Vector3.new(2, WALL_HEIGHT, depth + 4), CFrame.new(-halfW - 1, WALL_HEIGHT / 2, z0 + depth / 2) },
{ Vector3.new(2, WALL_HEIGHT, depth + 4), CFrame.new(halfW + 1, WALL_HEIGHT / 2, z0 + depth / 2) },
}
for _, def in ipairs(wallDefs) do
local w = part({
Name = "KillWall_PA",
Size = def[1],
CFrame = def[2],
Transparency = 1,
CanCollide = true,
})
w.Parent = folder
end
-- Spawn pad (cars appear here — Daikoku is the meet) -----------------------
-- Subtle painted zone, NOT neon: the cars are the stars of the meet, the
-- floor must never outshine them.
local spawn = part({
Name = "SpawnPad",
Size = Vector3.new(120, 1, 60),
CFrame = CFrame.new(0, 1.2, z0 + 130),
Color = Color3.fromRGB(45, 60, 55),
Material = Enum.Material.Asphalt,
Transparency = 0,
})
spawn.Parent = folder
makeSign("大黒PA DAIKOKU PA", CFrame.new(0, 12, z0 + 4) * CFrame.Angles(0, math.pi, 0), folder)
end
-- Rainbow Bridge towers over the east straight -----------------------------------
local function buildRainbowBridge(map: Folder)
local folder = Instance.new("Folder")
folder.Name = "RainbowBridge"
folder.Parent = map
for _, tz in ipairs({ 250, -250 }) do
for _, side in ipairs({ -1, 1 }) do
local tx = HX + side * (ROAD_WIDTH / 2 + 5)
local tower = part({
Name = "BridgeTower",
Size = Vector3.new(6, 95, 6),
CFrame = CFrame.new(tx, 47.5, tz),
Color = Color3.fromRGB(235, 235, 240),
Material = Enum.Material.Concrete,
})
tower.Parent = folder
local beacon = part({
Name = "TowerBeacon",
Size = Vector3.new(2, 2, 2),
CFrame = CFrame.new(tx, 96, tz),
Color = Color3.fromRGB(255, 80, 80),
Material = Enum.Material.Neon,
})
beacon.Parent = folder
end
local beam = part({
Name = "TowerBeam",
Size = Vector3.new(ROAD_WIDTH + 22, 4, 5),
CFrame = CFrame.new(HX, 62, tz),
Color = Color3.fromRGB(235, 235, 240),
Material = Enum.Material.Concrete,
})
beam.Parent = folder
end
makeSign(
"レインボーブリッジ RAINBOW BRIDGE",
CFrame.new(HX, 14, 330) * CFrame.Angles(0, math.pi / 2, 0),
folder
)
end
-- Odaiba: blocky Unicorn-Gundam-style statue + giant ferris wheel ----------------
local function buildOdaiba(map: Folder)
local folder = Instance.new("Folder")
folder.Name = "Odaiba"
folder.Parent = map
local gx, gz = HX + 150, 480 -- statue stands beyond the bridge's south end
local white = Color3.fromRGB(235, 235, 240)
local function block(name: string, size: Vector3, cf: CFrame, color: Color3, mat: Enum.Material?)
local b = part({
Name = name,
Size = size,
CFrame = cf,
Color = color,
Material = mat or Enum.Material.SmoothPlastic,
})
b.Parent = folder
return b
end
-- Base plinth
block(
"GundamBase",
Vector3.new(40, 4, 40),
CFrame.new(gx, 2, gz),
Color3.fromRGB(60, 60, 70),
Enum.Material.Concrete
)
-- Legs
block("GundamLegL", Vector3.new(7, 20, 9), CFrame.new(gx - 6, 14, gz), white)
block("GundamLegR", Vector3.new(7, 20, 9), CFrame.new(gx + 6, 14, gz), white)
-- Hips + torso
block("GundamHips", Vector3.new(16, 6, 10), CFrame.new(gx, 27, gz), white)
block("GundamTorso", Vector3.new(15, 14, 10), CFrame.new(gx, 37, gz), white)
block("GundamChest", Vector3.new(9, 5, 3), CFrame.new(gx, 39, gz - 6), Color3.fromRGB(60, 90, 220))
block("GundamCore", Vector3.new(4, 3, 2), CFrame.new(gx, 34, gz - 6), Color3.fromRGB(230, 60, 60))
-- Shoulders + arms
block("GundamShoulderL", Vector3.new(6, 5, 7), CFrame.new(gx - 11, 42, gz), white)
block("GundamShoulderR", Vector3.new(6, 5, 7), CFrame.new(gx + 11, 42, gz), white)
block("GundamArmL", Vector3.new(4.5, 16, 5), CFrame.new(gx - 11, 32, gz), white)
block("GundamArmR", Vector3.new(4.5, 16, 5), CFrame.new(gx + 11, 32, gz), white)
-- Head with glowing eyes + unicorn horn
block("GundamHead", Vector3.new(6, 5.5, 5.5), CFrame.new(gx, 47, gz), white)
block("GundamEyes", Vector3.new(4, 1, 0.6), CFrame.new(gx, 47.5, gz - 2.8), NEON_TEAL, Enum.Material.Neon)
block(
"GundamHorn",
Vector3.new(0.8, 6, 0.8),
CFrame.new(gx, 53, gz - 1) * CFrame.Angles(math.rad(15), 0, 0),
Color3.fromRGB(250, 220, 90),
Enum.Material.Neon
)
-- Psycho-frame glow strips on the legs/torso (the Unicorn's pink frame)
block("GundamFrameL", Vector3.new(1, 14, 1), CFrame.new(gx - 6, 14, gz - 4.6), NEON_PINK, Enum.Material.Neon)
block("GundamFrameR", Vector3.new(1, 14, 1), CFrame.new(gx + 6, 14, gz - 4.6), NEON_PINK, Enum.Material.Neon)
-- Giant ferris wheel (Palette Town) -----------------------------------------
local wx, wz = HX + 240, 120
local radius = 55
local hub = CFrame.new(wx, radius + 24, wz)
block(
"WheelSupportL",
Vector3.new(4, radius + 26, 4),
CFrame.new(wx - 18, (radius + 24) / 2, wz) * CFrame.Angles(0, 0, math.rad(-14)),
Color3.fromRGB(120, 120, 130),
Enum.Material.Metal
)
block(
"WheelSupportR",
Vector3.new(4, radius + 26, 4),
CFrame.new(wx + 18, (radius + 24) / 2, wz) * CFrame.Angles(0, 0, math.rad(14)),
Color3.fromRGB(120, 120, 130),
Enum.Material.Metal
)
block("WheelHub", Vector3.new(6, 6, 6), hub, Color3.fromRGB(200, 200, 210), Enum.Material.Metal)
for k = 1, 16 do
local ang = (k / 16) * math.pi * 2
local cab = part({
Name = "WheelCabin",
Size = Vector3.new(4, 4, 4),
Shape = Enum.PartType.Ball,
CFrame = hub * CFrame.new(math.cos(ang) * radius, math.sin(ang) * radius, 0),
Color = RAINBOW[(k % #RAINBOW) + 1],
Material = Enum.Material.Neon,
})
cab.Parent = folder
if k % 2 == 0 then
local spoke = part({
Name = "WheelSpoke",
Size = Vector3.new(0.8, radius, 0.8),
CFrame = hub * CFrame.Angles(0, 0, ang) * CFrame.new(0, radius / 2, 0),
Color = Color3.fromRGB(150, 150, 160),
Material = Enum.Material.Metal,
})
spoke.Parent = folder
end
end
makeSign("お台場 ODAIBA", CFrame.new(HX + 60, 12, 300) * CFrame.Angles(0, math.pi / 2, 0), folder)
end
-- Tokyo Tower replica on the west side --------------------------------------------
local function buildTokyoTower(map: Folder)
local folder = Instance.new("Folder")
folder.Name = "TokyoTower"
folder.Parent = map
local tx, tz = -HX - 220, 0
local orange = Color3.fromRGB(235, 100, 40)
local levels = {
{ w = 64, h = 50, c = orange },
{ w = 44, h = 45, c = Color3.fromRGB(240, 240, 245) },
{ w = 28, h = 45, c = orange },
{ w = 15, h = 40, c = Color3.fromRGB(240, 240, 245) },
}
local y = 0
for li, lv in ipairs(levels) do
local sec = part({
Name = "TowerSection" .. li,
Size = Vector3.new(lv.w, lv.h, lv.w),
CFrame = CFrame.new(tx, y + lv.h / 2, tz),
Color = lv.c,
Material = Enum.Material.Metal,
})
sec.Parent = folder
y += lv.h
end
-- Observation decks + antenna
local deck1 = part({
Name = "MainDeck",
Size = Vector3.new(36, 8, 36),
CFrame = CFrame.new(tx, 98, tz),
Color = Color3.fromRGB(250, 245, 235),
Material = Enum.Material.Neon,
})
deck1.Parent = folder
local deck2 = part({
Name = "TopDeck",
Size = Vector3.new(20, 6, 20),
CFrame = CFrame.new(tx, 152, tz),
Color = Color3.fromRGB(250, 245, 235),
Material = Enum.Material.Neon,
})
deck2.Parent = folder
local antenna = part({
Name = "Antenna",
Size = Vector3.new(2, 40, 2),
CFrame = CFrame.new(tx, 200, tz),
Color = orange,
Material = Enum.Material.Neon,
})
antenna.Parent = folder
end
-- Tatsumi-style overlook pad (visual scenery, NE corner outside) ------------------
local function buildTatsumi(map: Folder)
local folder = Instance.new("Folder")
folder.Name = "TatsumiPA"
folder.Parent = map
local px, pz = HX - 380, -HZ - 120
local pad = part({
Name = "TatsumiPad",
Size = Vector3.new(160, 2, 80),
CFrame = CFrame.new(px, 0, pz),
Color = Color3.fromRGB(34, 34, 40),
Material = Enum.Material.Asphalt,
})
pad.Parent = folder
for i = 0, 4 do
local lamp = part({
Name = "TatsumiLamp",
Size = Vector3.new(1, 12, 1),
CFrame = CFrame.new(px - 70 + i * 35, 6, pz - 30),
Color = Color3.fromRGB(255, 240, 200),
Material = Enum.Material.Neon,
})
lamp.Parent = folder
end
makeSign("辰巳PA TATSUMI PA", CFrame.new(px, 11, pz + 30), folder)
end
-- Neon skyline: towers inside the loop (city core) and outside ---------------------
local function buildSkyline(map: Folder)
local folder = Instance.new("Folder")
folder.Name = "Skyline"
folder.Parent = map
local accents = { NEON_PINK, NEON_BLUE, NEON_TEAL, Color3.fromRGB(200, 120, 255) }
local function tower(seed: number, x: number, z: number)
local width = 40 + det(seed) * 50
local depth = 40 + det(seed + 1) * 50
local height = 50 + det(seed + 2) * 170
local t = part({
Name = "Tower",
Size = Vector3.new(width, height, depth),
CFrame = CFrame.new(x, height / 2 - 10, z),
Color = Color3.fromRGB(16, 16, 24),
Material = Enum.Material.Slate,
})
t.Parent = folder
local accent = accents[(math.floor(seed) % #accents) + 1]
local band = part({
Name = "TowerBand",
Size = Vector3.new(width + 0.4, 2 + det(seed + 5) * 4, depth + 0.4),
CFrame = CFrame.new(x, height * (0.35 + det(seed + 6) * 0.4), z),
Color = accent,
Material = Enum.Material.Neon,
Transparency = 0.2,
})
band.Parent = folder
local roof = part({
Name = "TowerRoof",
Size = Vector3.new(width * 0.3, 1.5, depth * 0.3),
CFrame = CFrame.new(x, height - 9, z),
Color = accent,
Material = Enum.Material.Neon,
})
roof.Parent = folder
end
-- City core inside the loop
local seed = 1
for gx = -2, 2 do
for gz = -1, 1 do
seed += 7
local x = gx * 300 + (det(seed) - 0.5) * 120
local z = gz * 300 + (det(seed + 3) - 0.5) * 120
tower(seed, x, z)
end
end
-- Outer ring (skip landmark zones: Odaiba east, Tokyo Tower west-center,
-- Daikoku south-center)
for i = 1, 26 do
seed += 11
local ang = (i / 26) * math.pi * 2
local rad = 1750 + det(seed + 4) * 350
local x = math.cos(ang) * rad
local z = math.sin(ang) * rad * 0.75
local skip = (x > HX and math.abs(z) < 620) -- Odaiba
or (x < -HX and math.abs(z) < 260) -- Tokyo Tower
or (z > HZ and math.abs(x) < 420) -- Daikoku
if not skip then
tower(seed, x, z)
end
end
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 samples = genSamples()
buildLoop(map, samples)
buildDaikoku(map)
buildRainbowBridge(map)
buildOdaiba(map)
buildTokyoTower(map)
buildTatsumi(map)
buildSkyline(map)
-- Finish line across the south straight just past the Daikoku exit --------
local finish = part({
Name = "FinishLine",
Size = Vector3.new(ROAD_WIDTH, 1, 6),
CFrame = CFrame.new(420, 1.5, HZ),
Color = Color3.fromRGB(240, 240, 240),
Material = Enum.Material.Neon,
Transparency = 0.3,
})
finish.Parent = map
-- Safety net floor under everything ----------------------------------------
local floor = part({
Name = "SafetyFloor",
Size = Vector3.new((HX + 700) * 2, 2, (HZ + 700) * 2),
CFrame = CFrame.new(0, -60, 0),
Transparency = 1,
CanCollide = true,
})
floor.Parent = map
-- Ground plane far below road level (the "bay" the expressway floats over)
local ground = part({
Name = "Ground",
Size = Vector3.new((HX + 700) * 2, 2, (HZ + 700) * 2),
CFrame = CFrame.new(0, -12, 0),
Color = Color3.fromRGB(10, 12, 20),
Material = Enum.Material.Slate,
})
ground.Parent = map
map.Parent = Workspace
return map
end
return MapBuilder