Map v3: Shuto Night Loop — Tokyo landmark circuit
CI / quality (push) Successful in 55s

The straight strip becomes a closed rounded-rect loop (~7,400 studs/lap)
built from centerline samples, Shuto-C1 style. Landmark zones:

- Daikoku Futo PA: drivable meet lot off the south straight (guardrail
  gap entrance), painted bays, flood-light towers, bilingual sign —
  cars now SPAWN at Daikoku like a proper meet
- Rainbow Bridge over the east straight: white suspension towers with
  beacons, cross beams, rainbow-colored rail lights
- Odaiba beyond the bridge: blocky Unicorn Gundam (glowing eyes, horn,
  pink psycho-frame strips) + 16-cabin neon ferris wheel
- Yamate-style tunnel enclosing the whole north straight
- Tokyo Tower replica (orange/white tiers, two lit decks, antenna) west
- Tatsumi PA overlook pad NE
- City-core skyline inside the loop + outer ring skipping landmark zones
- Bilingual green highway signs via SurfaceGui (JP + EN)

Gameplay contract preserved: SpawnPad/FinishLine/KillWall names intact,
kill walls hug every road edge except the Daikoku entrance.
This commit is contained in:
2026-07-22 02:38:47 -04:00
parent dae30fd22e
commit 0fc0d0ae22
2 changed files with 584 additions and 222 deletions
+10 -3
View File
@@ -37,9 +37,16 @@ until this is true.
## M2 — More cars + polish (still no racing) ## M2 — More cars + polish (still no racing)
- [ ] Import a few more real car meshes. - [ ] Import a few more real car meshes.
- [x] Better map v2: 3200-stud expressway with gantry arches, a neon-lit - [x] Better map v3 — **"Shuto Night Loop"**: closed ~7,400-stud circuit
tunnel, jump ramps (right lane; left stays flat), end wall, and a inspired by Tokyo's Shuto expressway, with real-Tokyo landmark zones:
procedural neon skyline flanking the route. **Daikoku Futo PA** (drivable meet lot + painted bays + light towers —
cars spawn here), **Rainbow Bridge** (suspension towers, rainbow rail
lights), **Odaiba** beyond it (blocky Unicorn Gundam statue with glowing
psycho-frame + giant neon ferris wheel), **Yamate-style tunnel** (north
straight), **Tokyo Tower** replica (west), **Tatsumi PA** overlook,
bilingual green highway signs (大黒PA, レインボーブリッジ, お台場, 辰巳PA),
city-core + outer-ring procedural skyline. Not geographically accurate —
a themed loop, not a map of Tokyo.
- [x] Day/night, weather mood: `src/server/Ambience.luau` — Atmosphere haze - [x] Day/night, weather mood: `src/server/Ambience.luau` — Atmosphere haze
catching the neon, bloom + cool color-correction post effects, and a slow catching the neon, bloom + cool color-correction post effects, and a slow
22:00→03:00 clock drift (10-min ping-pong) so the night sky breathes. 22:00→03:00 clock drift (10-min ping-pong) so the night sky breathes.
+574 -219
View File
@@ -1,36 +1,56 @@
--!strict --!strict
--[[ --[[
MapBuilder.luau (SERVER) MapBuilder.luau (SERVER)
Builds the "Tokyo expressway" map entirely from code — ZERO manual Studio v3 — "Shuto Night Loop": a Tokyo-expressway-inspired CIRCUIT, still built
building. v2 (M2 groundwork): the straight highway now runs through a 100% from code. The straight strip is gone; the road is now a closed
sequence of FEATURES so driving it is actually interesting: rounded-rectangle loop (~7,400 studs/lap) modelled on the Shuto C1 vibe,
with real-Tokyo landmark zones:
seg 0-1 open start (spawn pad) SOUTH straight — Daikoku Futo PA: the legendary meet spot. A big
seg 2 overhead gantry arches drivable parking area off the expressway with painted
seg 3 TUNNEL (enclosed, neon-striped ceiling) bays, light towers, and the spawn pad. Cars spawn HERE.
seg 4 jump ramps (side-by-side launch + landing, optional — road EAST straight — Rainbow Bridge: white suspension towers, cross beams,
continues flat around them) rainbow-lit rails. Odaiba sits beyond it: a blocky
seg 5-6 open run to the finish line Unicorn-Gundam-style statue + a giant neon ferris
seg 7 finish + runoff 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).
Neon skyline blocks flank the whole route outside the guardrails for the NOT geographically accurate — it's a themed driving loop, not a map of
night-city mood. Everything is still named parts (SpawnPad, FinishLine, Tokyo. Gameplay parts keep their contract names (SpawnPad, FinishLine,
KillWall_*) so gameplay code keeps working when this is replaced by a KillWall_*) so nothing else changes.
modeled map later.
]] ]]
local Workspace = game:GetService("Workspace") local Workspace = game:GetService("Workspace")
local MapBuilder = {} local MapBuilder = {}
-- Loop geometry ----------------------------------------------------------------
local ROAD_WIDTH = 60 local ROAD_WIDTH = 60
local SEGMENT_LENGTH = 400 local HX = 1200 -- half-extent X
local NUM_SEGMENTS = 8 -- total length = 3200 studs of highway 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 WALL_HEIGHT = 26
local NEON_PINK = Color3.fromRGB(255, 40, 120) local NEON_PINK = Color3.fromRGB(255, 40, 120)
local NEON_BLUE = Color3.fromRGB(40, 160, 255) local NEON_BLUE = Color3.fromRGB(40, 160, 255)
local NEON_TEAL = Color3.fromRGB(40, 230, 200) 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 function part(props: { [string]: any }): Part
local p = Instance.new("Part") local p = Instance.new("Part")
@@ -49,232 +69,582 @@ local function det(seed: number): number
return x - math.floor(x) return x - math.floor(x)
end end
-- Road deck ------------------------------------------------------------------ -- Green highway sign with bilingual text ---------------------------------------
local function buildRoad(parent: Folder) local function makeSign(text: string, cf: CFrame, parent: Instance)
for i = 0, NUM_SEGMENTS - 1 do local board = part({
local z = -(i * SEGMENT_LENGTH) - SEGMENT_LENGTH / 2 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({ local road = part({
Name = "Road_" .. i, Name = "Road_" .. i,
Size = Vector3.new(ROAD_WIDTH, 2, SEGMENT_LENGTH), Size = Vector3.new(ROAD_WIDTH, 2, len),
Position = Vector3.new(0, 0, z), CFrame = cf,
Color = Color3.fromRGB(28, 28, 34), Color = Color3.fromRGB(28, 28, 34),
Material = Enum.Material.Asphalt, Material = Enum.Material.Asphalt,
}) })
road.Parent = parent road.Parent = roadFolder
local line = part({ local line = part({
Name = "Lane_" .. i, Name = "Lane_" .. i,
Size = Vector3.new(1, 2.1, SEGMENT_LENGTH), Size = Vector3.new(1, 2.1, len),
Position = Vector3.new(0, 0.1, z), CFrame = cf * CFrame.new(0, 0.1, 0),
Color = Color3.fromRGB(230, 200, 60), Color = Color3.fromRGB(230, 200, 60),
Material = Enum.Material.Neon, Material = Enum.Material.Neon,
}) })
line.Parent = parent 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
end end
-- Guardrails, kill walls, pylons ---------------------------------------------- -- Daikoku Futo PA ----------------------------------------------------------------
local function buildBarriers(map: Folder, totalLength: number) local function buildDaikoku(map: Folder)
for _, side in ipairs({ -1, 1 }) do local folder = Instance.new("Folder")
local x = side * (ROAD_WIDTH / 2) folder.Name = "DaikokuPA"
local rail = part({ folder.Parent = map
Name = "Guardrail_" .. (side == -1 and "L" or "R"),
Size = Vector3.new(1.5, 4, totalLength), local z0 = HZ + ROAD_WIDTH / 2 -- pad starts at the road's outer edge
Position = Vector3.new(x, 2, -totalLength / 2), local depth = 220
Color = Color3.fromRGB(180, 180, 190), 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, Material = Enum.Material.Metal,
}) })
rail.Parent = map 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
local wall = part({ -- Perimeter walls (invisible) on the three non-road sides
Name = "KillWall_" .. (side == -1 and "L" or "R"), local wallDefs = {
Size = Vector3.new(2, WALL_HEIGHT, totalLength), { Vector3.new(halfW * 2 + 4, WALL_HEIGHT, 2), CFrame.new(0, WALL_HEIGHT / 2, z0 + depth + 1) },
Position = Vector3.new(x + side * 2, WALL_HEIGHT / 2, -totalLength / 2), { 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, Transparency = 1,
CanCollide = true, CanCollide = true,
}) })
wall.Parent = map w.Parent = folder
for i = 0, math.floor(totalLength / 200) 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 NEON_PINK or NEON_BLUE,
Material = Enum.Material.Neon,
})
pylon.Parent = map
end
end end
-- Spawn pad (cars appear here — Daikoku is the meet) -----------------------
local spawn = part({
Name = "SpawnPad",
Size = Vector3.new(120, 1, 60),
CFrame = CFrame.new(0, 1.2, z0 + 130),
Color = Color3.fromRGB(20, 220, 120),
Material = Enum.Material.Neon,
Transparency = 0.4,
})
spawn.Parent = folder
makeSign("大黒PA DAIKOKU PA", CFrame.new(0, 12, z0 + 4) * CFrame.Angles(0, math.pi, 0), folder)
end end
-- Overhead gantry arches (segment 2) ------------------------------------------- -- Rainbow Bridge towers over the east straight -----------------------------------
local function buildGantries(map: Folder) local function buildRainbowBridge(map: Folder)
local folder = Instance.new("Folder") local folder = Instance.new("Folder")
folder.Name = "Gantries" folder.Name = "RainbowBridge"
folder.Parent = map folder.Parent = map
local segStart = 2 * SEGMENT_LENGTH for _, tz in ipairs({ 250, -250 }) do
for g = 0, 3 do
local z = -(segStart + 60 + g * 90)
for _, side in ipairs({ -1, 1 }) do for _, side in ipairs({ -1, 1 }) do
local post = part({ local tx = HX + side * (ROAD_WIDTH / 2 + 5)
Name = "GantryPost", local tower = part({
Size = Vector3.new(2, 24, 2), Name = "BridgeTower",
Position = Vector3.new(side * (ROAD_WIDTH / 2 - 2), 12, z), Size = Vector3.new(6, 95, 6),
Color = Color3.fromRGB(60, 60, 70), CFrame = CFrame.new(tx, 47.5, tz),
Material = Enum.Material.DiamondPlate, Color = Color3.fromRGB(235, 235, 240),
Material = Enum.Material.Concrete,
}) })
post.Parent = folder 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 end
local beam = part({ local beam = part({
Name = "GantryBeam", Name = "TowerBeam",
Size = Vector3.new(ROAD_WIDTH, 2.5, 2.5), Size = Vector3.new(ROAD_WIDTH + 22, 4, 5),
Position = Vector3.new(0, 24, z), CFrame = CFrame.new(HX, 62, tz),
Color = g % 2 == 0 and NEON_TEAL or NEON_PINK, Color = Color3.fromRGB(235, 235, 240),
Material = Enum.Material.Neon, Material = Enum.Material.Concrete,
}) })
beam.Parent = folder beam.Parent = folder
end end
makeSign(
"レインボーブリッジ RAINBOW BRIDGE",
CFrame.new(HX, 14, 330) * CFrame.Angles(0, math.pi / 2, 0),
folder
)
end end
-- Tunnel (segment 3): walls + ceiling with neon strips --------------------------- -- Odaiba: blocky Unicorn-Gundam-style statue + giant ferris wheel ----------------
local function buildTunnel(map: Folder) local function buildOdaiba(map: Folder)
local folder = Instance.new("Folder") local folder = Instance.new("Folder")
folder.Name = "Tunnel" folder.Name = "Odaiba"
folder.Parent = map folder.Parent = map
local zCenter = -(3 * SEGMENT_LENGTH) - SEGMENT_LENGTH / 2 local gx, gz = HX + 150, 480 -- statue stands beyond the bridge's south end
local tunnelHeight = 22 local white = Color3.fromRGB(235, 235, 240)
for _, side in ipairs({ -1, 1 }) do local function block(name: string, size: Vector3, cf: CFrame, color: Color3, mat: Enum.Material?)
local wall = part({ local b = part({
Name = "TunnelWall_" .. (side == -1 and "L" or "R"), Name = name,
Size = Vector3.new(3, tunnelHeight, SEGMENT_LENGTH), Size = size,
Position = Vector3.new(side * (ROAD_WIDTH / 2 + 1.5), tunnelHeight / 2, zCenter), CFrame = cf,
Color = Color3.fromRGB(38, 38, 46), Color = color,
Material = Enum.Material.Concrete, Material = mat or Enum.Material.SmoothPlastic,
}) })
wall.Parent = folder b.Parent = folder
return b
end end
local ceiling = part({ -- Base plinth
Name = "TunnelCeiling", block(
Size = Vector3.new(ROAD_WIDTH + 6, 2, SEGMENT_LENGTH), "GundamBase",
Position = Vector3.new(0, tunnelHeight + 1, zCenter), Vector3.new(40, 4, 40),
Color = Color3.fromRGB(30, 30, 38), CFrame.new(gx, 2, gz),
Material = Enum.Material.Concrete, Color3.fromRGB(60, 60, 70),
}) Enum.Material.Concrete
ceiling.Parent = folder )
-- 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)
-- Neon ceiling strips light the tunnel (one every 50 studs, alternating). -- Giant ferris wheel (Palette Town) -----------------------------------------
for i = 0, math.floor(SEGMENT_LENGTH / 50) do local wx, wz = HX + 240, 120
local z = -(3 * SEGMENT_LENGTH) - i * 50 local radius = 55
local strip = part({ local hub = CFrame.new(wx, radius + 24, wz)
Name = "TunnelLight", block(
Size = Vector3.new(ROAD_WIDTH * 0.5, 0.6, 2), "WheelSupportL",
Position = Vector3.new(0, tunnelHeight - 0.5, z), Vector3.new(4, radius + 26, 4),
Color = i % 2 == 0 and NEON_BLUE or NEON_TEAL, 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, Material = Enum.Material.Neon,
}) })
strip.Parent = folder 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 end
makeSign("お台場 ODAIBA", CFrame.new(HX + 60, 12, 300) * CFrame.Angles(0, math.pi / 2, 0), folder)
end end
-- Jump ramps (segment 4): launch + landing pair on the right half --------------- -- Tokyo Tower replica on the west side --------------------------------------------
local function buildRamps(map: Folder) local function buildTokyoTower(map: Folder)
local folder = Instance.new("Folder") local folder = Instance.new("Folder")
folder.Name = "Ramps" folder.Name = "TokyoTower"
folder.Parent = map folder.Parent = map
local zStart = 4 * SEGMENT_LENGTH + 100 local tx, tz = -HX - 220, 0
local rampX = ROAD_WIDTH / 4 -- right half of the road; left half stays flat local orange = Color3.fromRGB(235, 100, 40)
local levels = {
-- Launch ramp: a wedge sloping up in the direction of travel (-Z). { w = 64, h = 50, c = orange },
local launch = Instance.new("WedgePart") { w = 44, h = 45, c = Color3.fromRGB(240, 240, 245) },
launch.Anchored = true { w = 28, h = 45, c = orange },
launch.Name = "RampLaunch" { w = 15, h = 40, c = Color3.fromRGB(240, 240, 245) },
launch.Size = Vector3.new(ROAD_WIDTH / 2 - 4, 10, 48) }
-- WedgePart slopes from its -Z (tall) to +Z (thin edge); car travels -Z, local y = 0
-- so face the thin edge toward the approaching car (+Z toward car = yaw 180). for li, lv in ipairs(levels) do
launch.CFrame = CFrame.new(rampX, 5, -zStart) * CFrame.Angles(0, math.rad(180), 0) local sec = part({
launch.Color = Color3.fromRGB(50, 50, 62) Name = "TowerSection" .. li,
launch.Material = Enum.Material.Metal Size = Vector3.new(lv.w, lv.h, lv.w),
launch.TopSurface = Enum.SurfaceType.Smooth CFrame = CFrame.new(tx, y + lv.h / 2, tz),
launch.Parent = folder Color = lv.c,
Material = Enum.Material.Metal,
local edge = part({ })
Name = "RampEdgeGlow", sec.Parent = folder
Size = Vector3.new(ROAD_WIDTH / 2 - 4, 0.8, 1), y += lv.h
Position = Vector3.new(rampX, 10.4, -zStart - 24), end
Color = NEON_PINK, -- 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, Material = Enum.Material.Neon,
}) })
edge.Parent = folder deck1.Parent = folder
local deck2 = part({
-- Landing ramp: mirrored wedge further down so clean jumps land smooth. Name = "TopDeck",
local landing = Instance.new("WedgePart") Size = Vector3.new(20, 6, 20),
landing.Anchored = true CFrame = CFrame.new(tx, 152, tz),
landing.Name = "RampLanding" Color = Color3.fromRGB(250, 245, 235),
landing.Size = Vector3.new(ROAD_WIDTH / 2 - 4, 10, 60) Material = Enum.Material.Neon,
landing.CFrame = CFrame.new(rampX, 5, -(zStart + 150)) })
landing.Color = Color3.fromRGB(50, 50, 62) deck2.Parent = folder
landing.Material = Enum.Material.Metal local antenna = part({
landing.TopSurface = Enum.SurfaceType.Smooth Name = "Antenna",
landing.Parent = folder Size = Vector3.new(2, 40, 2),
CFrame = CFrame.new(tx, 200, tz),
Color = orange,
Material = Enum.Material.Neon,
})
antenna.Parent = folder
end end
-- Neon skyline: procedural building blocks flanking the route ------------------- -- Tatsumi-style overlook pad (visual scenery, NE corner outside) ------------------
local function buildSkyline(map: Folder, totalLength: number) 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") local folder = Instance.new("Folder")
folder.Name = "Skyline" folder.Name = "Skyline"
folder.Parent = map folder.Parent = map
local accents = { NEON_PINK, NEON_BLUE, NEON_TEAL, Color3.fromRGB(200, 120, 255) } local accents = { NEON_PINK, NEON_BLUE, NEON_TEAL, Color3.fromRGB(200, 120, 255) }
for _, side in ipairs({ -1, 1 }) do local function tower(seed: number, x: number, z: number)
local n = 0 local width = 40 + det(seed) * 50
local z = -80 local depth = 40 + det(seed + 1) * 50
while z > -totalLength do local height = 50 + det(seed + 2) * 170
n += 1 local t = part({
local seed = side * 1000 + n Name = "Tower",
local width = 40 + det(seed) * 60 Size = Vector3.new(width, height, depth),
local depth = 40 + det(seed + 1) * 60 CFrame = CFrame.new(x, height / 2 - 10, z),
local height = 40 + det(seed + 2) * 160 Color = Color3.fromRGB(16, 16, 24),
local gap = 30 + det(seed + 3) * 70 Material = Enum.Material.Slate,
local x = side * (ROAD_WIDTH / 2 + 50 + det(seed + 4) * 90 + width / 2) })
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
local tower = part({ -- City core inside the loop
Name = "Tower", local seed = 1
Size = Vector3.new(width, height, depth), for gx = -2, 2 do
Position = Vector3.new(x, height / 2 - 10, z - depth / 2), for gz = -1, 1 do
Color = Color3.fromRGB(16, 16, 24), seed += 7
Material = Enum.Material.Slate, local x = gx * 300 + (det(seed) - 0.5) * 120
}) local z = gz * 300 + (det(seed + 3) - 0.5) * 120
tower.Parent = folder tower(seed, x, z)
end
-- Lit window band + rooftop accent (2 parts per tower, cheap). end
local accent = accents[(n % #accents) + 1] -- Outer ring (skip landmark zones: Odaiba east, Tokyo Tower west-center,
local band = part({ -- Daikoku south-center)
Name = "TowerBand", for i = 1, 26 do
Size = Vector3.new(width + 0.4, 2 + det(seed + 5) * 4, depth + 0.4), seed += 11
Position = Vector3.new(x, height * (0.4 + det(seed + 6) * 0.4), z - depth / 2), local ang = (i / 26) * math.pi * 2
Color = accent, local rad = 1750 + det(seed + 4) * 350
Material = Enum.Material.Neon, local x = math.cos(ang) * rad
Transparency = 0.2, local z = math.sin(ang) * rad * 0.75
}) local skip = (x > HX and math.abs(z) < 620) -- Odaiba
band.Parent = folder or (x < -HX and math.abs(z) < 260) -- Tokyo Tower
or (z > HZ and math.abs(x) < 420) -- Daikoku
local roof = part({ if not skip then
Name = "TowerRoof", tower(seed, x, z)
Size = Vector3.new(width * 0.3, 1.5, depth * 0.3),
Position = Vector3.new(x, height - 9, z - depth / 2),
Color = accent,
Material = Enum.Material.Neon,
})
roof.Parent = folder
z = z - depth - gap
end end
end end
end end
@@ -288,61 +658,46 @@ function MapBuilder.build(): Folder
local map = Instance.new("Folder") local map = Instance.new("Folder")
map.Name = "Map" map.Name = "Map"
local roadFolder = Instance.new("Folder") local samples = genSamples()
roadFolder.Name = "Expressway" buildLoop(map, samples)
roadFolder.Parent = map buildDaikoku(map)
buildRainbowBridge(map)
buildOdaiba(map)
buildTokyoTower(map)
buildTatsumi(map)
buildSkyline(map)
local totalLength = SEGMENT_LENGTH * NUM_SEGMENTS -- Finish line across the south straight just past the Daikoku exit --------
buildRoad(roadFolder)
buildBarriers(map, totalLength)
buildGantries(map)
buildTunnel(map)
buildRamps(map)
buildSkyline(map, totalLength)
-- 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({ local finish = part({
Name = "FinishLine", Name = "FinishLine",
Size = Vector3.new(ROAD_WIDTH, 1, 6), Size = Vector3.new(ROAD_WIDTH, 1, 6),
Position = Vector3.new(0, 1.5, -totalLength + 30), CFrame = CFrame.new(420, 1.5, HZ),
Color = Color3.fromRGB(240, 240, 240), Color = Color3.fromRGB(240, 240, 240),
Material = Enum.Material.Neon, Material = Enum.Material.Neon,
Transparency = 0.3, Transparency = 0.3,
}) })
finish.Parent = map finish.Parent = map
-- End wall so you can't sail off the far edge ------------------------------ -- Safety net floor under everything ----------------------------------------
local endWall = part({
Name = "KillWall_End",
Size = Vector3.new(ROAD_WIDTH + 8, WALL_HEIGHT, 2),
Position = Vector3.new(0, WALL_HEIGHT / 2, -totalLength - 1),
Transparency = 1,
CanCollide = true,
})
endWall.Parent = map
-- A floor far below to catch anything that clips through (safety net) ------
local floor = part({ local floor = part({
Name = "SafetyFloor", Name = "SafetyFloor",
Size = Vector3.new(ROAD_WIDTH * 4, 2, totalLength + 400), Size = Vector3.new((HX + 700) * 2, 2, (HZ + 700) * 2),
Position = Vector3.new(0, -60, -totalLength / 2), CFrame = CFrame.new(0, -60, 0),
Transparency = 1, Transparency = 1,
CanCollide = true, CanCollide = true,
}) })
floor.Parent = map 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 map.Parent = Workspace
return map return map
end end