Run it
Copy the script and paste it into your executor.
ENV = ()
startShown = (ENV.BrookhavenStudio ENV.BrookhavenStudio.IsShown ENV.BrookhavenStudio.())
ENV.BrookhavenStudio ENV.BrookhavenStudio.Unload
ok, err = (ENV.BrookhavenStudio.Unload)
ok
( .. (err))
Players = :()
ReplicatedStorage = :()
TweenService = :()
UserInputService = :()
RunService = :()
MarketplaceService = :()
HttpService = :()
Lighting = :()
VirtualUser = :()
LocalPlayer = Players.LocalPlayer
Remotes = ReplicatedStorage:()
LegacyRemotes = ReplicatedStorage:()
Gamepasses = (ReplicatedStorage.Modules.Shared.PlayerData.Gamepasses)
(cleanName)
_, child (LegacyRemotes:())
(child.Name:(, )) == cleanName
child
( .. cleanName .. )
(name)
r = Remotes:(name)
r
( .. name .. )
r
CarEvent = ()
HouseEvent = ()
NameColorEvent = ()
NameTextEvent = ()
PropertySetColor = ()
HouseNumber = LocalPlayer:():()
(name, ...)
args = .(...)
(()
(name):(.(args, , args.n))
)
ownedCache = {}
(key)
ownedCache[key] ~=
ownedCache[key]
pass = Gamepasses[key]
pass ==
( .. key)
ok, result = (()
MarketplaceService:(LocalPlayer.UserId, Gamepasses.(pass))
)
ok
( .. key .. .. (result))
ownedCache[key] = result ==
ownedCache[key]
()
()
()
()
CARS = {
{ id = , label = , pass = },
{ id = , label = , pass = },
{ id = , label = , pass = },
{ id = , label = , pass = },
{ id = , label = , pass = },
{ id = , label = , pass = },
{ id = , label = , pass = },
{ id = , label = , pass = },
{ id = , label = , pass = },
{ id = , label = , pass = },
{ id = , label = },
{ id = , label = },
{ id = , label = },
}
UNDERGLOWS = { , , , , , , , }
RGB_MODES = { , , , , , , , }
RGB_PALETTES = {
Ocean = { .(, , ), .(, , ), .(, , ), .(, , ) },
Sunset = { .(, , ), .(, , ), .(, , ), .(, , ) },
Galaxy = { .(, , ), .(, , ), .(, , ), .(, , ) },
Fire = { .(, , ), .(, , ), .(, , ), .(, , ) },
}
SWATCHES = {
.(, , ),
.(, , ),
.(, , ),
.(, , ),
.(, , ),
.(, , ),
.(, , ),
}
STUNTS = {
{ name = , axis = , turns = },
{ name = , axis = , turns = - },
{ name = , axis = , turns = },
{ name = , axis = , turns = - },
{ name = , axis = , turns = },
{ name = , axis = , turns = },
{ name = , axis = , turns = },
}
SETTINGS_FILE =
Settings = {
car = ,
autoTune = ,
performance = ,
accel = ,
steer = ,
handling = ,
grip = ,
tireGrip = ,
traction = ,
antiRoll = ,
brakeAssist = ,
brakeStrength = ,
autoFlip = ,
rideHeight = ,
underglow = ,
glowLength = ,
glowWidth = ,
rainbowGlow = ,
carRGB = ,
rgbMode = ,
rgbCycle = ,
stunt = ,
stuntAirtime = ,
hopAirtime = ,
rpName = ,
rpBio = ,
rainbowName = ,
antiAfk = ,
speedo = ,
lockTime = ,
hour = ,
fullbright = ,
fovOn = ,
fov = ,
unlockZoom = ,
houseRainbow = ,
houseCycle = ,
loadBuild = ,
buildSlot = ,
airStunts = ,
airTrick = ,
airAlways = ,
airMin = ,
landAssist = ,
stuntTrail = ,
drift = ,
driftGrip = ,
autoLights = ,
arraylist = ,
toggleNotify = ,
blur = ,
binds = { Stunt = , [] = , Drift = },
schema = ,
}
SETTINGS_SCHEMA =
isfile readfile (SETTINGS_FILE)
ok, data = (()
HttpService:((SETTINGS_FILE))
)
ok (data) ==
key, value (data)
Settings[key] ~= (value) == (Settings[key])
Settings[key] = value
()
Settings.schema <
Settings.rideHeight =
Settings.schema < SETTINGS_SCHEMA
name, key ({ Stunt = , [] = , Drift = })
Settings.binds[name] ==
Settings.binds[name] = key
Settings.schema = SETTINGS_SCHEMA
alive =
savePending =
()
savePending writefile
savePending =
.(, ()
savePending =
alive
(SETTINGS_FILE, HttpService:(Settings))
)
T = {
bg = .(, , ),
side = .(, , ),
raised = .(, , ),
line = .(, , ),
off = .(, , ),
white = .(, , ),
text = .(, , ),
sub = .(, , ),
dim = .(, , ),
black = .(, , ),
}
FONT = .Font.BuilderSansMedium
FONT_BOLD = .Font.BuilderSansBold
FONT_BLACK = .Font.BuilderSansExtraBold
EASE = TweenInfo.(, .EasingStyle.Quint, .EasingDirection.Out)
connections = {}
(signal, fn)
c = signal:(fn)
.(connections, c)
c
order =
()
order +=
order
(className, props, children)
inst = .(className)
key, value (props {})
key ~=
inst[key] = value
_, child (children {})
child.Parent = inst
inst.Parent = props props.Parent
inst
(inst, props, info)
tw = TweenService:(inst, info EASE, props)
tw:()
tw
(props)
props.BackgroundTransparency =
props.Font = props.Font FONT
props.TextColor3 = props.TextColor3 T.text
props.TextXAlignment = props.TextXAlignment .TextXAlignment.Left
(, props)
(radius)
(, { CornerRadius = radius .(, radius) .(, ) })
(left, right, top, bottom)
(, {
PaddingLeft = .(, left ),
PaddingRight = .(, right ),
PaddingTop = .(, top ),
PaddingBottom = .(, bottom ),
})
oldBlur = Lighting:()
oldBlur
oldBlur:()
Gui = (, {
Name = ,
ResetOnSpawn = ,
IgnoreGuiInset = ,
ZIndexBehavior = .ZIndexBehavior.Sibling,
DisplayOrder = ,
Parent = (gethui ()) :(),
})
()
viewport = .CurrentCamera.ViewportSize
.(.(viewport.X / , viewport.Y / ), , )
guiScale = ()
scaleObjects = {}
(inst)
.(scaleObjects, (, { Scale = guiScale, Parent = inst }))
inst
TOAST_W, TOAST_H, TOAST_TIME = , ,
toastHolder = ((, {
AnchorPoint = .(, ),
Position = .(, -, , -),
Size = .(TOAST_W, ),
BackgroundTransparency = ,
Parent = Gui,
}, {
(, { VerticalAlignment = .VerticalAlignment.Bottom, SortOrder = .SortOrder.LayoutOrder }),
}))
toastCount =
(title, message, kind)
( .. title .. .. message)
alive
toastCount +=
slot = (, {
LayoutOrder = toastCount,
Size = .(TOAST_W, ),
BackgroundTransparency = ,
Parent = toastHolder,
})
card = (, {
AnchorPoint = .(, ),
Position = .(, , , ),
Size = .(TOAST_W, TOAST_H),
BackgroundColor3 = T.bg,
BackgroundTransparency = ,
BorderSizePixel = ,
GroupTransparency = ,
Parent = slot,
}, {
(),
(, { Color = T.line, ApplyStrokeMode = .ApplyStrokeMode.Border }),
})
textX =
kind == kind ==
dot = (, {
AnchorPoint = .(, ),
Position = .(, , , ),
Size = .(, ),
BackgroundColor3 = kind == T.white T.bg,
BorderSizePixel = ,
Parent = card,
}, { () })
kind ==
(, { Color = T.white, Thickness = , Parent = dot })
textX =
({
Text = title,
Font = FONT_BOLD,
TextSize = ,
TextColor3 = T.white,
Position = .(, textX, , ),
Size = .(, -textX - , , ),
TextTruncate = .TextTruncate.AtEnd,
Parent = card,
})
({
Text = message,
TextSize = ,
TextColor3 = T.sub,
Position = .(, textX, , ),
Size = .(, -textX - , , ),
TextTruncate = .TextTruncate.AtEnd,
Parent = card,
})
timer = (, {
AnchorPoint = .(, ),
Position = .(, , , ),
Size = .(, , , ),
BackgroundColor3 = T.white,
BackgroundTransparency = ,
BorderSizePixel = ,
Parent = card,
})
(slot, { Size = .(TOAST_W, TOAST_H + ) }, TweenInfo.(, .EasingStyle.Quint, .EasingDirection.Out))
(card, { Position = .(, , , ), GroupTransparency = }, TweenInfo.(, .EasingStyle.Quint, .EasingDirection.Out))
(timer, { Size = .(, , , ) }, TweenInfo.(TOAST_TIME, .EasingStyle.Linear))
.(TOAST_TIME, ()
card.Parent
(card, { Position = .(, , , ), GroupTransparency = }, TweenInfo.(, .EasingStyle.Quint, .EasingDirection.In))
.()
slot.Parent
(slot, { Size = .(TOAST_W, ) }, TweenInfo.(, .EasingStyle.Quint, .EasingDirection.Out))
.()
slot:()
)
()
:()
(car)
owner = car car:()
owner ~= owner:() owner.Value == LocalPlayer.Name
()
folder = ()
folder
_, model (folder:())
(model) model
(part)
folder = ()
folder
node = part
node node.Parent ~= folder
node = node.Parent
node
(car)
body = car:()
colorModel = body body:()
colorModel
_, part (colorModel:())
part:() part.Color
config = car:()
default = config config:()
default default.Value
Session =
originalPaints = ({}, { __mode = })
cachedCar, nextCarScan = ,
()
Session
Session.car
cachedCar cachedCar.Parent (cachedCar)
cachedCar
cachedCar =
.() >= nextCarScan
nextCarScan = .() +
cachedCar = ()
cachedCar originalPaints[cachedCar] ==
originalPaints[cachedCar] = (cachedCar)
cachedCar
(car, color)
called, ok, msg = (, car:(), color)
called
, (ok)
ok == , msg
tunedCars = ({}, { __mode = })
refreshModule
setVehicleStatus
(s)
(s.geom.valid Settings.performance) Settings.accel
()
Settings.performance Settings.steer
()
s = Session
s
accel = (s)
s.seat.Torque = s.baseTorque * accel
s.seat.TurnSpeed = s.baseTurn * ()
baseTurbo = s.turbo (s.baseTurbo)
baseTurbo
s.turboExpected = .(, baseTurbo * accel)
s.turbo.Value = s.turboExpected
TIRE_FRICTION_WEIGHT =
STOCK_FRICTION =
(s)
.(Settings.tireGrip, .(s.geom.gripLimit, STOCK_FRICTION))
(s)
s.geom.valid Settings.handling
(s, wheel)
s.drifting s.rearWheels[wheel]
Settings.driftGrip
(s) (s)
()
s = Session
s
wheel, original (s.wheelProps)
wheel.Parent
friction = (s, wheel)
friction
wheel.CustomPhysicalProperties = PhysicalProperties.(
original.Density, friction, original.Elasticity, TIRE_FRICTION_WEIGHT, original.ElasticityWeight
)
wheel.CustomPhysicalProperties = original
groundParams = RaycastParams.()
groundParams.FilterType = .RaycastFilterType.Exclude
(s)
platform = s.geom.platform
platform platform.Parent
platform.CFrame
s.seat.CFrame
(car, seat, root)
chassis = car:()
platform = chassis chassis:()
platform platform:()
platform =
frame = platform platform.CFrame seat.CFrame
front, rear, all = {}, {}, {}
_, d (car:())
steering = d:()
steering d:()
holder = d:() d:()
physical = d:()
holder holder:()
wheel = {
frameLocal = frame:(holder.Position),
radius = physical physical:() physical.Size.Y / ,
contact = physical physical:() frame:(physical.Position).Y - physical.Size.Y / ,
}
.(all, wheel)
.(steering front rear, wheel)
extents = car:()
geom = { valid = , platform = platform, wheels = #all, gripLimit = STOCK_FRICTION, probe = extents.Y + }
#all < #front < #rear <
geom
(list)
sum = .zero
_, w (list)
sum += w.frameLocal
sum / #list
frontLocal, rearLocal = (front), (rear)
minX, maxX, contactY, radius = .huge, -.huge, ,
_, w (all)
minX = .(minX, w.frameLocal.X)
maxX = .(maxX, w.frameLocal.X)
contactY += w.frameLocal.Y - w.radius
radius += w.radius
contactY /= #all
radius /= #all
com = frame:(root.AssemblyCenterOfMass)
cgHeight = .(com.Y - contactY, )
halfTrack = (maxX - minX) /
frontDist = .(com.Z - frontLocal.Z)
rearDist = .(rearLocal.Z - com.Z)
stability = .(halfTrack, frontDist, rearDist) / cgHeight
geom.valid =
geom.stability = stability
geom.gripLimit = stability
geom.halfTrack = halfTrack
geom.frontDist = frontDist
geom.rearDist = rearDist
geom.cgHeight = cgHeight
geom.wheelbase = frontDist + rearDist
geom.radius = radius
geom.probe = radius * +
contactSum, contactCount = ,
_, w (all)
w.contact
contactSum += w.contact
contactCount +=
contactCount >
geom.rootHeight = frame:(root.Position).Y - contactSum / contactCount
geom.frontRoot = root.CFrame:(frame:(frontLocal))
geom.rearRoot = root.CFrame:(frame:(rearLocal))
geom
(s, root)
s.root == root s.force s.force.Parent == root
_, inst ({ s.force, s.attach, s.align, s.alignAttach, s.rearForce, s.rearAttach })
inst:()
s.root = root
frame = (s)
s.attach = (, { Name = , Parent = root })
s.force = (, {
Name = ,
Attachment0 = s.attach,
RelativeTo = .ActuatorRelativeTo.World,
ApplyAtCenterOfMass = ,
Force = .zero,
Parent = root,
})
s.rearAttach = (, { Name = , Position = s.geom.rearRoot, Parent = root })
s.rearForce = (, {
Name = ,
Attachment0 = s.rearAttach,
RelativeTo = .ActuatorRelativeTo.World,
ApplyAtCenterOfMass = ,
Force = .zero,
Parent = root,
})
s.alignAttach = (, { Name = , Parent = root })
s.alignAttach.WorldAxis = frame.UpVector
s.alignAttach.WorldSecondaryAxis = frame.LookVector
s.align = (, {
Name = ,
Mode = .OrientationAlignmentMode.OneAttachment,
Attachment0 = s.alignAttach,
AlignType = .AlignType.PrimaryAxisParallel,
PrimaryAxis = .yAxis,
RigidityEnabled = ,
Responsiveness = ,
MaxTorque = ,
MaxAngularVelocity = ,
Enabled = ,
Parent = root,
})
ANTI_FLIP_DEADZONE =
ANTI_FLIP_RAMP =
(dt)
s = Session
s s.geom.valid
root = s.seat.AssemblyRootPart
root
(s, root)
s.stunting
s.force.Force = .zero
s.rearForce.Force = .zero
s.align.Enabled =
frame = (s)
up, right, look = frame.UpVector, frame.RightVector, frame.LookVector
gravity = .Gravity
groundParams.FilterDescendantsInstances = { s.car, LocalPlayer.Character }
frontPoint = root.CFrame:(s.geom.frontRoot)
rearPoint = root.CFrame:(s.geom.rearRoot)
frontHit = :(frontPoint, -up * s.geom.probe, groundParams)
rearHit = :(rearPoint, -up * s.geom.probe, groundParams)
grounded = frontHit ~= rearHit ~=
v = root.AssemblyLinearVelocity
force = .zero
Settings.handling Settings.grip grounded
flatSpeed = .(v.X, , v.Z).Magnitude
force += .(, -root.AssemblyMass * gravity * .(flatSpeed / , , ) * , )
Settings.brakeAssist grounded
forward = v:(look)
throttle = s.seat.ThrottleFloat
(forward > throttle < -) (forward < - throttle > )
balance = .(s.geom.frontDist, s.geom.rearDist) / s.geom.cgHeight
decel = gravity * .(Settings.brakeStrength, balance * ) * .(throttle)
decel = .(decel, .(forward) / .(dt, / ))
force += look * (forward > - ) * s.mass * decel
s.force.Force = force
Settings.handling rearHit Settings.traction > s.drifting
lateral = root:(rearPoint):(right)
cap = s.mass * gravity * .(, s.geom.stability)
push = .(-lateral * s.mass * (Settings.traction / ) * , -cap, cap)
s.rearForce.Force = right * push
s.rearForce.Force = .zero
strength =
Settings.handling Settings.antiRoll grounded
roadForward = frontHit rearHit (frontHit.Position - rearHit.Position)
roadForward roadForward.Magnitude < .(roadForward.Unit.Y) >
roadForward = .(look.X, , look.Z)
roadForward.Magnitude >
sideways = roadForward.Unit:(.yAxis)
sideways.Magnitude >
targetUp = sideways.Unit:(roadForward.Unit)
tilt = .(.(.(up:(targetUp), -, )))
strength = .((tilt - ANTI_FLIP_DEADZONE) / ANTI_FLIP_RAMP, , )
s.align.PrimaryAxis = targetUp
s.align.MaxTorque = s.flipTorque * strength
s.align.Enabled = strength >
(car)
config = car:()
heights = config config:()
heights
values, default = {},
_, v (heights:())
v:()
.(values, v.Value)
v:() ==
default = v.Value
.(values)
i, value (values)
default .(value - default) <
i
(name, ...)
Session
,
called, ok, msg = (name, ...)
called
, (ok)
ok == , msg
(s)
.()
Session ~= s
parts = {}
speed = ()
called, ok, _, value = (, speed)
called ok
.(parts, .. (value speed))
.(parts, )
(, )
.(parts, )
(s)
grip = (s)
(, .(grip, ))
.(parts, grip < Settings.tireGrip .(, grip) .(, grip))
s.geom.valid
.(parts, )
Settings.rideHeight > (, Settings.rideHeight)
.(parts, .. Settings.rideHeight)
() (, Settings.underglow)
.(parts, .(Settings.underglow))
(, Settings.glowLength, Settings.glowWidth)
Session == s
s.ready =
(, .(parts, ), )
()
refreshModule
()
()
()
setVehicleStatus
Session
name = Session.car:() Session.car.Name
(name, Session.geom.valid , )
parked = ()
parked
(parked:() parked.Name, , )
(, , )
()
s = Session
s
Session =
_, c (s.conns)
c:()
s.seat.Parent
s.seat.Torque = s.baseTorque
s.seat.TurnSpeed = s.baseTurn
s.turbo s.turbo.Parent s.baseTurbo
s.turbo.Value = s.baseTurbo
wheel, original (s.wheelProps)
wheel.Parent
wheel.CustomPhysicalProperties = original
_, inst ({ s.force, s.attach, s.align, s.alignAttach, s.rearForce, s.rearAttach })
inst:()
()
(seat, car)
turbo = seat:()
s = {
seat = seat,
car = car,
uuid = car:(),
baseTorque = seat.Torque,
baseTurn = seat.TurnSpeed,
turbo = turbo turbo:() turbo ,
baseTurbo = turbo turbo:() turbo.Value ,
ready = ,
stunting = ,
drifting = ,
airArmed = ,
groundTime = ,
conns = {},
wheelProps = {},
rearWheels = {},
mass = ,
}
_, part (car:())
part:()
part.Massless
s.mass += part:()
part.Name ==
s.wheelProps[part] = part.CustomPhysicalProperties PhysicalProperties.(part.Material)
s.rearWheels[part] = part.Parent ~= part.Parent:()
.(s.conns, part:():(()
p = part.CustomPhysicalProperties
want = Session == s (s, part)
want p (.(p.Friction - want) > .(p.FrictionWeight - TIRE_FRICTION_WEIGHT) > )
s.wheelProps[part] = p
()
))
originalPaints[car] ==
originalPaints[car] = (car)
s.geom = (car, seat, seat.AssemblyRootPart)
root = seat.AssemblyRootPart
groundParams.FilterDescendantsInstances = { car, LocalPlayer.Character }
below = :(root.Position, .(, -, ), groundParams)
s.clearance = .(s.geom.rootHeight (below root.Position.Y - below.Position.Y) , , )
s.geom.valid
s.flipTorque = s.mass * .Gravity * .(s.geom.halfTrack, s.geom.wheelbase / ) *
Session = s
.(s.conns, seat:():(()
Session == s .(seat.Torque - s.baseTorque * (s)) >
s.baseTorque = seat.Torque
()
))
.(s.conns, seat:():(()
Session == s .(seat.TurnSpeed - s.baseTurn * ()) >
s.baseTurn = seat.TurnSpeed
()
))
s.turbo
.(s.conns, s.turbo.Changed:((newValue)
Session == s newValue ~= s.turboExpected
s.baseTurbo = newValue
()
))
.(s.conns, car:():(syncEffectModules))
.(s.conns, car:():(syncEffectModules))
.(s.conns, RunService.Heartbeat:(updateHandling))
()
()
()
Settings.autoTune tunedCars[car]
tunedCars[car] =
.(autoTune, s)
s.ready =
(humanoid)
seat = humanoid.SeatPart
Session Session.seat ~= seat
()
seat seat:() Session
car = (seat)
car (car)
(seat, car)
()
(character)
humanoid = character:(, )
humanoid alive
(humanoid:(), ()
(humanoid)
)
(humanoid)
spawning =
()
spawning
entry
_, car (CARS)
car.id == Settings.car entry = car
entry
(, , )
character = LocalPlayer.Character
humanoid = character character:()
humanoid humanoid.Health <=
(, , )
humanoid.SeatPart humanoid.Sit
(, , )
spawning =
before = ()
CarEvent:(, entry.id)
spawned
started = .()
.()
current = ()
current current ~= before spawned = current
spawned .() - started > alive
spawning =
spawned
(, entry.label .. , )
(, , )
()
(attribute, remoteName, wanted)
s = Session
s
(attribute == , , )
(s.car:(attribute) == ) ~= wanted
ok, msg = (remoteName)
ok
(, .. (msg), )
.(, syncEffectModules)
stuntBusy =
stuntCount =
HOP = { name = , axis = , turns = }
LANDING = { name = , axis = , turns = }
(def, angle)
def.axis ==
.(.xAxis, angle)
def.axis ==
.(.yAxis, angle)
def.axis ==
.(.zAxis, angle)
.(.yAxis, angle) * .(.zAxis, angle)
(name)
_, def (STUNTS)
def.name == name def
STUNTS[]
(x)
x * x * ( - * x)
(s, root)
groundParams.FilterDescendantsInstances = { s.car, LocalPlayer.Character }
:(root.Position, .(, -(s.clearance + ), ), groundParams) ~=
(s, root)
gravity = .Gravity
pos, v = root.Position, root.AssemblyLinearVelocity
groundParams.FilterDescendantsInstances = { s.car, LocalPlayer.Character }
below = :(pos, .(, -, ), groundParams)
below
groundY = below.Position.Y
()
height = pos.Y - s.clearance - groundY
height <= v.Y <=
(v.Y + .(.(v.Y * v.Y + * gravity * height, ))) / gravity
t = ()
_ = ,
ahead = pos + .(v.X, , v.Z) * t
hit = :(.(ahead.X, pos.Y + , ahead.Z), .(, -, ), groundParams)
hit hit.Position.Y > groundY
groundY = hit.Position.Y
t = ()
t
(def)
turns = .(def.turns)
turns == + * turns
(def, left)
turns = .(def.turns)
turns == .(left - , * turns + )
(s, root)
frame = (s)
right = root.CFrame:(frame.RightVector)
up = root.CFrame:(frame.UpVector)
rear = s.geom.valid s.geom.rearRoot root.CFrame:(root.Position - frame.LookVector * )
half = s.geom.valid s.geom.halfTrack
made = {}
_, side ({ -, })
base = rear + right * half * side
a0 = (, { Name = , Position = base, Parent = root })
a1 = (, { Name = , Position = base + up * , Parent = root })
trail = (, {
Name = ,
Attachment0 = a0,
Attachment1 = a1,
Lifetime = ,
MinLength = ,
FaceCamera = ,
LightEmission = ,
Color = ColorSequence.(.(, , )),
Transparency = NumberSequence.({ NumberSequenceKeypoint.(, ), NumberSequenceKeypoint.(, ) }),
WidthScale = NumberSequence.({ NumberSequenceKeypoint.(, ), NumberSequenceKeypoint.(, ) }),
Parent = root,
})
.(made, trail)
.(made, a0)
.(made, a1)
made
(s, def, flight, rotateTime, launch)
root = s.seat.AssemblyRootPart
stuntBusy root
stuntBusy =
s.stunting =
frame = (s)
flatLook = .(frame.LookVector.X, , frame.LookVector.Z)
flatLook.Magnitude <
v = root.AssemblyLinearVelocity
flatLook = .(v.X, , v.Z)
flatLook.Magnitude <
flatLook = .(, , -)
level = .(.zero, flatLook.Unit)
startRot = frame.Rotation
attach = (, { Name = , Parent = root })
attach.WorldCFrame = .(root.Position) * frame.Rotation
align = (, {
Name = ,
Mode = .OrientationAlignmentMode.OneAttachment,
Attachment0 = attach,
RigidityEnabled = ,
= startRot,
Parent = root,
})
launch >
lifted = {}
_, part (s.car:())
part:() part.Anchored
assembly = part.AssemblyRootPart
assembly lifted[assembly]
lifted[assembly] =
assembly.AssemblyLinearVelocity += .(, launch, )
trails = Settings.stuntTrail (s, root) {}
started = .()
landedAt
conn
()
conn conn:()
root.Parent
tilt = .(.(.((s).UpVector.Y, -, )))
(.(, def.name, tilt, .() - started))
def.turns ~=
stuntCount +=
align:()
attach:()
_, inst (trails)
inst:()
inst.Enabled =
.(, ()
_, inst (trails)
inst:()
)
s.stunting =
stuntBusy =
conn = RunService.Heartbeat:(()
Session ~= s root.Parent alive
()
t = .() - started
base = startRot:(level, (.(t / , , )))
progress = rotateTime > .(t / rotateTime, , )
align.CFrame = base * (def, def.turns * * .pi * (progress))
progress >= t > flight *
landedAt (s, root)
landedAt = t
(landedAt t - landedAt > ) t > flight +
()
)
(s, root, def, left)
need = (def)
left >= need
(s, def, left, (def, left), )
gravity = .Gravity
vy = root.AssemblyLinearVelocity.Y
height = gravity * left * left / - vy * left
boost = (gravity * need * need / - height) / need - vy
(s, def, need, (def, need), .(boost, ))
(def, airtime, title)
s = Session
s
(title, , )
stuntBusy
root = s.seat.AssemblyRootPart
root
turns = .(def.turns)
(s, root)
airtime = .(airtime, + * turns)
(s, def, airtime, turns > airtime * , .Gravity * airtime / )
left = (s, root)
left
(s, root, def, left)
(title, , )
(dt)
s = Session
s s.stunting
root = s.seat.AssemblyRootPart
root
(s, root)
s.groundTime += dt
s.groundTime >
s.airArmed =
s.groundTime =
s.airArmed
s.airArmed =
(Settings.airStunts Settings.landAssist)
left = (s, root)
left
Settings.airStunts
def = Settings.airTrick == STUNTS[.(#STUNTS)] (Settings.airTrick)
left >= (def) (Settings.airAlways left >= Settings.airMin)
(s, root, def, left)
Settings.landAssist left >= (LANDING)
(s, LANDING, left, , )
(stops, phase)
scaledPhase = phase * #stops
index = .(scaledPhase)
frac = scaledPhase - index
eased = frac * frac * ( - * frac)
from = stops[index % #stops + ]
to = stops[(index + ) % #stops + ]
from:(to, eased)
(mode, t, cycle)
phase = (t % cycle) / cycle
mode ==
.(phase, , )
mode ==
beat = + * .(t * .pi * / .(cycle / , ))
.(phase, , + * beat)
mode ==
sweep = + * .(t * .pi * / )
.(, , ):(.(, , ), sweep)
RGB_PALETTES[mode]
(RGB_PALETTES[mode], phase)
.(phase, , )
(t)
Settings.carRGB
(Settings.rgbMode, t, Settings.rgbCycle)
(, t, Settings.rgbCycle)
(car)
body = car:()
colorModel = body body:()
parts = {}
colorModel
_, d (colorModel:())
d:() .(parts, d)
parts
(car)
body = car:()
collide = body body:()
objects = {}
collide
_, d (collide:())
d.Name == (d:() d:())
.(objects, d)
objects
()
car = ()
paint = car originalPaints[car]
paint
.()
Settings.carRGB car.Parent
(car, paint)
(v)
Settings.carRGB = v
()
refreshModule ()
v
.(restorePaint)
(color)
PropertySetColor:(color)
HouseEvent:(, color)
(slot)
HouseNumber.Value <=
(, , )
slot ==
(, , )
called, result, message = (, slot, )
(, called, result, message)
called
(, .. (result), )
result ==
(, .. (message ( .. (message)) ), )
(, .. slot, )
()
called, saves = ()
called (saves) ~=
, (saves)
options = {}
slot, data (saves)
.(options, {
value = slot,
label = .(, (data.Name slot), (data.PropCount) ),
})
.(options, (a, b) a.value < b.value )
options
(t)
.((t % Settings.houseCycle) / Settings.houseCycle, , )
(a, b)
.(a.R - b.R) + .(a.G - b.G) + .(a.B - b.B) <
housePaint = { parts = {}, recent = {}, refreshAt = }
()
lots = :()
lot = lots lots:(LocalPlayer.Name .. )
found = {}
lot found
candidates = .(housePaint.recent)
.(candidates, (.()))
_, d (lot:())
d:()
_, color (candidates)
(d.Color, color)
.(found, d)
found
LIGHTING_KEYS = { , , , , , }
savedLighting =
()
active = Settings.lockTime Settings.fullbright
active savedLighting
savedLighting = {}
_, key (LIGHTING_KEYS)
savedLighting[key] = Lighting[key]
active savedLighting
key, value (savedLighting)
Lighting[key] = value
end
savedLighting = nil
end
end
local savedFov
local function syncFov()
local camera = workspace.CurrentCamera
if Settings.fovOn and not savedFov then
savedFov = camera.FieldOfView
elseif not Settings.fovOn and savedFov then
camera.FieldOfView = savedFov
savedFov = nil
end
end
local savedZoom
local function syncZoom()
if Settings.unlockZoom and not savedZoom then
savedZoom = LocalPlayer.CameraMaxZoomDistance
LocalPlayer.CameraMaxZoomDistance = 1000
elseif not Settings.unlockZoom and savedZoom then
LocalPlayer.CameraMaxZoomDistance = savedZoom
savedZoom = nil
end
end
RunService:BindToRenderStep("BrookhavenStudioView", Enum.RenderPriority.Last.Value, function()
if Settings.fovOn then
workspace.CurrentCamera.FieldOfView = Settings.fov
end
if not savedLighting then return end
if Settings.lockTime then
Lighting.ClockTime = Settings.hour
elseif Lighting.ClockTime ~= savedLighting.ClockTime then
savedLighting.ClockTime = Lighting.ClockTime
end
if Settings.fullbright then
Lighting.Brightness = 2
Lighting.Ambient = Color3.fromRGB(178, 178, 178)
Lighting.OutdoorAmbient = Color3.fromRGB(178, 178, 178)
Lighting.GlobalShadows = false
Lighting.FogEnd = 1e6
end
end)
bind(LocalPlayer.Idled, function()
if Settings.antiAfk then
VirtualUser:CaptureController()
VirtualUser:ClickButton2(Vector2.new())
end
end)
---------------------------------------------------------------------------------------------
-- Menu: one flat box (RightShift). Sidebar tabs on the left, the page on the right.
---------------------------------------------------------------------------------------------
local BOX_W, BOX_H = 780, 540
local SIDEBAR_W = 200
local HEADER_H = 58
local TAB_H, TAB_GAP, TAB_TOP = 44, 4, 12
local PAD = 22
local GLIDE = TweenInfo.new(0.32, Enum.EasingStyle.Quint, Enum.EasingDirection.Out)
local menuOpen = false
-- Frees the mouse from first person / shift lock while the menu is open.
local modal = make("TextButton", {
Text = "",
Size = UDim2.fromOffset(0, 0),
BackgroundTransparency = 1,
Modal = false,
Visible = false,
Parent = Gui,
})
local box = make("CanvasGroup", {
AnchorPoint = Vector2.new(0.5, 0.5),
Position = UDim2.fromScale(0.5, 0.5),
Size = UDim2.fromOffset(BOX_W, BOX_H),
BackgroundColor3 = T.bg,
BorderSizePixel = 0,
GroupTransparency = 1,
Visible = false,
Parent = Gui,
})
local basePos = box.Position
local boxScale = make("UIScale", { Scale = guiScale * 0.94, Parent = box })
local menuBlur = make("BlurEffect", { Name = "BrookhavenStudioBlur", Size = 0, Parent = Lighting })
local function hline(parent, y)
return make("Frame", {
Position = UDim2.new(0, 0, 0, y),
Size = UDim2.new(1, 0, 0, 1),
BackgroundColor3 = T.line,
BorderSizePixel = 0,
Parent = parent,
})
end
-- Header (drag handle), full width.
local header = make("Frame", {
Size = UDim2.new(1, 0, 0, HEADER_H),
BackgroundTransparency = 1,
Parent = box,
}, { pad(24, 24) })
label({
Text = "BROOKHAVEN STUDIO <font size=\"13\" weight=\"medium\" color=\"#5A5A5E\">by Obsidian Works</font>",
RichText = true,
Font = FONT_BLACK,
TextSize = 20,
TextColor3 = T.white,
Size = UDim2.fromScale(0.75, 1),
Parent = header,
})
label({
Text = "RShift to close",
TextSize = 13,
TextColor3 = T.dim,
AnchorPoint = Vector2.new(1, 0),
Position = UDim2.fromScale(1, 0),
Size = UDim2.fromScale(0.25, 1),
TextXAlignment = Enum.TextXAlignment.Right,
Parent = header,
})
hline(box, HEADER_H)
-- Sidebar: tabs on top, your vehicle card and Unload at the bottom.
local sidebar = make("Frame", {
Position = UDim2.fromOffset(0, HEADER_H + 1),
Size = UDim2.new(0, SIDEBAR_W, 1, -(HEADER_H + 1)),
BackgroundColor3 = T.side,
BorderSizePixel = 0,
Parent = box,
})
make("Frame", {
AnchorPoint = Vector2.new(1, 0),
Position = UDim2.fromScale(1, 0),
Size = UDim2.new(0, 1, 1, 0),
BackgroundColor3 = T.line,
BorderSizePixel = 0,
Parent = sidebar,
})
-- One highlight and indicator that glide to the active tab.
local tabHighlight = make("Frame", {
Position = UDim2.fromOffset(10, TAB_TOP),
Size = UDim2.new(1, -21, 0, TAB_H),
BackgroundColor3 = T.raised,
BorderSizePixel = 0,
Parent = sidebar,
}, { corner(6) })
local tabIndicator = make("Frame", {
Position = UDim2.fromOffset(10, TAB_TOP + (TAB_H - 18) / 2),
Size = UDim2.fromOffset(3, 18),
BackgroundColor3 = T.white,
BorderSizePixel = 0,
ZIndex = 2,
Parent = sidebar,
}, { corner() })
local tabList = make("Frame", {
Size = UDim2.new(1, -1, 0, 0),
AutomaticSize = Enum.AutomaticSize.Y,
BackgroundTransparency = 1,
ZIndex = 3,
Parent = sidebar,
}, {
make("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder, Padding = UDim.new(0, TAB_GAP) }),
pad(10, 10, TAB_TOP, 0),
})
local cardName, cardLine, cardStroke
local unloadHolder
do
local sideBottom = make("Frame", {
AnchorPoint = Vector2.new(0, 1),
Position = UDim2.new(0, 0, 1, 0),
Size = UDim2.new(1, -1, 0, 156),
BackgroundTransparency = 1,
Parent = sidebar,
}, { pad(18, 18, 0, 16) })
make("Frame", {
Position = UDim2.fromOffset(-18, 0),
Size = UDim2.new(1, 36, 0, 1),
BackgroundColor3 = T.line,
BorderSizePixel = 0,
Parent = sideBottom,
})
label({
Text = "VEHICLE",
Font = FONT_BOLD,
TextSize = 12,
TextColor3 = T.sub,
Position = UDim2.fromOffset(0, 16),
Size = UDim2.new(1, 0, 0, 14),
Parent = sideBottom,
})
local ring = make("Frame", {
Position = UDim2.fromOffset(0, 36),
Size = UDim2.fromOffset(42, 42),
BackgroundColor3 = T.raised,
BorderSizePixel = 0,
Parent = sideBottom,
}, { corner() })
cardStroke = make("UIStroke", { Color = T.line, Thickness = 1.5, Parent = ring })
make("ImageLabel", {
Size = UDim2.fromScale(1, 1),
BackgroundTransparency = 1,
Image = "rbxthumb://type=AvatarHeadShot&id=" .. LocalPlayer.UserId .. "&w=150&h=150",
Parent = ring,
}, { corner() })
cardName = label({
Text = "On foot",
Font = FONT_BLACK,
TextSize = 21,
TextColor3 = T.dim,
Position = UDim2.fromOffset(52, 34),
Size = UDim2.new(1, -52, 0, 24),
TextTruncate = Enum.TextTruncate.AtEnd,
Parent = sideBottom,
})
cardLine = label({
Text = "",
TextSize = 14,
TextColor3 = T.sub,
Position = UDim2.fromOffset(52, 60),
Size = UDim2.new(1, -52, 0, 18),
TextTruncate = Enum.TextTruncate.AtEnd,
Parent = sideBottom,
})
unloadHolder = make("Frame", {
AnchorPoint = Vector2.new(0, 1),
Position = UDim2.new(0, 0, 1, 0),
Size = UDim2.new(1, 0, 0, 40),
BackgroundTransparency = 1,
Parent = sideBottom,
})
end
-- While you drive, the card's second line shows live speed and your stunt count.
local cardNote, cardActive = "", false
setVehicleStatus = function(name, note, active)
cardName.Text = name
cardNote = note
cardActive = active
cardName.TextColor3 = active and T.white or T.dim
cardStroke.Color = active and T.white or T.line
if not active then
cardLine.Text = note
end
end
-- Content: page title, subtitle and the scrolling page.
local CONTENT_POS = UDim2.fromOffset(SIDEBAR_W, HEADER_H + 1)
local content = make("CanvasGroup", {
Position = CONTENT_POS,
Size = UDim2.new(1, -SIDEBAR_W, 1, -(HEADER_H + 1)),
BackgroundTransparency = 1,
Parent = box,
})
local pageTitle = label({
Text = "",
Font = FONT_BLACK,
TextSize = 30,
TextColor3 = T.white,
Position = UDim2.fromOffset(PAD, 20),
Size = UDim2.new(1, -PAD * 2, 0, 34),
Parent = content,
})
local pageSub = label({
Text = "",
TextSize = 15,
TextColor3 = T.sub,
Position = UDim2.fromOffset(PAD, 56),
Size = UDim2.new(1, -PAD * 2, 0, 18),
Parent = content,
})
local scroller = make("ScrollingFrame", {
Position = UDim2.fromOffset(0, 88),
Size = UDim2.new(1, 0, 1, -88),
BackgroundTransparency = 1,
BorderSizePixel = 0,
CanvasSize = UDim2.new(),
AutomaticCanvasSize = Enum.AutomaticSize.Y,
ScrollBarThickness = 2,
ScrollBarImageColor3 = T.dim,
ScrollingDirection = Enum.ScrollingDirection.Y,
Parent = content,
}, { pad(0, 0, 0, 12) })
local TABS = { "Vehicle", "Stunts", "Visuals", "Player", "House", "Settings" }
local TAB_SUB = {
Vehicle = "Spawn, tune and drive",
Stunts = "Tricks on a key or in mid-air",
Visuals = "Paint, glow and camera",
Player = "Your roleplay name and session",
House = "Color and saved props",
Settings = "Interface and keybinds",
}
local pages, tabButtons = {}, {}
local activeTab
local function selectTab(name, instant)
if name == activeTab then return end
activeTab = name
pageTitle.Text = name
pageSub.Text = TAB_SUB[name]
scroller.CanvasPosition = Vector2.zero
for i, tabName in ipairs(TABS) do
local on = tabName == name
local tab = tabButtons[tabName]
pages[tabName].Visible = on
tab.label.Font = on and FONT_BOLD or FONT
tween(tab.label, { TextColor3 = on and T.white or T.sub, Position = UDim2.fromOffset(on and 20 or 16, 0) })
if on then
local y = TAB_TOP + (i - 1) * (TAB_H + TAB_GAP)
local info = instant and TweenInfo.new(0) or GLIDE
tween(tabHighlight, { Position = UDim2.fromOffset(10, y) }, info)
tween(tabIndicator, { Position = UDim2.fromOffset(10, y + (TAB_H - 18) / 2) }, info)
end
end
if not instant then
content.GroupTransparency = 1
content.Position = CONTENT_POS + UDim2.fromOffset(16, 0)
tween(content, { GroupTransparency = 0, Position = CONTENT_POS }, GLIDE)
end
end
for i, tabName in ipairs(TABS) do
pages[tabName] = make("Frame", {
Size = UDim2.new(1, 0, 0, 0),
AutomaticSize = Enum.AutomaticSize.Y,
BackgroundTransparency = 1,
Visible = false,
Parent = scroller,
}, { make("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder }) })
local btn = make("TextButton", {
LayoutOrder = i,
Text = "",
AutoButtonColor = false,
Size = UDim2.new(1, 0, 0, TAB_H),
BackgroundTransparency = 1,
BorderSizePixel = 0,
ZIndex = 3,
Parent = tabList,
})
local text = label({
Text = tabName,
TextSize = 16,
TextColor3 = T.sub,
Position = UDim2.fromOffset(16, 0),
Size = UDim2.new(1, -20, 1, 0),
ZIndex = 3,
Parent = btn,
})
bind(btn.MouseEnter, function()
if activeTab ~= tabName then tween(text, { TextColor3 = T.text }) end
end)
bind(btn.MouseLeave, function()
if activeTab ~= tabName then tween(text, { TextColor3 = T.sub }) end
end)
bind(btn.MouseButton1Click, function()
selectTab(tabName)
end)
tabButtons[tabName] = { btn = btn, label = text }
end
-- Rows ---------------------------------------------------------------------------------------
local Modules, ModuleByName = {}, {}
local bindingKey -- keybind waiting for a key press
local keyRows = {}
local function renderKeyRows()
for _, render in pairs(keyRows) do
render()
end
end
local carPicker, buildPicker, passNote
local unloadRef
-- The row builders and pages live in their own scope (Luau allows 200 locals per function).
do
local current -- page rows are added to
local function runSafely(title, fn)
task.spawn(function()
local ok, err = xpcall(fn, debug.traceback)
if not ok then
warn(err)
notify(title, "Something broke: " .. tostring(err):match("^[^\n]*"), "bad")
end
end)
end
local function hoverRow(btn)
bind(btn.MouseEnter, function() tween(btn, { BackgroundTransparency = 0 }) end)
bind(btn.MouseLeave, function() tween(btn, { BackgroundTransparency = 1 }) end)
end
-- Name on the left; an optional dim hint line under it.
local function rowText(parent, text, hint, rightSpace)
local nameLabel = label({
Text = text,
TextSize = 17,
Position = UDim2.fromOffset(0, hint and 10 or 0),
Size = UDim2.new(1, -rightSpace, 0, hint and 22 or 46),
TextTruncate = Enum.TextTruncate.AtEnd,
Parent = parent,
})
if hint then
label({
Text = hint,
TextSize = 13,
TextColor3 = T.dim,
Position = UDim2.fromOffset(0, 32),
Size = UDim2.new(1, -rightSpace, 0, 16),
TextTruncate = Enum.TextTruncate.AtEnd,
Parent = parent,
})
end
return nameLabel
end
local function sectionHeader(text)
local row = make("Frame", {
LayoutOrder = nextOrder(),
Size = UDim2.new(1, 0, 0, 34),
BackgroundTransparency = 1,
Parent = current,
}, { pad(PAD, PAD) })
local title = label({
Text = string.upper(text),
Font = FONT_BOLD,
TextSize = 12,
TextColor3 = T.sub,
Size = UDim2.fromScale(1, 1),
TextYAlignment = Enum.TextYAlignment.Bottom,
Parent = row,
})
pad(0, 0, 0, 4).Parent = title
end
-- def: { name, get, set, hint?, suffix?, array? (false = keep off the HUD list), quiet? }
local function toggleRow(def)
local btn = make("TextButton", {
LayoutOrder = nextOrder(),
Text = "",
AutoButtonColor = false,
Size = UDim2.new(1, 0, 0, def.hint and 60 or 46),
BackgroundColor3 = T.raised,
BackgroundTransparency = 1,
BorderSizePixel = 0,
Parent = current,
}, { pad(PAD, PAD) })
local nameLabel = rowText(btn, def.name, def.hint, 56)
local track = make("Frame", {
AnchorPoint = Vector2.new(1, 0.5),
Position = UDim2.new(1, 0, 0.5, 0),
Size = UDim2.fromOffset(40, 22),
BackgroundColor3 = T.off,
BorderSizePixel = 0,
Parent = btn,
}, { corner() })
local knob = make("Frame", {
AnchorPoint = Vector2.new(0, 0.5),
Position = UDim2.new(0, 3, 0.5, 0),
Size = UDim2.fromOffset(16, 16),
BackgroundColor3 = T.sub,
BorderSizePixel = 0,
Parent = track,
}, { corner() })
local m = { def = def, name = def.name }
function m.render(instant)
local on = def.get() == true
local info = instant and TweenInfo.new(0) or EASE
tween(nameLabel, { TextColor3 = on and T.white or T.text }, info)
tween(track, { BackgroundColor3 = on and T.white or T.off }, info)
tween(knob, {
Position = on and UDim2.new(1, -19, 0.5, 0) or UDim2.new(0, 3, 0.5, 0),
BackgroundColor3 = on and T.black or T.sub,
}, info)
end
hoverRow(btn)
bind(btn.MouseButton1Click, function()
local enabled = def.get() ~= true
def.set(enabled)
saveSoon()
m.render()
if Settings.toggleNotify and not def.quiet then
notify(def.name, enabled and "Enabled" or "Disabled", enabled and "good" or nil)
end
end)
m.render(true)
table.insert(Modules, m)
ModuleByName[def.name] = m
return m
end
local function setting(name, key, extra)
local def = {
name = name,
get = function() return Settings[key] end,
set = function(v) Settings[key] = v end,
}
for k, v in pairs(extra or {}) do
def[k] = v
end
return def
end
local function sliderRow(text, min, max, step, initial, format, onChange, onRelease)
local row = make("Frame", {
LayoutOrder = nextOrder(),
Size = UDim2.new(1, 0, 0, 62),
BackgroundTransparency = 1,
Parent = current,
}, { pad(PAD, PAD) })
label({ Text = text, TextSize = 16, TextColor3 = T.sub, Size = UDim2.new(1, -90, 0, 32), Parent = row })
local valueText = label({
Font = FONT_BOLD,
TextSize = 16,
TextColor3 = T.white,
AnchorPoint = Vector2.new(1, 0),
Position = UDim2.fromScale(1, 0),
Size = UDim2.fromOffset(90, 32),
TextXAlignment = Enum.TextXAlignment.Right,
Parent = row,
})
-- Tall invisible hit area around the thin track.
local hit = make("TextButton", {
Text = "",
AutoButtonColor = false,
Position = UDim2.fromOffset(0, 34),
Size = UDim2.new(1, 0, 0, 18),
BackgroundTransparency = 1,
Parent = row,
})
local track = make("Frame", {
AnchorPoint = Vector2.new(0, 0.5),
Position = UDim2.fromScale(0, 0.5),
Size = UDim2.new(1, 0, 0, 4),
BackgroundColor3 = T.off,
BorderSizePixel = 0,
Parent = hit,
}, { corner() })
local fill = make("Frame", { Size = UDim2.fromScale(0, 1), BackgroundColor3 = T.white, BorderSizePixel = 0, Parent = track }, { corner() })
local knob = make("Frame", {
AnchorPoint = Vector2.new(0.5, 0.5),
Position = UDim2.fromScale(0, 0.5),
Size = UDim2.fromOffset(16, 16),
BackgroundColor3 = T.white,
BorderSizePixel = 0,
Parent = track,
}, { corner() })
local value = math.clamp(initial, min, max)
local function render()
local a = (value - min) / (max - min)
fill.Size = UDim2.fromScale(a, 1)
knob.Position = UDim2.fromScale(a, 0.5)
valueText.Text = format(value)
end
local control = {
set = function(v)
value = math.clamp(v, min, max)
render()
onChange(value)
end,
}
local held = false
local function setFromX(x)
local a = math.clamp((x - track.AbsolutePosition.X) / track.AbsoluteSize.X, 0, 1)
local v = math.clamp(math.floor((min + a * (max - min)) / step + 0.5) * step, min, max)
if math.abs(v - value) > step / 2 then
value = v
render()
onChange(v)
end
end
local function isPress(input)
return input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch
end
bind(hit.InputBegan, function(input)
if isPress(input) then
held = true
setFromX(input.Position.X)
end
end)
bind(UserInputService.InputChanged, function(input)
if held and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
setFromX(input.Position.X)
end
end)
bind(UserInputService.InputEnded, function(input)
if held and isPress(input) then
held = false
saveSoon()
if onRelease then
runSafely(text, function() onRelease(value) end)
end
end
end)
render()
return control
end
-- A value on the right; click to open the options underneath.
local function choiceRow(text, initial, onChange)
local btn = make("TextButton", {
LayoutOrder = nextOrder(),
Text = "",
AutoButtonColor = false,
Size = UDim2.new(1, 0, 0, 46),
BackgroundColor3 = T.raised,
BackgroundTransparency = 1,
BorderSizePixel = 0,
Parent = current,
}, { pad(PAD, PAD) })
label({ Text = text, TextSize = 17, Size = UDim2.new(0.45, 0, 1, 0), Parent = btn })
local valueText = label({
Font = FONT_BOLD,
TextSize = 16,
TextColor3 = T.white,
AnchorPoint = Vector2.new(1, 0),
Position = UDim2.new(1, -20, 0, 0),
Size = UDim2.new(0.55, -20, 1, 0),
TextXAlignment = Enum.TextXAlignment.Right,
TextTruncate = Enum.TextTruncate.AtEnd,
Parent = btn,
})
local arrow = label({
Text = "›",
Font = FONT_BOLD,
TextSize = 22,
TextColor3 = T.sub,
AnchorPoint = Vector2.new(1, 0.5),
Position = UDim2.new(1, 0, 0.5, -2),
Size = UDim2.fromOffset(12, 22),
TextXAlignment = Enum.TextXAlignment.Center,
Parent = btn,
})
local list = make("Frame", {
LayoutOrder = nextOrder(),
Size = UDim2.new(1, 0, 0, 0),
AutomaticSize = Enum.AutomaticSize.Y,
BackgroundColor3 = T.side,
BorderSizePixel = 0,
Visible = false,
Parent = current,
}, {
make("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder }),
pad(0, 0, 4, 4),
})
hoverRow(btn)
local selected = initial
local options = {}
local function setOpen(open)
list.Visible = open
tween(arrow, { Rotation = open and 90 or 0 })
end
local function render()
for _, child in ipairs(list:GetChildren()) do
if child:IsA("TextButton") then child:Destroy() end
end
local selectedLabel
for i, option in ipairs(options) do
local isSelected = option.value == selected
if isSelected then selectedLabel = option.label end
local b = make("TextButton", {
LayoutOrder = i,
Text = "",
AutoButtonColor = false,
Size = UDim2.new(1, 0, 0, 34),
BackgroundColor3 = T.raised,
BackgroundTransparency = 1,
BorderSizePixel = 0,
Parent = list,
}, { pad(PAD + 14, PAD) })
label({
Text = option.label,
Font = isSelected and FONT_BOLD or FONT,
TextSize = 15,
TextColor3 = isSelected and T.white or T.sub,
Size = UDim2.fromScale(1, 1),
Parent = b,
})
if isSelected then
make("Frame", {
AnchorPoint = Vector2.new(0, 0.5),
Position = UDim2.new(0, -12, 0.5, 0),
Size = UDim2.fromOffset(3, 14),
BackgroundColor3 = T.white,
BorderSizePixel = 0,
Parent = b,
}, { corner() })
end
hoverRow(b)
bind(b.MouseButton1Click, function()
selected = option.value
setOpen(false)
render()
onChange(option.value)
saveSoon()
end)
end
valueText.Text = selectedLabel or (#options > 0 and "Choose" or "Loading…")
end
bind(btn.MouseButton1Click, function()
if #options > 0 then setOpen(not list.Visible) end
end)
render()
return {
setOptions = function(newOptions, newSelected)
options = newOptions
if newSelected ~= nil then selected = newSelected end
render()
end,
}
end
local function namesToOptions(names)
local options = {}
for _, name in ipairs(names) do
table.insert(options, { value = name, label = name })
end
return options
end
-- A pill button on the right, styled like Unload: white on hover.
local function actionRow(text, buttonText, fn, hint)
local row = make("Frame", {
LayoutOrder = nextOrder(),
Size = UDim2.new(1, 0, 0, hint and 60 or 46),
BackgroundTransparency = 1,
Parent = current,
}, { pad(PAD, PAD) })
rowText(row, text, hint, 130)
local button = make("TextButton", {
Text = buttonText,
Font = FONT_BOLD,
TextSize = 14,
TextColor3 = T.text,
AutoButtonColor = false,
AnchorPoint = Vector2.new(1, 0.5),
Position = UDim2.new(1, 0, 0.5, 0),
Size = UDim2.fromOffset(0, 30),
AutomaticSize = Enum.AutomaticSize.X,
BackgroundColor3 = T.raised,
BorderSizePixel = 0,
Parent = row,
}, { corner(6), pad(16, 16) })
bind(button.MouseEnter, function() tween(button, { BackgroundColor3 = T.white, TextColor3 = T.black }) end)
bind(button.MouseLeave, function() tween(button, { BackgroundColor3 = T.raised, TextColor3 = T.text }) end)
bind(button.MouseButton1Click, function()
runSafely(text, fn)
end)
return button
end
local function inputRow(text, placeholder, initial, onCommit)
local row = make("Frame", {
LayoutOrder = nextOrder(),
Size = UDim2.new(1, 0, 0, 50),
BackgroundTransparency = 1,
Parent = current,
}, { pad(PAD, PAD) })
rowText(row, text, nil, 260)
local boxField = make("TextBox", {
Text = initial,
PlaceholderText = placeholder,
PlaceholderColor3 = T.dim,
ClearTextOnFocus = false,
Font = FONT,
TextSize = 15,
TextColor3 = T.white,
TextXAlignment = Enum.TextXAlignment.Left,
TextTruncate = Enum.TextTruncate.AtEnd,
AnchorPoint = Vector2.new(1, 0.5),
Position = UDim2.new(1, 0, 0.5, 0),
Size = UDim2.fromOffset(250, 32),
BackgroundColor3 = T.raised,
BorderSizePixel = 0,
Parent = row,
}, { corner(6), pad(12, 12) })
local stroke = make("UIStroke", { Color = T.line, ApplyStrokeMode = Enum.ApplyStrokeMode.Border, Parent = boxField })
local committed = initial
bind(boxField.Focused, function() tween(stroke, { Color = T.sub }) end)
bind(boxField.FocusLost, function()
tween(stroke, { Color = T.line })
if boxField.Text ~= committed then
committed = boxField.Text
onCommit(boxField.Text)
end
end)
end
local function swatchRow(text, colors, onPick)
local row = make("Frame", {
LayoutOrder = nextOrder(),
Size = UDim2.new(1, 0, 0, 46),
BackgroundTransparency = 1,
Parent = current,
}, { pad(PAD, PAD) })
rowText(row, text, nil, 240)
local holder = make("Frame", {
AnchorPoint = Vector2.new(1, 0.5),
Position = UDim2.new(1, 0, 0.5, 0),
Size = UDim2.fromOffset(230, 22),
BackgroundTransparency = 1,
Parent = row,
}, {
make("UIListLayout", {
FillDirection = Enum.FillDirection.Horizontal,
HorizontalAlignment = Enum.HorizontalAlignment.Right,
VerticalAlignment = Enum.VerticalAlignment.Center,
SortOrder = Enum.SortOrder.LayoutOrder,
Padding = UDim.new(0, 8),
}),
})
for i, color in ipairs(colors) do
local swatch = make("TextButton", {
LayoutOrder = i,
Text = "",
AutoButtonColor = false,
Size = UDim2.fromOffset(22, 22),
BackgroundColor3 = color,
BorderSizePixel = 0,
Parent = holder,
}, { corner() })
local stroke = make("UIStroke", { Color = T.off, Thickness = 1.5, Parent = swatch })
bind(swatch.MouseEnter, function() tween(stroke, { Color = T.white }) end)
bind(swatch.MouseLeave, function() tween(stroke, { Color = T.off }) end)
bind(swatch.MouseButton1Click, function()
runSafely(text, function() onPick(color) end)
end)
end
end
local function keyRow(text, bindName, hint)
local btn = make("TextButton", {
LayoutOrder = nextOrder(),
Text = "",
AutoButtonColor = false,
Size = UDim2.new(1, 0, 0, hint and 60 or 46),
BackgroundColor3 = T.raised,
BackgroundTransparency = 1,
BorderSizePixel = 0,
Parent = current,
}, { pad(PAD, PAD) })
rowText(btn, text, hint, 150)
local pill = make("TextLabel", {
AnchorPoint = Vector2.new(1, 0.5),
Position = UDim2.new(1, 0, 0.5, 0),
Size = UDim2.fromOffset(0, 30),
AutomaticSize = Enum.AutomaticSize.X,
BackgroundColor3 = T.raised,
Font = FONT_BOLD,
TextSize = 14,
TextColor3 = T.white,
Text = "",
Parent = btn,
}, { corner(6), pad(14, 14) })
keyRows[bindName] = function()
local waiting = bindingKey == bindName
pill.Text = waiting and "Press a key…" or (Settings.binds[bindName] or "None")
pill.BackgroundColor3 = waiting and T.white or T.raised
pill.TextColor3 = waiting and T.black or T.white
end
hoverRow(btn)
bind(btn.MouseButton1Click, function()
bindingKey = bindName
renderKeyRows()
end)
keyRows[bindName]()
end
local function note(text)
return label({
LayoutOrder = nextOrder(),
Text = text,
TextSize = 13,
TextColor3 = T.dim,
Size = UDim2.new(1, 0, 0, 36),
TextXAlignment = Enum.TextXAlignment.Center,
TextWrapped = true,
Parent = current,
})
end
refreshModule = function(name)
local m = ModuleByName[name]
if m then
m.render()
end
end
local function fmtTimes(v) return string.format("%.1fx", v) end
---------------------------------------------------------------------------------------------
-- Pages
---------------------------------------------------------------------------------------------
-- Vehicle -------------------------------------------------------------------------------------
current = pages.Vehicle
passNote = note("Checking your gamepasses…")
sectionHeader("Spawn")
carPicker = choiceRow("Car", Settings.car, function(value)
Settings.car = value
end)
actionRow("Spawn car", "Spawn", spawnCar, "Get out of any seat first")
toggleRow(setting("Auto-tune", "autoTune", {
hint = "Top speed, turbo, grip and underglow as soon as you get in",
array = false,
}))
sectionHeader("Handling")
toggleRow(setting("Performance", "performance", {
hint = "Harder launches and quicker steering; top speed stays at your cap",
set = function(v)
Settings.performance = v
applyPhysics()
end,
suffix = function() return fmtTimes(Settings.accel) end,
}))
-- Brookhaven turns the wheels toward the target angle at TurnSpeed per second (about 60 is
-- instant), and ramps throttle and power from Turbo and Torque, which Acceleration scales.
local accelSlider = sliderRow("Acceleration", 1, 5, 0.1, Settings.accel, fmtTimes, function(v)
Settings.accel = v
applyPhysics()
end)
local steerSlider = sliderRow("Steering response", 1, 6, 0.1, Settings.steer, fmtTimes, function(v)
Settings.steer = v
applyPhysics()
end)
actionRow("Max response", "Max out", function()
Settings.performance = true
refreshModule("Performance")
accelSlider.set(5)
steerSlider.set(6)
saveSoon()
notify("Max response", "Acceleration 5x · steering 6x", "good")
end, "Fastest launches and near-instant steering")
toggleRow(setting("Grip", "handling", {
hint = "No sliding in sharp turns; capped per car so tall ones can't flip",
set = function(v)
Settings.handling = v
applyTires()
end,
}))
sliderRow("Tire grip", 0.5, 2, 0.05, Settings.tireGrip, function(v) return string.format("%.2f", v) end, function(v)
Settings.tireGrip = v
applyTires()
end, function()
local s = Session
if s and tuningTires(s) then
local grip = tireFriction(s)
local ok, msg = carRequest("SetDriftStrength", math.min(grip, 1.5))
if not ok then
notify("Grip", "Refused: " .. tostring(msg), "bad")
elseif grip < Settings.tireGrip then
notify("Grip", string.format("Capped at %.2f so this car can't flip", grip))
end
end
end)
sliderRow("Stability control", 0, 100, 5, Settings.traction, function(v) return string.format("%d%%", v) end, function(v)
Settings.traction = v
end)
toggleRow(setting("Anti-flip", "antiRoll", { array = false }))
toggleRow(setting("Downforce", "grip", { array = false }))
toggleRow(setting("Brake Assist", "brakeAssist", {
hint = "Much harder braking when you press against your direction",
suffix = function() return string.format("%.1fg", Settings.brakeStrength) end,
}))
sliderRow("Brake strength", 0.5, 2, 0.1, Settings.brakeStrength, function(v) return string.format("%.1fg", v) end, function(v)
Settings.brakeStrength = v
end)
toggleRow(setting("Drift Mode", "drift", {
hint = "Hold the drift key (Settings → Keybinds) to let the rear slide",
set = function(v)
Settings.drift = v
if not v and Session and Session.drifting then
Session.drifting = false
applyTires()
end
end,
}))
sliderRow("Drift grip", 0.1, 1, 0.05, Settings.driftGrip, function(v) return string.format("%.2f", v) end, function(v)
Settings.driftGrip = v
if Session and Session.drifting then applyTires() end
end)
sectionHeader("Car")
toggleRow(setting("Auto Flip", "autoFlip", { hint = "Puts the car back on its wheels if it ends up on its roof" }))
toggleRow(setting("Auto Headlights", "autoLights", { hint = "Lights on at night and off in the day; V still works" }))
sliderRow("Ride height", 0, 4, 1, Settings.rideHeight, function(v)
return v == 0 and "Car default" or ("Level " .. v)
end, function(v)
Settings.rideHeight = v
end)
actionRow("Apply ride height", "Apply", function()
if not Session then
notify("Ride height", "Get in your car first", "bad")
return
end
local level = Settings.rideHeight > 0 and Settings.rideHeight or defaultRideLevel(Session.car)
if not level then
notify("Ride height", "This car has no ride height settings", "bad")
return
end
local ok, msg = carRequest("SetSuspensionLevel", level)
notify("Ride height", ok and ("Level " .. level) or ("Refused: " .. tostring(msg)), ok and "good" or "bad")
end)
actionRow("Flip upright", "Flip", function()
local ok, msg = carRequest("RepositionVehicle")
notify("Flip upright", ok and "Car repositioned" or ("Refused: " .. tostring(msg)), ok and "good" or "bad")
end)
actionRow("Headlights", "Toggle", function()
local s = Session
if not s then
notify("Headlights", "Get in your car first", "bad")
return
end
-- The server answers with the new light state, not a success flag.
local called, lightsOn = invoke("ToggleHeadLights")
if called and type(lightsOn) == "boolean" then
s.lightsOn = lightsOn
notify("Headlights", lightsOn and "On" or "Off", "good")
else
notify("Headlights", "Request failed: " .. tostring(lightsOn), "bad")
end
end)
toggleRow({
name = "Fire",
quiet = true,
array = false,
get = function() return Session ~= nil and Session.car:GetAttribute("OnFire") == true end,
set = function(v) task.spawn(setCarEffect, "OnFire", "ToggleOnFire", v) end,
})
toggleRow({
name = "Engine Smoke",
quiet = true,
array = false,
get = function() return Session ~= nil and Session.car:GetAttribute("Smoking") == true end,
set = function(v) task.spawn(setCarEffect, "Smoking", "ToggleEngineSmoke", v) end,
})
-- Stunts --------------------------------------------------------------------------------------
current = pages.Stunts
local stuntNames = {}
for _, def in ipairs(STUNTS) do
table.insert(stuntNames, def.name)
end
sectionHeader("On a key")
choiceRow("Trick", Settings.stunt, function(value)
Settings.stunt = value
end).setOptions(namesToOptions(stuntNames))
sliderRow("Airtime", 0.8, 2.5, 0.1, Settings.stuntAirtime, function(v) return string.format("%.1fs", v) end, function(v)
Settings.stuntAirtime = v
end)
actionRow("Do the trick", "Go", function()
performStunt(findStunt(Settings.stunt), Settings.stuntAirtime, "Stunt")
end, "Or press your Stunt key while driving, even mid-jump")
actionRow("Car hop", "Hop", function()
performStunt(HOP, Settings.hopAirtime, "Car Hop")
end, "A quick hop that lands flat; or press your Car Hop key")
sliderRow("Hop airtime", 0.3, 1.2, 0.05, Settings.hopAirtime, function(v) return string.format("%.2fs", v) end, function(v)
Settings.hopAirtime = v
end)
sectionHeader("In the air")
toggleRow(setting("Air Stunts", "airStunts", {
hint = "Drive off something high and the car does the trick by itself",
suffix = function() return Settings.airTrick end,
}))
do
local options = namesToOptions(stuntNames)
table.insert(options, { value = "Random", label = "Random" })
choiceRow("Air trick", Settings.airTrick, function(value)
Settings.airTrick = value
end).setOptions(options)
end
toggleRow(setting("Every Jump", "airAlways", {
hint = "Any jump gets the trick: short ones get a boost so it always finishes",
array = false,
}))
sliderRow("Minimum jump", 0.1, 0.8, 0.05, Settings.airMin, function(v) return string.format("%.2fs", v) end, function(v)
Settings.airMin = v
end)
note("Jumps shorter than this are ignored, so curbs and bumps never flip you.")
toggleRow(setting("Landing Assist", "landAssist", { hint = "Jumps too short for a trick still land flat on four wheels" }))
toggleRow(setting("Stunt Trail", "stuntTrail", { hint = "White streaks behind the car in the air (only you see them)" }))
-- Visuals -------------------------------------------------------------------------------------
current = pages.Visuals
sectionHeader("Paint")
toggleRow(setting("Car RGB", "carRGB", {
hint = "Smooth color fade, driving or parked; off puts your color back",
set = function(v) setCarRGB(v) end,
suffix = function() return Settings.rgbMode end,
}))
choiceRow("Mode", Settings.rgbMode, function(value)
Settings.rgbMode = value
end).setOptions(namesToOptions(RGB_MODES))
sliderRow("Cycle length", 1, 20, 0.5, Settings.rgbCycle, function(v) return string.format("%.1fs", v) end, function(v)
Settings.rgbCycle = v
end)
swatchRow("Paint once", SWATCHES, function(color)
local car = ownCar()
if not car then
notify("Paint", "Spawn a car first", "bad")
return
end
if Settings.carRGB then
Settings.carRGB = false
saveSoon()
refreshModule("Car RGB")
task.wait(0.4) -- let any in-flight RGB step land first
end
local ok, msg = paintCar(car, color)
if ok then
originalPaints[car] = color
notify("Paint", "Car painted", "good")
else
notify("Paint", "Refused: " .. tostring(msg), "bad")
end
end)
sectionHeader("Underglow")
toggleRow(setting("RGB Underglow", "rainbowGlow", { hint = "Glow follows your paint, or rainbows on its own" }))
choiceRow("Style", Settings.underglow, function(value)
Settings.underglow = value
end).setOptions(namesToOptions(UNDERGLOWS))
sliderRow("Length", 0.1, 1.5, 0.05, Settings.glowLength, function(v) return string.format("%.2f", v) end, function(v)
Settings.glowLength = v
end)
sliderRow("Width", 0.1, 1.5, 0.05, Settings.glowWidth, function(v) return string.format("%.2f", v) end, function(v)
Settings.glowWidth = v
end)
actionRow("Apply underglow", "Apply", function()
local ok, msg = carRequest("SetUnderglow", Settings.underglow)
if ok then
carRequest("SetUnderglowSize", Settings.glowLength, Settings.glowWidth)
notify("Underglow", Settings.underglow, "good")
else
notify("Underglow", "Refused: " .. tostring(msg), "bad")
end
end)
sectionHeader("Camera and world")
toggleRow(setting("Speedometer", "speedo", {}))
toggleRow(setting("Fullbright", "fullbright", {
set = function(v)
Settings.fullbright = v
syncLightingSnapshot()
end,
}))
local function hourText(v)
return string.format("%02d:%s", math.floor(v) % 24, v % 1 >= 0.5 and "30" or "00")
end
toggleRow(setting("Time Lock", "lockTime", {
set = function(v)
Settings.lockTime = v
syncLightingSnapshot()
end,
suffix = function() return hourText(Settings.hour) end,
}))
sliderRow("Hour", 0, 24, 0.5, Settings.hour, hourText, function(v)
Settings.hour = v
end)
toggleRow(setting("FOV", "fovOn", {
set = function(v)
Settings.fovOn = v
syncFov()
end,
suffix = function() return tostring(Settings.fov) end,
}))
sliderRow("Field of view", 50, 120, 1, Settings.fov, tostring, function(v)
Settings.fov = v
end)
toggleRow(setting("Unlock Zoom", "unlockZoom", {
set = function(v)
Settings.unlockZoom = v
syncZoom()
end,
}))
-- Player --------------------------------------------------------------------------------------
current = pages.Player
sectionHeader("Roleplay")
-- Brookhaven ignores blank names and bios (tested), so an empty box only stops re-applying it.
inputRow("Name", "Shown above your head", Settings.rpName, function(text)
Settings.rpName = text
saveSoon()
if text:gsub("%s", "") == "" then
notify("Roleplay name", "Brookhaven won't blank a name; it won't be re-applied")
return
end
NameTextEvent:FireServer("RolePlayName", text)
notify("Roleplay name", "Set to " .. text, "good")
end)
inputRow("Bio", "Shown under your name", Settings.rpBio, function(text)
Settings.rpBio = text
saveSoon()
if text:gsub("%s", "") == "" then
notify("Roleplay bio", "Brookhaven won't blank a bio; it won't be re-applied")
return
end
NameTextEvent:FireServer("RolePlayBio", text)
notify("Roleplay bio", "Bio updated", "good")
end)
toggleRow(setting("Rainbow Name", "rainbowName", {
hint = "Cycles your roleplay name's color (needs a name set)",
set = function(v)
Settings.rainbowName = v
if not v then
task.delay(1.2, function()
if alive and not Settings.rainbowName then
NameColorEvent:FireServer("PickingRPNameColor", Color3.new(1, 1, 1))
end
end)
end
end,
}))
sectionHeader("Session")
toggleRow(setting("Anti-AFK", "antiAfk", { hint = "Stops the 20-minute idle kick" }))
-- House ---------------------------------------------------------------------------------------
current = pages.House
sectionHeader("Color")
toggleRow(setting("Rainbow House", "houseRainbow", {
hint = "Your house fades through the colors; starts when you claim one",
suffix = function() return string.format("%ds", Settings.houseCycle) end,
}))
sliderRow("Cycle length", 6, 60, 1, Settings.houseCycle, function(v) return string.format("%ds", v) end, function(v)
Settings.houseCycle = v
end)
swatchRow("Paint once", SWATCHES, function(color)
if HouseNumber.Value <= 0 then
notify("House paint", "Claim a house first", "bad")
return
end
Settings.houseRainbow = false
saveSoon()
refreshModule("Rainbow House")
setHouseColor(color)
notify("House paint", "House painted", "good")
end)
sectionHeader("Saved props")
buildPicker = choiceRow("Build", Settings.buildSlot, function(value)
Settings.buildSlot = value
end)
actionRow("Load props", "Load", function()
loadBuild(Settings.buildSlot)
end, "Into the house you own")
toggleRow(setting("Load on claim", "loadBuild", {
hint = "Loads the build when you claim a house",
array = false,
}))
-- Settings ------------------------------------------------------------------------------------
current = pages.Settings
sectionHeader("Interface")
toggleRow(setting("ArrayList", "arraylist", { hint = "Enabled modules in the top-right corner", array = false }))
toggleRow(setting("Toggle alerts", "toggleNotify", { hint = "A notification when you switch something on or off", array = false, quiet = true }))
toggleRow(setting("Background blur", "blur", {
array = false,
set = function(v)
Settings.blur = v
tween(menuBlur, { Size = (v and menuOpen) and 14 or 0 })
end,
}))
actionRow("Recenter menu", "Reset", function()
basePos = UDim2.fromScale(0.5, 0.5)
tween(box, { Position = basePos }, GLIDE)
end)
sectionHeader("Keybinds")
keyRow("Stunt", "Stunt")
keyRow("Car hop", "Car Hop")
keyRow("Drift (hold)", "Drift")
note("Click a key, then press the new one. Esc clears it. RightShift opens this menu.")
-- Unload button (bottom of the sidebar), styled like Snitch's.
do
local btn = make("TextButton", {
Text = "Unload",
Font = FONT_BOLD,
TextSize = 15,
TextColor3 = T.text,
AutoButtonColor = false,
Size = UDim2.fromScale(1, 1),
BackgroundColor3 = T.raised,
BorderSizePixel = 0,
Parent = unloadHolder,
}, { corner(6) })
bind(btn.MouseEnter, function() tween(btn, { BackgroundColor3 = T.white, TextColor3 = T.black }) end)
bind(btn.MouseLeave, function() tween(btn, { BackgroundColor3 = T.raised, TextColor3 = T.text }) end)
bind(btn.MouseButton1Click, function()
if unloadRef then unloadRef() end
end)
end
end
---------------------------------------------------------------------------------------------
-- HUD (always on screen): Minecraft-client arraylist, top right, sorted longest first
---------------------------------------------------------------------------------------------
local placeArrayList
do
local HUD_FONT = Enum.Font.Arcade
local HUD_SIZE = 15
local HUD_LINE = 23
local SHADOW = Color3.fromRGB(38, 38, 40)
local hud = make("Frame", {
AnchorPoint = Vector2.new(1, 0),
Position = UDim2.new(1, -4, 0, 4),
Size = UDim2.fromOffset(400, 560),
BackgroundTransparency = 1,
Parent = Gui,
}, {
make("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder, HorizontalAlignment = Enum.HorizontalAlignment.Right }),
})
-- Text with a 1px Minecraft shadow; returns the white label (the shadow follows its Text).
local function shadowText(parent, layoutOrder, size, color, height)
local holder = make("Frame", {
LayoutOrder = layoutOrder,
Size = UDim2.fromOffset(0, height),
AutomaticSize = Enum.AutomaticSize.X,
BackgroundTransparency = 1,
Parent = parent,
})
local shadow = label({
Text = "",
Font = HUD_FONT,
TextSize = size,
TextColor3 = SHADOW,
Position = UDim2.fromOffset(1, 1),
Size = UDim2.fromOffset(0, height),
AutomaticSize = Enum.AutomaticSize.X,
Parent = holder,
})
local main = label({
Text = "",
Font = HUD_FONT,
TextSize = size,
TextColor3 = color,
Size = UDim2.fromOffset(0, height),
AutomaticSize = Enum.AutomaticSize.X,
Parent = holder,
})
bind(main:GetPropertyChangedSignal("Text"), function()
shadow.Text = main.Text
end)
return main, holder
end
local watermark = make("Frame", {
LayoutOrder = -1000000,
Size = UDim2.fromOffset(0, 30),
AutomaticSize = Enum.AutomaticSize.X,
BackgroundTransparency = 1,
Parent = hud,
}, { pad(0, 4) })
local wmText = shadowText(watermark, 1, 22, T.white, 30)
wmText.Text = "BH STUDIO"
-- Lines: [name][suffix][gap][bar]. The list layout places every child, so the white bar is
-- the last item in the row rather than an absolutely positioned frame.
local hudEntries = {}
for _, m in ipairs(Modules) do
if m.def.array ~= false then
local frame = make("Frame", {
Size = UDim2.fromOffset(0, HUD_LINE),
AutomaticSize = Enum.AutomaticSize.X,
BackgroundColor3 = T.black,
BackgroundTransparency = 0.5,
BorderSizePixel = 0,
Visible = false,
Parent = hud,
}, {
pad(6, 0),
make("UIListLayout", {
FillDirection = Enum.FillDirection.Horizontal,
VerticalAlignment = Enum.VerticalAlignment.Center,
SortOrder = Enum.SortOrder.LayoutOrder,
Padding = UDim.new(0, 7),
}),
})
local main = shadowText(frame, 1, HUD_SIZE, T.white, HUD_LINE)
main.Text = m.name
local suffix, suffixHolder = shadowText(frame, 2, HUD_SIZE, T.sub, HUD_LINE)
local bar = make("Frame", {
LayoutOrder = 3,
Size = UDim2.fromOffset(2, HUD_LINE),
BackgroundColor3 = T.white,
BorderSizePixel = 0,
Parent = frame,
})
table.insert(hudEntries, { m = m, frame = frame, main = main, suffix = suffix, suffixHolder = suffixHolder, bar = bar })
end
end
-- Brookhaven's HUD owns the top-right corner (clock and ad icons along the top, the menu
-- column down the right edge), so the list sits just inside it. Measured from the live HUD
-- so it fits any screen size.
local function shownOnScreen(inst, screenGui)
local node = inst
while node and node ~= screenGui do
if node:IsA("GuiObject") and not node.Visible then return false end
node = node.Parent
end
return true
end
placeArrayList = function()
local screen = Gui.AbsoluteSize
local origin = Gui.AbsolutePosition
local column, topRow = {}, {}
for _, screenGui in ipairs(LocalPlayer.PlayerGui:GetChildren()) do
if screenGui:IsA("ScreenGui") and screenGui.Enabled then
for _, d in ipairs(screenGui:GetDescendants()) do
if (d:IsA("GuiButton") or d:IsA("ImageLabel") or d:IsA("TextLabel")) and d.Visible and d.AbsoluteSize.X > 20 then
local x = d.AbsolutePosition.X - origin.X
local y = d.AbsolutePosition.Y - origin.Y
local w, h = d.AbsoluteSize.X, d.AbsoluteSize.Y
if d:IsA("GuiButton") and x + w > screen.X - 24 and y < screen.Y * 0.7 and shownOnScreen(d, screenGui) then
table.insert(column, x)
elseif x + w > screen.X - 480 and y < 80 and h < 80 and shownOnScreen(d, screenGui) then
table.insert(topRow, { x + w, y + h })
end
end
end
end
end
local right = 4
for _, x in ipairs(column) do
right = math.max(right, screen.X - x + 8)
end
-- Only top-row items above the list's own span (entries are under ~220 px wide) push it down.
local top = 4
for _, item in ipairs(topRow) do
if item[1] > screen.X - right - 220 then
top = math.max(top, item[2] + 6)
end
end
hud.Position = UDim2.new(1, -right, 0, top)
end
-- Every line sorted by its rendered width, widest on top; a slow white-to-grey wave rolls
-- down the list (the monochrome take on the client rainbow).
bind(RunService.RenderStepped, function()
hud.Visible = Settings.arraylist
if not Settings.arraylist then return end
local visible = {}
for _, e in ipairs(hudEntries) do
local on = e.m.def.get() == true
if on and not e.frame.Visible then
e.frame.Visible = true
e.main.TextTransparency = 1
tween(e.main, { TextTransparency = 0 })
elseif not on and e.frame.Visible then
e.frame.Visible = false
end
if on then
local text = e.m.def.suffix and e.m.def.suffix() or ""
if e.suffix.Text ~= text then e.suffix.Text = text end
e.suffixHolder.Visible = text ~= ""
table.insert(visible, e)
end
end
table.sort(visible, function(a, b)
local wa, wb = a.frame.AbsoluteSize.X, b.frame.AbsoluteSize.X
if wa ~= wb then return wa > wb end
return a.m.name < b.m.name
end)
local t = os.clock()
local function wave(i)
local k = 0.5 + 0.5 * math.sin(t * 2.2 - i * 0.55)
return Color3.fromRGB(245, 245, 245):Lerp(Color3.fromRGB(150, 150, 154), k)
end
wmText.TextColor3 = wave(0)
for i, e in ipairs(visible) do
e.frame.LayoutOrder = i
local color = wave(i)
e.main.TextColor3 = color
e.bar.BackgroundColor3 = color
end
end)
end
---------------------------------------------------------------------------------------------
-- Speedometer (your screen only). Speed is studs/s converted at 1 stud = 0.28 m.
---------------------------------------------------------------------------------------------
do
local Speedo = scaled(make("Frame", {
Name = "Speedometer",
AnchorPoint = Vector2.new(0.5, 1),
Position = UDim2.new(0.5, 0, 1, -24),
Size = UDim2.fromOffset(230, 64),
BackgroundColor3 = T.bg,
BackgroundTransparency = 0.04,
BorderSizePixel = 0,
Visible = false,
Parent = Gui,
}, {
corner(10),
make("UIStroke", { Color = T.line, ApplyStrokeMode = Enum.ApplyStrokeMode.Border }),
}))
local speedNumber = label({
Text = "0",
Font = FONT_BLACK,
TextSize = 30,
TextColor3 = T.white,
Position = UDim2.fromOffset(16, 7),
Size = UDim2.fromOffset(90, 32),
Parent = Speedo,
})
label({
Text = "MPH",
Font = FONT_BOLD,
TextSize = 11,
TextColor3 = T.sub,
Position = UDim2.fromOffset(17, 40),
Size = UDim2.fromOffset(60, 12),
Parent = Speedo,
})
local speedCar = label({
Text = "",
TextSize = 13,
TextColor3 = T.sub,
Position = UDim2.fromOffset(104, 13),
Size = UDim2.new(1, -120, 0, 16),
TextXAlignment = Enum.TextXAlignment.Right,
TextTruncate = Enum.TextTruncate.AtEnd,
Parent = Speedo,
})
local speedTrack = make("Frame", {
Position = UDim2.fromOffset(104, 39),
Size = UDim2.new(1, -120, 0, 4),
BackgroundColor3 = T.off,
BorderSizePixel = 0,
Parent = Speedo,
}, { corner() })
local speedFill = make("Frame", { Size = UDim2.new(0, 0, 1, 0), BackgroundColor3 = T.white, BorderSizePixel = 0, Parent = speedTrack }, { corner() })
local shownSpeed = 0
bind(RunService.RenderStepped, function(dt)
local s = Session
local driving = s ~= nil
Speedo.Visible = Settings.speedo and driving
if not driving then
shownSpeed = 0
return
end
local root = s.seat.AssemblyRootPart
local mph = root and root.AssemblyLinearVelocity.Magnitude * 0.28 * 2.237 or 0
shownSpeed += (mph - shownSpeed) * math.min(dt * 8, 1)
local whole = math.floor(shownSpeed + 0.5)
if Settings.speedo then
speedNumber.Text = tostring(whole)
speedFill.Size = UDim2.new(math.clamp(shownSpeed / 160, 0, 1), 0, 1, 0)
speedCar.Text = s.car:GetAttribute("vehicleName") or ""
end
if menuOpen and cardActive then
local parts = { whole .. " mph", stuntCount .. (stuntCount == 1 and " stunt" or " stunts") }
if cardNote ~= "" then
table.insert(parts, 1, cardNote)
end
cardLine.Text = table.concat(parts, " · ")
end
end)
end
---------------------------------------------------------------------------------------------
-- Opening, closing, dragging and keys
---------------------------------------------------------------------------------------------
local dragging = false
do
local dragStart, startPos
bind(header.InputBegan, function(input)
if menuOpen and (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then
dragging, dragStart, startPos = true, input.Position, box.Position
end
end)
bind(UserInputService.InputChanged, function(input)
if dragging and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
local d = input.Position - dragStart
box.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + d.X, startPos.Y.Scale, startPos.Y.Offset + d.Y)
basePos = box.Position
end
end)
bind(UserInputService.InputEnded, function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
dragging = false
end
end)
end
local function setMenu(open)
menuOpen = open
modal.Modal = open
modal.Visible = open
dragging = false
if open then
box.Visible = true
box.Position = basePos
-- Never open partly off-screen.
local pos, size, screen = box.AbsolutePosition, box.AbsoluteSize, Gui.AbsoluteSize
if pos.X < 0 or pos.Y < 0 or pos.X + size.X > screen.X or pos.Y + size.Y > screen.Y then
basePos = UDim2.fromScale(0.5, 0.5)
box.Position = basePos
end
boxScale.Scale = guiScale * 0.94
local info = TweenInfo.new(0.34, Enum.EasingStyle.Quint, Enum.EasingDirection.Out)
tween(box, { GroupTransparency = 0 }, info)
tween(boxScale, { Scale = guiScale }, info)
tween(menuBlur, { Size = Settings.blur and 14 or 0 }, info)
refreshVehicleStatus()
else
if bindingKey then
bindingKey = nil
renderKeyRows()
end
local info = TweenInfo.new(0.18, Enum.EasingStyle.Quad, Enum.EasingDirection.In)
tween(box, { GroupTransparency = 1 }, info)
tween(boxScale, { Scale = guiScale * 0.96 }, info)
tween(menuBlur, { Size = 0 }, info)
task.delay(0.2, function()
if not menuOpen then box.Visible = false end
end)
end
end
local function setDrift(on)
local s = Session
if not s or not s.geom.valid or s.drifting == on then return end
s.drifting = on
applyTires()
end
-- The game binds Shift itself, so RightShift can arrive as "processed": only ignore keys
-- while you're typing in a text box (chat etc.).
bind(UserInputService.InputBegan, function(input)
if input.UserInputType ~= Enum.UserInputType.Keyboard then return end
if bindingKey then
local name = bindingKey
bindingKey = nil
if input.KeyCode == Enum.KeyCode.Escape or input.KeyCode == Enum.KeyCode.Backspace then
Settings.binds[name] = nil
notify("Keybinds", name .. " cleared")
elseif input.KeyCode ~= Enum.KeyCode.RightShift then
Settings.binds[name] = input.KeyCode.Name
notify("Keybinds", name .. " is now " .. input.KeyCode.Name, "good")
end
saveSoon()
renderKeyRows()
return
end
if UserInputService:GetFocusedTextBox() then return end
if input.KeyCode == Enum.KeyCode.RightShift then
setMenu(not menuOpen)
return
end
local key = input.KeyCode.Name
if key == Settings.binds.Stunt then
performStunt(findStunt(Settings.stunt), Settings.stuntAirtime, "Stunt")
elseif key == Settings.binds["Car Hop"] then
performStunt(HOP, Settings.hopAirtime, "Car Hop")
end
if key == Settings.binds.Drift and Settings.drift then
setDrift(true)
end
end)
bind(UserInputService.InputEnded, function(input)
if input.UserInputType == Enum.UserInputType.Keyboard and input.KeyCode.Name == Settings.binds.Drift then
setDrift(false)
end
end)
local function unload()
if not alive then return end
alive = false
local rgbCar = Settings.carRGB and ownCar()
if rgbCar and originalPaints[rgbCar] then
task.spawn(paintCar, rgbCar, originalPaints[rgbCar])
end
endSession()
RunService:UnbindFromRenderStep("BrookhavenStudioView")
if savedLighting then
for key, value in pairs(savedLighting) do
Lighting[key] = value
end
savedLighting = nil
end
if savedFov then
workspace.CurrentCamera.FieldOfView = savedFov
end
if savedZoom then
LocalPlayer.CameraMaxZoomDistance = savedZoom
end
for _, c in ipairs(connections) do
c:Disconnect()
end
table.clear(connections)
modal.Modal = false
menuBlur:Destroy()
Gui:Destroy()
if ENV.BrookhavenStudio and ENV.BrookhavenStudio.Unload == unload then
ENV.BrookhavenStudio = nil
end
print("[Brookhaven Studio] unloaded")
end
unloadRef = unload
bind(workspace.CurrentCamera:GetPropertyChangedSignal("ViewportSize"), function()
guiScale = computeScale()
for _, sc in ipairs(scaleObjects) do
sc.Scale = guiScale
end
if menuOpen then
boxScale.Scale = guiScale
end
task.defer(placeArrayList)
end)
ENV.BrookhavenStudio = {
Unload = unload,
Settings = Settings,
Modules = ModuleByName,
SetShown = setMenu,
IsShown = function() return menuOpen end,
SelectTab = selectTab,
SetCarRGB = setCarRGB,
SyncLighting = syncLightingSnapshot,
ApplyCarSettings = function()
applyPhysics()
applyTires()
end,
Stunt = function(name)
performStunt(findStunt(name), Settings.stuntAirtime, "Stunt")
end,
SetDrift = setDrift,
Session = function() return Session end,
StuntCount = function() return stuntCount end,
}
---------------------------------------------------------------------------------------------
-- Start
---------------------------------------------------------------------------------------------
syncLightingSnapshot()
syncFov()
syncZoom()
selectTab("Vehicle", true)
setMenu(startShown)
refreshVehicleStatus()
-- Gamepass checks hit Roblox's web API, so they run after the menu is up.
task.spawn(function()
local available = {}
for _, car in ipairs(CARS) do
if not car.pass or owns(car.pass) then
table.insert(available, { value = car.id, label = car.label })
end
end
if not alive then return end
local selected = Settings.car
local found = false
for _, option in ipairs(available) do
if option.value == selected then found = true end
end
if not found and available[1] then
selected = available[1].value
Settings.car = selected
end
carPicker.setOptions(available, selected)
local headline = owns("VIP") and "VIP" or owns("PREMIUM") and "Premium" or "Standard"
passNote.Text = string.format("%s · %d of %d cars · top speed %d", headline, #available, #CARS, topSpeed())
if LocalPlayer.Character then
task.spawn(hookCharacter, LocalPlayer.Character)
end
end)
bind(LocalPlayer.CharacterAdded, function(character)
endSession()
hookCharacter(character)
end)
if Settings.rpName:gsub("%s", "") ~= "" then
NameTextEvent:FireServer("RolePlayName", Settings.rpName)
end
if Settings.rpBio:gsub("%s", "") ~= "" then
NameTextEvent:FireServer("RolePlayBio", Settings.rpBio)
end
task.spawn(function()
local options, err = fetchSaves()
if not alive then return end
if not options then
notify("Saved props", "Couldn't read your house saves: " .. tostring(err), "bad")
buildPicker.setOptions({})
return
end
local selected = Settings.buildSlot
if selected == "" and options[1] then
selected = options[1].value
Settings.buildSlot = selected
end
buildPicker.setOptions(options, selected)
end)
bind(HouseNumber.Changed, function(number)
if number > 0 then
notify("House", "House #" .. number .. " claimed" .. (Settings.houseRainbow and " · color cycle on" or ""), "good")
if Settings.loadBuild and Settings.buildSlot ~= "" then
task.delay(3, function()
if alive and HouseNumber.Value == number then
loadBuild(Settings.buildSlot)
end
end)
end
end
end)
-- House color cycle. Each server update repaints hundreds of parts for everyone, so the server
-- only gets a step every 0.6s; your own screen is smoothed below.
task.spawn(function()
while alive do
if Settings.houseRainbow and HouseNumber.Value > 0 then
local color = houseColorAt(os.clock() + 0.05)
setHouseColor(color)
table.insert(housePaint.recent, 1, color)
housePaint.recent[4] = nil
if os.clock() >= housePaint.refreshAt then
housePaint.refreshAt = os.clock() + 8
task.delay(0.8, function()
if alive then
housePaint.parts = collectHouseParts()
end
end)
end
task.wait(0.6)
else
table.clear(housePaint.parts)
housePaint.refreshAt = 0
task.wait(0.3)
end
end
end)
do
-- Repaint 20 times a second, and also immediately in any frame where a server update just
-- landed (the first part no longer shows what we last wrote), so it never flickers.
local nextFrame = 0
local lastWritten
bind(RunService.RenderStepped, function()
local parts = housePaint.parts
if not Settings.houseRainbow or HouseNumber.Value <= 0 or #parts == 0 then return end
local now = os.clock()
local overwritten = lastWritten ~= nil and parts[1].Color ~= lastWritten
if now < nextFrame and not overwritten then return end
nextFrame = now + 0.05
local color = houseColorAt(now)
for _, part in ipairs(parts) do
part.Color = color
end
lastWritten = parts[1].Color
end)
end
-- RGB streaming. The server gets ~10 small steps a second (tested: 28/28 accepted at this
-- rate), sent without waiting on each reply, so other players see a smooth fade too.
-- Three refusals in a row (e.g. a car that can't be painted) switch the feature off.
local RGB_SEND_INTERVAL = 0.1
local RGB_MAX_IN_FLIGHT = 2
-- getTarget returns what to recolor right now, or nil to pause.
local function rgbStream(getTarget, send, onFail)
task.spawn(function()
local inFlight, failures = 0, 0
while alive do
local target = getTarget()
if target and inFlight < RGB_MAX_IN_FLIGHT then
inFlight += 1
task.spawn(function()
local ok, msg = send(target, os.clock() + RGB_SEND_INTERVAL)
inFlight -= 1
if ok or getTarget() ~= target then
failures = 0
else
failures += 1
if failures >= 3 then
failures = 0
onFail(msg)
end
end
end)
end
task.wait(target and RGB_SEND_INTERVAL or 0.25)
end
end)
end
-- Car RGB keeps going whether you're driving the car or it's parked (the game accepts paint
-- for your car from anywhere). While you drive, it waits for auto-tune to finish first.
local function rgbCar()
if not Settings.carRGB then return nil end
local s = Session
if s and not s.ready then return nil end
return ownCar()
end
rgbStream(rgbCar, function(car, t)
return paintCar(car, rgbColor(Settings.rgbMode, t, Settings.rgbCycle))
end, function(msg)
setCarRGB(false)
notify("Car RGB", "Stopped: " .. tostring(msg), "bad")
end)
-- The underglow request has no car id, so it only works for the car you're in.
rgbStream(function()
local s = Session
return Settings.rainbowGlow and s and s.ready and s or nil
end, function(_, t)
local ok, msg = carRequest("SetUnderglowColor", 1, glowColor(t))
-- Usually the glow is just switched off; turn the chosen style back on and keep going.
if not ok and tostring(msg):lower():find("select an underglow") then
carRequest("SetUnderglow", Settings.underglow)
end
return ok, msg
end, function(msg)
Settings.rainbowGlow = false
saveSoon()
refreshModule("RGB Underglow")
notify("RGB Underglow", "Stopped: " .. tostring(msg), "bad")
end)
-- Your own screen: recolor every frame so the fade is perfectly smooth between the server's
-- steps (replicated values land before RenderStepped, so these always win on screen).
bind(RunService.RenderStepped, function()
local t = os.clock()
local car = rgbCar()
if car then
local color = rgbColor(Settings.rgbMode, t, Settings.rgbCycle)
for _, part in ipairs(paintParts(car)) do
part.Color = color
end
end
local s = Session
if not s or not s.ready then return end
if Settings.rainbowGlow then
local color = glowColor(t)
for _, obj in ipairs(glowObjects(s.car)) do
if obj:IsA("Beam") then
obj.Color = ColorSequence.new(color)
else
obj.Color = color
end
end
end
end)
-- Rainbow RP name. Brookhaven waits 1s between name color changes, so match that.
task.spawn(function()
local hue = 0
while alive do
if Settings.rainbowName then
hue = (hue + 0.08) % 1
NameColorEvent:FireServer("PickingRPNameColor", Color3.fromHSV(hue, 0.85, 1))
task.wait(1.1)
else
task.wait(0.3)
end
end
end)
-- Auto Flip: if the car stays on its roof or side for a moment, ask the game to set it upright.
task.spawn(function()
local tippedSince
local lastFlip = 0
while alive do
local s = Session
if Settings.autoFlip and s and not s.stunting and s.geom then
local up = carFrame(s).UpVector
if up.Y < 0.35 then
tippedSince = tippedSince or os.clock()
if os.clock() - tippedSince > 1.2 and os.clock() - lastFlip > 5 then
lastFlip = os.clock()
tippedSince = nil
local ok = carRequest("RepositionVehicle")
notify("Auto Flip", ok and "Back on your wheels" or "Couldn't flip the car", ok and "good" or "bad")
end
else
tippedSince = nil
end
else
tippedSince = nil
end
task.wait(0.2)
end
end)
-- Air Stunts and Landing Assist watch every physics step.
bind(RunService.Heartbeat, airMonitor)
-- Auto Headlights. The game only reports the light state when it's toggled, so this switches
-- at dusk and dawn (and when you get in) and checks the answer; pressing V yourself still works
-- in between.
task.spawn(function()
while alive do
local s = Session
if Settings.autoLights and s and s.ready then
local clock = savedLighting and savedLighting.ClockTime or Lighting.ClockTime
local night = clock < 6.3 or clock >= 17.7
if s.lightsFor ~= night then
s.lightsFor = night
if s.lightsOn == nil and not night then
s.lightsOn = false -- a freshly spawned car has its lights off
end
for _ = 1, 2 do
if s.lightsOn == night or Session ~= s then break end
local called, state = invoke("ToggleHeadLights")
if not called or type(state) ~= "boolean" then
notify("Auto Headlights", "Couldn't switch the lights: " .. tostring(state), "bad")
break
end
s.lightsOn = state
end
end
end
task.wait(1)
end
end)
-- Periodic refresh for things that change on their own.
task.spawn(function()
local tick = 0
while alive do
tick += 1
if tick % 10 == 0 then
refreshVehicleStatus()
for _, name in ipairs({ "Fire", "Engine Smoke" }) do
refreshModule(name)
end
end
-- Brookhaven's HUD changes with what you're doing, so re-measure it every few seconds.
if tick % 50 == 1 then
placeArrayList()
end
task.wait(0.1)
end
end)
notify("Brookhaven Studio", "v6 loaded · RightShift opens the menu", "good")
Universal