Run it
Copy the script and paste it into your executor.
DEFAULT_PREFS = {
reset = .KeyCode.E,
menu = .KeyCode.Semicolon,
scale = ,
height = ,
opacity = ,
popups = ,
crosshair = ,
xhStyle = ,
xhLength = ,
xhGap = ,
xhThickness = ,
xhDynamic = ,
xhSpread = ,
xhRotation = ,
xhOutline = ,
xhHue = ,
xhSat = ,
xhVal = ,
xhAlpha = ,
}
PREFS_FILE =
TURN_DEADZONE =
SPEED_WINDOW =
AIR_MARGIN =
HISTORY =
RAY_LENGTH =
MIN_STRAFE_SPEED =
LATERAL_MIN =
FALLBACK_STYLE = { name = , keys = { w = , a = , s = , d = } }
STYLE_KEY = { forward = , left = , back = , right = }
MOVE_KEYS = { forward = .KeyCode.W, left = .KeyCode.A, back = .KeyCode.S, right = .KeyCode.D }
env = ()
env.StrafeTrainer
(env.StrafeTrainer.destroy)
GuiService = :()
HttpService = :()
Players = :()
RunService = :()
TweenService = :()
UserInputService = :()
LocalPlayer = Players.LocalPlayer
COLOR_IDLE = .(, , )
COLOR_HELD = .(, , )
COLOR_HINT = .(, , )
COLOR_GOOD = .(, , )
COLOR_BAD = .(, , )
COLOR_DIM = .(, , )
COLOR_MUTED = .(, , )
COLOR_TEXT = .(, , )
COLOR_BACK = .(, , )
TW_BAR = TweenInfo.(, .EasingStyle.Quad, .EasingDirection.Out)
TW_FADE = TweenInfo.(, .EasingStyle.Quad, .EasingDirection.Out)
TW_SETTLE = TweenInfo.(, .EasingStyle.Quad, .EasingDirection.Out)
TW_POP = TweenInfo.(, .EasingStyle.Back, .EasingDirection.Out)
TW_DRIFT = TweenInfo.(, .EasingStyle.Quad, .EasingDirection.Out)
TW_SLIDE = TweenInfo.(, .EasingStyle.Quint, .EasingDirection.Out)
POPUP_X =
POPUP_GAP =
POPUP_RISE =
SPREAD_FULL_TURN =
stats = {
speed = ,
airborne = ,
jumps = ,
lastSync = ,
lastGain = ,
avgSync = ,
avgGain = ,
}
(obj, info, props)
t = TweenService:(obj, info, props)
t:()
t
KEY_ROWS = {
{ , },
{ , },
}
STEPPERS = {
scale = { , , , , },
height = { , , , , },
opacity = { , , , , },
xhLength = { , , , , },
xhGap = { , , , , },
xhThickness = { , , , , },
xhSpread = { , , , , },
xhRotation = { , , , , , },
}
UNIT_PREFS = { , , , }
XH_STYLES = { , , , , }
prefs = .(DEFAULT_PREFS)
()
ok, saved = (()
(PREFS_FILE) HttpService:((PREFS_FILE))
)
ok (saved) ~=
name, default DEFAULT_PREFS
v = saved[name]
(default) ==
found, key = (()
.KeyCode[v]
)
v = found key
(v) ~= (default)
v =
v ~=
prefs[name] = v
name, spec STEPPERS
stepSize = spec[]
prefs[name] = .(.(prefs[name] / stepSize) * stepSize, spec[], spec[])
_, name UNIT_PREFS
prefs[name] = .(prefs[name], , )
.(XH_STYLES, prefs.xhStyle)
prefs.xhStyle = DEFAULT_PREFS.xhStyle
()
out = {}
name, v prefs
out[name] = (v) == v.Name v
(()
(PREFS_FILE, HttpService:(out))
)
()
gui = .()
gui.Name =
gui.ResetOnSpawn =
gui.IgnoreGuiInset =
gui.ZIndexBehavior = .ZIndexBehavior.Sibling
hud = .()
hud.AnchorPoint = .(, )
hud.Position = .(, , , -prefs.height)
hud.Size = .(, )
hud.BackgroundTransparency =
hud.Parent = gui
hudScale = .()
hudScale.Scale = prefs.scale
hudScale.Parent = hud
panel = .()
panel.AnchorPoint = .(, )
panel.Position = .(, )
panel.Size = .(, )
panel.BackgroundColor3 = COLOR_BACK
panel.BackgroundTransparency = - prefs.opacity /
panel.BorderSizePixel =
panel.GroupTransparency =
panel.Parent = hud
.(, panel).CornerRadius = .(, )
scale = .()
scale.Scale =
scale.Parent = panel
stroke = .()
stroke.Color = .(, , )
stroke.Transparency =
stroke.Thickness =
stroke.Parent = panel
(anchorX, xScale, xOffset)
bar = .()
bar.AnchorPoint = .(anchorX, )
bar.Position = .(xScale, xOffset, , )
bar.Size = .(, )
bar.BackgroundColor3 = COLOR_IDLE
bar.BorderSizePixel =
bar.Parent = panel
.(, bar).CornerRadius = .(, )
bar
barLeft = (, , )
barRight = (, , -)
speedLabel = .()
speedLabel.AnchorPoint = .(, )
speedLabel.Position = .(, , , )
speedLabel.Size = .(, )
speedLabel.BackgroundTransparency =
speedLabel.Font = .Font.GothamBold
speedLabel.TextSize =
speedLabel.TextColor3 = COLOR_TEXT
speedLabel.Text =
speedLabel.Parent = panel
statLabel = .()
statLabel.AnchorPoint = .(, )
statLabel.Position = .(, , , )
statLabel.Size = .(, )
statLabel.BackgroundTransparency =
statLabel.Font = .Font.Gotham
statLabel.TextSize =
statLabel.TextColor3 = COLOR_DIM
statLabel.RichText =
statLabel.Text =
statLabel.Parent = panel
(parent)
root = .()
root.AnchorPoint = .(, )
root.Position = .(, )
root.Size = .(, )
root.BackgroundTransparency =
root.Parent = parent
(zIndex, round)
frame = .()
frame.AnchorPoint = .(, )
frame.BorderSizePixel =
frame.ZIndex = zIndex
frame.Parent = root
stroke = .()
stroke.Color = .(, , )
stroke.LineJoinMode = round .LineJoinMode.Round .LineJoinMode.Miter
stroke.Parent = frame
corner
round
corner = .()
corner.CornerRadius = .(, )
corner.Parent = frame
{ frame = frame, stroke = stroke, corner = corner }
xh = { root = root, arms = {} }
i = ,
xh.arms[i] = ()
xh.dot = (, )
xh.ringOutline = (, )
xh.ring = (, )
xh.ring.frame.BackgroundTransparency =
xh.ringOutline.frame.BackgroundTransparency =
xh
(xh, cfg)
t = cfg.thickness
c = (t % ) *
centre = .(c, c)
clear = - cfg.alpha
style = cfg.style
rot = cfg.rotation + (style == )
reach = t / + cfg.gap + cfg.length /
showArms = style == style == style ==
i, arm xh.arms
arm.frame.Visible = showArms
showArms
a = .(rot + (i - ) * )
arm.frame.Position = .(c + .(a) * reach, c + .(a) * reach)
arm.frame.Size = i % == .(cfg.length, t) .(t, cfg.length)
arm.frame.Rotation = rot
arm.frame.BackgroundColor3 = cfg.color
arm.frame.BackgroundTransparency = clear
arm.stroke.Enabled = cfg.outline
arm.stroke.Transparency = clear
showDot = style == style ==
xh.dot.frame.Visible = showDot
showDot
xh.dot.frame.Position = centre
xh.dot.frame.Size = .(t, t)
xh.dot.frame.Rotation = rot
xh.dot.frame.BackgroundColor3 = cfg.color
xh.dot.frame.BackgroundTransparency = clear
roundDot = style == t >=
xh.dot.corner.CornerRadius = .(roundDot , )
xh.dot.stroke.LineJoinMode = roundDot .LineJoinMode.Round .LineJoinMode.Miter
xh.dot.stroke.Enabled = cfg.outline
xh.dot.stroke.Transparency = clear
showRing = style ==
ringSize = * cfg.gap + cfg.length
outlineSize = .(ringSize - , )
xh.ring.frame.Visible = showRing
xh.ringOutline.frame.Visible = showRing cfg.outline
showRing
xh.ring.frame.Position = centre
xh.ring.frame.Size = .(ringSize, ringSize)
xh.ring.stroke.Thickness = t
xh.ring.stroke.Color = cfg.color
xh.ring.stroke.Transparency = clear
xh.ringOutline.frame.Position = centre
xh.ringOutline.frame.Size = .(outlineSize, outlineSize)
xh.ringOutline.stroke.Thickness = t +
xh.ringOutline.stroke.Transparency = clear
(spreadFrac)
spread = prefs.xhDynamic .(prefs.xhSpread * spreadFrac + )
{
style = prefs.xhStyle,
length = prefs.xhLength,
gap = prefs.xhGap + spread,
thickness = prefs.xhThickness,
rotation = prefs.xhRotation,
outline = prefs.xhOutline,
color = .(prefs.xhHue, prefs.xhSat, prefs.xhVal),
alpha = prefs.xhAlpha,
}
liveCrosshair = (gui)
liveCrosshair.root.Visible =
gui.Parent = ()
(panel, TW_FADE, { GroupTransparency = })
(scale, TW_POP, { Scale = })
samples = {}
lastYaw =
groundBaseline =
wasAirborne =
takeoffSpeed =
turnTime, syncTime = ,
history = {}
shownSpeed =
barState = {}
popups = {}
turnRate =
velocity = .zero
view =
nextViewSearch =
rayParams = RaycastParams.()
rayParams.FilterType = .RaycastFilterType.Exclude
(v)
v .(, .(v + ))
(v)
v .(, v)
(side, rise)
.(, side * POPUP_X, , -POPUP_GAP - rise)
(side)
label = .()
label.AnchorPoint = .(, )
label.Position = (side, -)
label.Size = .(, )
label.BackgroundTransparency =
label.Font = .Font.GothamBold
label.TextSize =
label.TextColor3 = COLOR_DIM
label.TextTransparency =
label.Text =
label.Parent = hud
popScale = .()
popScale.Scale =
popScale.Parent = label
p = { label = label, scale = popScale, turn = , sync = , shown = }
popups[side] = p
p
(side)
p = popups[side]
p
popups[side] =
p.shown
p.label:()
(p.label, TW_DRIFT, {
TextTransparency = ,
Position = (side, POPUP_RISE),
}).Completed:(()
p.label:()
)
(side, held, inSync, turning, dt)
held
(side)
p = popups[side] (side)
turning
p.turn += dt
inSync
p.sync += dt
p.label.Text = (p.sync / p.turn * )
p.shown
p.shown =
(p.label, TW_POP, { TextTransparency = , Position = (side, ) })
(p.scale, TW_POP, { Scale = })
()
.(samples)
lastYaw =
wasAirborne =
turnTime, syncTime = ,
turnRate =
side popups
(side)
()
statLabel.Text = .(
,
(stats.lastSync),
(stats.lastGain),
(stats.avgSync),
(stats.avgGain)
)
()
.(history)
stats.jumps =
stats.lastSync, stats.lastGain = ,
stats.avgSync, stats.avgGain = ,
groundBaseline =
()
()
scale.Scale =
(scale, TW_POP, { Scale = })
stroke.Transparency =
(stroke, TW_SETTLE, { Transparency = })
()
()
folder = :()
char = folder folder:(LocalPlayer.Name) LocalPlayer.Character
char char:(), folder
(now, pos)
last = samples[#samples]
last (pos - last[]).Magnitude >
.(samples)
.(samples, { now, pos })
#samples > now - samples[][] >= SPEED_WINDOW
.(samples, )
first = samples[]
span = now - first[]
span <=
velocity
d = pos - first[]
.(d.X, d.Z) / span
()
view .() >= nextViewSearch
nextViewSearch = .() +
ok, found = (filtergc, , { Keys = { , } }, )
view = ok (found) == found
ok, info = (()
view.PlaybackContext.StyleInfo
)
ok (info) == (info.keys) == info FALLBACK_STYLE
(style, held, camYaw)
keys = style.keys
w, a, s, d = keys.w, keys.a, keys.s, keys.d
weight = (held.forward w ) + (held.left a ) + (held.back s ) + (held.right d )
style.total style.total ~= weight
w == held.forward a == held.left s == held.back d == held.right
x = ((d ~= held.right) ) - ((a ~= held.left) )
z = ((s ~= held.back) ) - ((w ~= held.forward) )
x == z ==
c, sn = .(camYaw), .(camYaw)
dir = .(x * c + z * sn, z * c - x * sn).Unit
allowed = style.allow_strafe_dir
allowed
along = .(dir.X * velocity.X + dir.Y * velocity.Y, dir.X * velocity.Y - dir.Y * velocity.X):(allowed)
(along == along < held.left along > held.right)
dir
(style)
only =
name, field STYLE_KEY
weight = style.keys[field]
weight weight ~=
only
only = name
only
(camYaw)
stats.speed < MIN_STRAFE_SPEED
style = ()
held = {}
name STYLE_KEY
held[name] = UserInputService:(MOVE_KEYS[name])
dir, flip = (style, held, camYaw),
only = (style)
dir only held[only]
held[only] =
dir, flip = (style, held, camYaw), -
dir
lateral = (dir.X * velocity.Y - dir.Y * velocity.X) / stats.speed
.(lateral) < LATERAL_MIN
lateral > flip -flip
(root, folder)
rayParams.FilterDescendantsInstances = { folder root.Parent }
hit = :(root.Position, .(, -RAY_LENGTH, ), rayParams)
hit
dist = root.Position.Y - hit.Position.Y
groundBaseline dist < groundBaseline
groundBaseline = dist
dist > groundBaseline + AIR_MARGIN
(landSpeed)
sync = turnTime > (syncTime / turnTime * )
gain = landSpeed - takeoffSpeed
stats.jumps +=
stats.lastSync = sync
stats.lastGain = gain
.(history, { sync = sync, gain = gain })
#history > HISTORY
.(history, )
syncSum, syncN, gainSum = , ,
_, h history
gainSum += h.gain
h.sync
syncSum += h.sync
syncN +=
stats.avgGain = gainSum / #history
stats.avgSync = syncN > syncSum / syncN
()
statLabel.TextColor3 = gain >= COLOR_GOOD COLOR_BAD
(statLabel, TW_SETTLE, { TextColor3 = COLOR_DIM })
(bar, isCorrect, isWrong, held)
color, height
isCorrect
color = held COLOR_GOOD COLOR_HINT
height = held
isWrong held
color, height = COLOR_BAD,
color = held COLOR_HELD COLOR_IDLE
height = held
last = barState[bar]
last last.color ~= color last.height ~= height
barState[bar] = { color = color, height = height }
(bar, TW_BAR, { BackgroundColor3 = color, Size = .(, height) })
(dt)
root, folder = ()
root dt <=
()
now = .()
velocity = (now, root.Position)
stats.speed = velocity.Magnitude
look = .CurrentCamera.CFrame.LookVector
yaw = .(-look.X, -look.Z)
yawRate =
lastYaw
d = (yaw - lastYaw + .pi) % ( * .pi) - .pi
yawRate = d / dt
lastYaw = yaw
turnRate = .(yawRate)
turning = .(yawRate) > TURN_DEADZONE
turnLeft = turning yawRate >
turnRight = turning yawRate <
side = (yaw)
leftHeld = side ==
rightHeld = side == -
airborne = (root, folder)
stats.airborne = airborne
airborne wasAirborne
takeoffSpeed = stats.speed
turnTime, syncTime = ,
wasAirborne airborne
(stats.speed)
wasAirborne = airborne
leftSync = turnLeft leftHeld
rightSync = turnRight rightHeld
airborne turning
turnTime += dt
leftSync rightSync
syncTime += dt
(barLeft, turnLeft, turnRight, leftHeld)
(barRight, turnRight, turnLeft, rightHeld)
(-, prefs.popups leftHeld, leftSync, turning, dt)
(, prefs.popups rightHeld, rightSync, turning, dt)
shownSpeed += (stats.speed - shownSpeed) * .(dt * , )
speedLabel.Text = .(, shownSpeed)
MENU_W =
MENU_PAD =
ROW_H =
EDITOR_W =
EDITOR_PAD =
EDITOR_GAP =
EDITOR_ROW_H =
PAGE_H =
CONTROL_W =
BUTTON_IDLE =
BUTTON_HOVER =
WHEEL_SIZE =
WHEEL_SPOKES =
TABS = { , , }
MOUSE_STEP =
KEY_SYMBOLS = {
Semicolon = ,
Colon = ,
Quote = ,
Comma = ,
Period = ,
Slash = ,
BackSlash = ,
LeftBracket = ,
RightBracket = ,
Minus = ,
Equals = ,
Backquote = ,
}
(key)
KEY_SYMBOLS[key.Name] key.Name
menuOpen =
editorOpen =
activeTab = TABS[]
capturing =
savedMouse =
dragUpdate =
rowRefreshers = {}
setEditorOpen, setTab
()
_, refresh rowRefreshers
()
()
(hud, TW_BAR, { Position = .(, , , -prefs.height) })
(hudScale, TW_BAR, { Scale = prefs.scale })
(panel, TW_BAR, { BackgroundTransparency = - prefs.opacity / })
()
()
()
()
()
dragUpdate
dragUpdate =
()
(zIndex)
p = .()
p.BackgroundColor3 = COLOR_BACK
p.BackgroundTransparency =
p.BorderSizePixel =
p.GroupTransparency =
p.Visible =
p.ZIndex = zIndex
p.Parent = gui
.(, p).CornerRadius = .(, )
s = .()
s.Color = .(, , )
s.Transparency =
s.Thickness =
s.Parent = p
catcher = .()
catcher.Size = .(, )
catcher.BackgroundTransparency =
catcher.Text =
catcher.AutoButtonColor =
catcher.ZIndex =
catcher.Parent = p
p, catcher
(p, pad)
body = .()
body.Position = .(pad, )
body.Size = .(, -pad * , , )
body.BackgroundTransparency =
body.Parent = p
body
(text, font, size, color)
l = .()
l.BackgroundTransparency =
l.Font = font
l.TextSize = size
l.TextColor3 = color
l.TextXAlignment = .TextXAlignment.Left
l.Text = text
l
(parent, y, rowH)
{ parent = parent, y = y, rowH = rowH }
(stack, title)
stack.y +=
l = (title, .Font.GothamBold, , COLOR_MUTED)
l.Position = .(, stack.y)
l.Size = .(, , , )
l.Parent = stack.parent
stack.y +=
(stack, title)
row = .()
row.Position = .(, stack.y)
row.Size = .(, , , stack.rowH)
row.BackgroundTransparency =
row.Parent = stack.parent
l = (title, .Font.Gotham, , COLOR_DIM)
l.Size = .(, )
l.Parent = row
stack.y += stack.rowH
row
(parent, width, height)
b = .()
b.Size = .(width, height)
b.BackgroundColor3 = COLOR_TEXT
b.BackgroundTransparency = BUTTON_IDLE
b.BorderSizePixel =
b.AutoButtonColor =
b.Font = .Font.GothamBold
b.TextSize =
b.TextColor3 = COLOR_TEXT
b.Text =
b.Parent = parent
.(, b).CornerRadius = .(, )
b.MouseEnter:(()
(b, TW_BAR, { BackgroundTransparency = BUTTON_HOVER })
)
b.MouseLeave:(()
(b, TW_BAR, { BackgroundTransparency = BUTTON_IDLE })
)
b
(row, width, right)
b = (row, width, )
b.AnchorPoint = .(, )
b.Position = .(, -right, , )
b
(button, name)
button.MouseButton1Click:(()
prefs[name] = prefs[name]
()
)
.(rowRefreshers, ()
button.Text = prefs[name]
button.TextColor3 = prefs[name] COLOR_TEXT COLOR_DIM
)
button
(stack, label, name)
(((stack, label), CONTROL_W, ), name)
(stack, name)
label, min, max, stepSize, fmt, wraps = .(STEPPERS[name])
row = (stack, label)
value = (, .Font.GothamBold, , COLOR_TEXT)
value.AnchorPoint = .(, )
value.Position = .(, -, , )
value.Size = .(CONTROL_W - , )
value.TextXAlignment = .TextXAlignment.Center
value.Parent = row
(dir)
v = .((prefs[name] + dir * stepSize) / stepSize) * stepSize
wraps
v %= max + stepSize
prefs[name] = .(v, min, max)
()
minus = (row, , CONTROL_W - )
minus.Text =
minus.MouseButton1Click:(()
(-)
)
plus = (row, , )
plus.Text =
plus.MouseButton1Click:(()
()
)
.(rowRefreshers, ()
value.Text = .(fmt, prefs[name])
)
value
()
UserInputService:() - GuiService:()
(parent, update)
hit = .()
hit.Size = .(, )
hit.BackgroundTransparency =
hit.Text =
hit.AutoButtonColor =
hit.ZIndex =
hit.Parent = parent
hit.MouseButton1Down:(()
dragUpdate = update
(())
)
hit
menu, menuCatcher = ()
menu.AnchorPoint = .(, )
menu.Position = .(, )
menuCatcher.Modal =
menuScale = .()
menuScale.Scale =
menuScale.Parent = menu
menuBody = (menu, MENU_PAD)
title = (, .Font.GothamBold, , COLOR_TEXT)
title.Position = .(, )
title.Size = .(, , , )
title.Parent = menuBody
closeHint = (, .Font.Gotham, , COLOR_MUTED)
closeHint.Position = title.Position
closeHint.Size = title.Size
closeHint.TextXAlignment = .TextXAlignment.Right
closeHint.Parent = menuBody
.(rowRefreshers, ()
closeHint.Text = (prefs.menu) ..
)
menuStack = (menuBody, , ROW_H)
(menuStack, )
styleValue = (, .Font.GothamBold, , COLOR_TEXT)
styleValue.Size = .(, )
styleValue.TextXAlignment = .TextXAlignment.Right
styleValue.Parent = (menuStack, )
.(rowRefreshers, ()
style = ()
styleValue.Text = style == FALLBACK_STYLE .(style.name )
styleValue.TextColor3 = style == FALLBACK_STYLE COLOR_DIM COLOR_TEXT
)
_, spec KEY_ROWS
name = spec[]
b = ((menuStack, spec[]), CONTROL_W, )
b.MouseButton1Click:(()
capturing = capturing ~= name name
()
)
.(rowRefreshers, ()
waiting = capturing == name
b.Text = waiting (prefs[name])
b.TextColor3 = waiting COLOR_DIM COLOR_TEXT
)
(menuStack, )
(menuStack, )
(menuStack, )
(menuStack, )
(menuStack, , )
crosshairRow = (menuStack, )
((crosshairRow, , ), )
editButton = (crosshairRow, , )
editButton.MouseButton1Click:(()
( editorOpen)
)
.(rowRefreshers, ()
editButton.Text = editorOpen
)
menuStack.y +=
defaultsButton = ((menuStack, ), CONTROL_W, )
defaultsButton.Text =
defaultsButton.MouseButton1Click:(()
capturing =
name, v DEFAULT_PREFS
prefs[name] = v
()
)
menuHeight = menuStack.y +
menu.Size = .(MENU_W, menuHeight)
editor = ()
editor.AnchorPoint = .(, )
editor.Size = .(EDITOR_W, menuHeight)
editorBody = (editor, EDITOR_PAD)
bodyW = EDITOR_W - EDITOR_PAD *
previewH = menuHeight - EDITOR_PAD * - - - PAGE_H
preview = .()
preview.Position = .(, EDITOR_PAD)
preview.Size = .(, , , previewH)
preview.BackgroundColor3 = COLOR_TEXT
preview.BackgroundTransparency =
preview.BorderSizePixel =
preview.Parent = editorBody
.(, preview).CornerRadius = .(, )
previewCrosshair = (preview)
tabY = EDITOR_PAD + previewH +
pages = {}
i, tab TABS
b = .()
b.Position = .((i - ) / #TABS, , , tabY)
b.Size = .( / #TABS, , , )
b.BackgroundTransparency =
b.AutoButtonColor =
b.Font = .Font.GothamBold
b.TextSize =
b.Text = tab
b.Parent = editorBody
b.MouseButton1Click:(()
(tab)
)
.(rowRefreshers, ()
b.TextColor3 = activeTab == tab COLOR_TEXT COLOR_MUTED
)
page = .()
page.Position = .(, tabY + )
page.Size = .(, , , PAGE_H)
page.BackgroundTransparency =
page.Visible = tab == activeTab
page.Parent = editorBody
pages[tab] = page
(tab)
.((.(TABS, tab) - ) / #TABS, , , tabY + )
tabLine = .()
tabLine.AnchorPoint = .(, )
tabLine.Position = (activeTab)
tabLine.Size = .(, )
tabLine.BackgroundColor3 = COLOR_TEXT
tabLine.BackgroundTransparency =
tabLine.BorderSizePixel =
tabLine.Parent = editorBody
(tab)
activeTab = tab
name, page pages
page.Visible = name == tab
(tabLine, TW_SLIDE, { Position = (tab) })
()
ICON_GAP =
iconW = (bodyW - ICON_GAP * (#XH_STYLES - )) / #XH_STYLES
i, style XH_STYLES
b = (pages.style, iconW, )
b.Position = .((i - ) * (iconW + ICON_GAP), )
ring = .()
ring.ApplyStrokeMode = .ApplyStrokeMode.Border
ring.Color = COLOR_TEXT
ring.Transparency =
ring.Parent = b
icon = (b)
b.MouseButton1Click:(()
prefs.xhStyle = style
()
)
.(rowRefreshers, ()
selected = prefs.xhStyle == style
ring.Enabled = selected
(icon, {
style = style,
length = ,
gap = ,
thickness = style == ,
rotation = ,
outline = ,
color = selected COLOR_TEXT COLOR_DIM,
alpha = ,
})
)
styleStack = (pages.style, , EDITOR_ROW_H)
(styleStack, )
(styleStack, , )
sizeStack = (pages.size, , EDITOR_ROW_H)
_, name { , , }
(sizeStack, name)
(sizeStack, , )
spreadValue = (sizeStack, )
.(rowRefreshers, ()
spreadValue.TextColor3 = prefs.xhDynamic COLOR_TEXT COLOR_DIM
)
wheel = .()
wheel.Position = .(, (PAGE_H - WHEEL_SIZE) / )
wheel.Size = .(WHEEL_SIZE, WHEEL_SIZE)
wheel.BackgroundTransparency =
wheel.Parent = pages.colour
wheelR = WHEEL_SIZE /
spokeW = .( * .pi * wheelR / WHEEL_SPOKES) +
i = , WHEEL_SPOKES -
a = i / WHEEL_SPOKES * * .pi
spoke = .()
spoke.AnchorPoint = .(, )
spoke.Position = .(wheelR + .(a) * wheelR / , wheelR + .(a) * wheelR / )
spoke.Size = .(wheelR, spokeW)
spoke.Rotation = .(a)
spoke.BackgroundColor3 = COLOR_TEXT
spoke.BorderSizePixel =
spoke.Parent = wheel
g = .()
g.Color = ColorSequence.(COLOR_TEXT, .(i / WHEEL_SPOKES, , ))
g.Parent = spoke
wheelShade = .()
wheelShade.Size = .(, )
wheelShade.BackgroundColor3 = .(, , )
wheelShade.BorderSizePixel =
wheelShade.Parent = wheel
.(, wheelShade).CornerRadius = .(, )
wheelRim = .()
wheelRim.Color = COLOR_TEXT
wheelRim.Transparency =
wheelRim.Parent = wheelShade
marker = .()
marker.AnchorPoint = .(, )
marker.Size = .(, )
marker.BackgroundTransparency =
marker.Parent = wheel
.(, marker).CornerRadius = .(, )
markerHalo = .()
markerHalo.Color = .(, , )
markerHalo.Transparency =
markerHalo.Parent = marker
markerFill = .()
markerFill.AnchorPoint = .(, )
markerFill.Position = .(, )
markerFill.Size = .(, )
markerFill.BorderSizePixel =
markerFill.Parent = marker
.(, markerFill).CornerRadius = .(, )
markerRing = .()
markerRing.Color = COLOR_TEXT
markerRing.Thickness =
markerRing.Parent = markerFill
(wheel, (mouse)
d = mouse - (wheel.AbsolutePosition + wheel.AbsoluteSize / )
prefs.xhHue = (.(d.Y, d.X) / ( * .pi)) %
prefs.xhSat = .(d.Magnitude / (wheel.AbsoluteSize.X / ), )
()
)
(y, caption, get, set)
x = WHEEL_SIZE +
cap = (caption, .Font.Gotham, , COLOR_MUTED)
cap.Position = .(x, y)
cap.Size = .(, -x, , )
cap.Parent = pages.colour
bar = .()
bar.Position = .(x, y + )
bar.Size = .(, -x, , )
bar.BackgroundColor3 = COLOR_TEXT
bar.BorderSizePixel =
bar.Parent = pages.colour
.(, bar).CornerRadius = .(, )
gradient = .()
gradient.Parent = bar
knob = .()
knob.AnchorPoint = .(, )
knob.Size = .(, )
knob.BackgroundColor3 = COLOR_TEXT
knob.BorderSizePixel =
knob.Parent = bar
.(, knob).CornerRadius = .(, )
knobEdge = .()
knobEdge.Color = .(, , )
knobEdge.Transparency =
knobEdge.Parent = knob
hit = (bar, (mouse)
(.((mouse.X - bar.AbsolutePosition.X) / bar.AbsoluteSize.X, , ))
()
)
hit.Position = .(, -)
hit.Size = .(, , , )
.(rowRefreshers, ()
knob.Position = .((), , , )
)
gradient
sliderY = (PAGE_H - ) /
brightGradient = (sliderY, , ()
prefs.xhVal
, (v)
prefs.xhVal = v
)
alphaGradient = (sliderY + , , ()
prefs.xhAlpha
, (v)
prefs.xhAlpha = .(v, )
)
alphaGradient.Transparency = NumberSequence.(, )
.(rowRefreshers, ()
a = prefs.xhHue * * .pi
r = prefs.xhSat * wheelR
marker.Position = .(wheelR + .(a) * r, wheelR + .(a) * r)
colour = .(prefs.xhHue, prefs.xhSat, prefs.xhVal)
markerFill.BackgroundColor3 = colour
wheelShade.BackgroundTransparency = prefs.xhVal
brightGradient.Color = ColorSequence.(.(, , ), .(prefs.xhHue, prefs.xhSat, ))
alphaGradient.Color = ColorSequence.(colour)
)
()
editorOpen (EDITOR_GAP + EDITOR_W) /
(tucked)
.(, MENU_W / + EDITOR_GAP - () - (tucked ), , )
(open)
editorOpen = open
()
(menu, TW_SLIDE, { Position = .(, -(), , ) })
open
editor.Position = ()
editor.Visible =
(editor, TW_SLIDE, { Position = (), GroupTransparency = })
(editor, TW_SLIDE, { Position = (), GroupTransparency = }).Completed:(()
(menuOpen editorOpen)
editor.Visible =
)
iconHidden, iconWasEnabled = ,
(hide)
hide
iconHidden
iconHidden =
iconWasEnabled = UserInputService.MouseIconEnabled
UserInputService.MouseIconEnabled
iconWasEnabled =
UserInputService.MouseIconEnabled =
iconHidden
iconHidden =
UserInputService.MouseIconEnabled = iconWasEnabled
()
UserInputService.MouseBehavior = .MouseBehavior.Default
UserInputService.MouseIconEnabled =
UserInputService.MouseIcon =
(open)
open == menuOpen
menuOpen = open
capturing =
()
()
panels = editorOpen { menu, editor } { menu }
open
()
savedMouse = { UserInputService.MouseBehavior, UserInputService.MouseIconEnabled, UserInputService.MouseIcon }
RunService:(MOUSE_STEP, .RenderPriority.Last.Value, freeMouse)
_, p panels
p.Visible =
(p, TW_FADE, { GroupTransparency = })
(menuScale, TW_POP, { Scale = })
RunService:(MOUSE_STEP)
UserInputService.MouseBehavior = savedMouse[]
UserInputService.MouseIconEnabled = savedMouse[]
UserInputService.MouseIcon = savedMouse[]
(menuScale, TW_FADE, { Scale = })
_, p panels
(p, TW_FADE, { GroupTransparency = }).Completed:(()
menuOpen
p.Visible =
)
(key)
name = capturing
capturing =
key ~= .KeyCode.Escape key ~= .KeyCode.Unknown
_, spec KEY_ROWS
spec[] ~= name prefs[spec[]] == key
prefs[spec[]] = prefs[name]
prefs[name] = key
()
()
()
spreadShown =
(dt)
dragUpdate
UserInputService:(.UserInputType.MouseButton1)
(())
()
target = .(turnRate / SPREAD_FULL_TURN, )
spreadShown += (target - spreadShown) * .(dt * , )
live = prefs.crosshair menuOpen UserInputService.MouseBehavior == .MouseBehavior.LockCenter
liveCrosshair.root.Visible = live
live
(liveCrosshair, (spreadShown))
(live)
menuOpen editorOpen
(previewCrosshair, ( - * .(.() * )))
conn = RunService.RenderStepped:((dt)
ok, err = (step, dt)
ok
stats.lastError = (err)
ok, err = (overlayStep, dt)
ok
stats.lastError = (err)
)
inputConn = UserInputService.InputBegan:((input, processed)
processed input.UserInputType ~= .UserInputType.Keyboard
capturing
(input.KeyCode)
input.KeyCode == prefs.menu
( menuOpen)
input.KeyCode == prefs.reset
()
)
env.StrafeTrainer = {
stats = stats,
prefs = prefs,
reset = resetStats,
destroy = ()
()
()
conn:()
inputConn:()
gui:()
env.StrafeTrainer =
,
}Shows speed, per-jump sync % and gain, and which key matches your turn direction. To reset stats press E (rebindable) menu is ; might expand upon this if anyone requests features dc: kurvyz tg: t.me/Kurvvy

KAT