
KeylessUniversal

-[[
MOVEMENT + DASH SYSTEM (with Mobile support and "John Doe" style intro)
-----------------------------------------------------------------
Where to place it: StarterPlayer > StarterPlayerScripts (as a LocalScript)
- Keeps all the original sprint/dash/animation logic.
- Automatically detects if the player is on mobile (touch).
- On mobile, shows an intro in black/yellow with a "scanline"
and glitch effect, then reveals two buttons: [R] sprint and [Q] dash.
- On PC it keeps working normally via keyboard (R and Q).
]]
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local SoundService = game:GetService("SoundService")
local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui")
-- ===================== CONFIG =====================
local HIT_SOUND_ID = "rbxassetid://138651783706047"
local DASH_ANIM_ID = "rbxassetid://73053491533472"
local DASH_DURATION = 0.6
local DASH_SPEED = 85
local DELAY_BEFORE_DASH = 0.5
local DASH_HITBOX_RADIUS = 6
local THEME = {
Background = Color3.fromRGB(5, 5, 5),
Accent = Color3.fromRGB(255, 214, 10),
AccentDim = Color3.fromRGB(120, 100, 0),
Stroke = Color3.fromRGB(40, 36, 0),
}
local isSprinting = false
local character, humanoid, rootPart, animator
local idleTrack, forwardTrack, backwardTrack, sprintTrack, currentTrack, dashTrack
local heartbeatConn, speedLoopTask, dashHitConnection
local isDashing = false
local hitDebounce = {}
local originalCollisionGroup
-- Keep as true while testing on PC/Studio to force the mobile GUI
-- to appear even without touch. Set to false when publishing the game.
local FORCE_MOBILE_UI_FOR_TESTING = true
local isMobile = FORCE_MOBILE_UI_FOR_TESTING
or (UserInputService.TouchEnabled and not UserInputService.KeyboardEnabled)
-- ===================== MOVEMENT LOGIC (original base) =====================
local function onHitDuringDash(hitCharacter)
if not isDashing then return end
if hitDebounce[hitCharacter] then return end
hitDebounce[hitCharacter] = true
local hitSound = Instance.new("Sound")
hitSound.SoundId = HIT_SOUND_ID
hitSound.Volume = 0.7
hitSound.Pitch = 1
hitSound.Parent = SoundService
hitSound:Play()
hitSound.Ended:Connect(function() hitSound:Destroy() end)
task.delay(0.8, function()
hitDebounce[hitCharacter] = nil
end)
end
local function stopTrack(track, fadeTime)
if track and track.IsPlaying then track:Stop(fadeTime or 0.1) end
end
local function playOnly(track, speedOverride)
if not track then return end
if currentTrack == track then
if not track.IsPlaying then track:Play(0.1) end
if speedOverride then track:AdjustSpeed(speedOverride) end
return
end
if currentTrack then currentTrack:Stop(0.1) end
currentTrack = track
track:Play(0.1, 1, speedOverride or 1)
end
local function makeTrack(id, priority, looped)
local anim = Instance.new("Animation")
anim.AnimationId = id
local track = animator:LoadAnimation(anim)
track.Priority = priority
track.Looped = looped or false
return track
end
local function cleanup()
if heartbeatConn then heartbeatConn:Disconnect() end
if dashHitConnection then dashHitConnection:Disconnect() end
stopTrack(idleTrack)
stopTrack(forwardTrack)
stopTrack(backwardTrack)
stopTrack(sprintTrack)
stopTrack(dashTrack)
hitDebounce = {}
if character and originalCollisionGroup then
for _, part in ipairs(character:GetDescendants()) do
if part:IsA("BasePart") then
part.CollisionGroup = originalCollisionGroup
part.CanCollide = true
end
end
end
end
local function applyWalkSpeed()
if not humanoid then return end
local md = humanoid.MoveDirection
local moving = md.Magnitude > 0.1
if not moving then
humanoid.WalkSpeed = isSprinting and 24 or 8
return
end
local dot = md:Dot(rootPart.CFrame.LookVector)
humanoid.WalkSpeed = (dot < -0.2) and 6 or (isSprinting and 24 or 8)
end
local function updateAnimations()
if not humanoid or not rootPart then return end
local md = humanoid.MoveDirection
local moving = md.Magnitude > 0.1
if not moving then
playOnly(idleTrack)
elseif md:Dot(rootPart.CFrame.LookVector) < -0.2 then
playOnly(backwardTrack)
elseif isSprinting then
playOnly(sprintTrack, 2.5)
else
playOnly(forwardTrack)
end
end
-- ===== Reusable actions (called by both keyboard AND mobile buttons) =====
local function toggleSprint()
if isDashing then return end
isSprinting = not isSprinting
applyWalkSpeed()
updateAnimations()
end
local function dash()
if not character or not rootPart or not humanoid or isDashing then return end
isDashing = true
isSprinting = false
hitDebounce = {}
originalCollisionGroup = rootPart.CollisionGroup
for _, part in ipairs(character:GetDescendants()) do
if part:IsA("BasePart") then
part.CollisionGroup = "Default"
part.CanCollide = false
end
end
if animator then
local anim = Instance.new("Animation")
anim.AnimationId = DASH_ANIM_ID
dashTrack = animator:LoadAnimation(anim)
dashTrack.Priority = Enum.AnimationPriority.Action3
dashTrack.Looped = false
dashTrack:Play()
end
task.wait(DELAY_BEFORE_DASH)
if not rootPart or not rootPart.Parent then
isDashing = false
return
end
humanoid.AutoRotate = false
local forwardDir = rootPart.CFrame.LookVector
local currentVel = rootPart.AssemblyLinearVelocity
local dashTween = TweenService:Create(rootPart, TweenInfo.new(DASH_DURATION, Enum.EasingStyle.Cubic, Enum.EasingDirection.Out), {
AssemblyLinearVelocity = forwardDir * DASH_SPEED + Vector3.new(0, currentVel.Y, 0)
})
dashTween:Play()
dashTween.Completed:Connect(function()
humanoid.AutoRotate = true
isDashing = false
end)
task.delay(DASH_DURATION + 0.5, function()
isDashing = false
humanoid.AutoRotate = true
end)
end
local function setupDashHitDetection()
if dashHitConnection then dashHitConnection:Disconnect() end
dashHitConnection = RunService.Heartbeat:Connect(function()
if not isDashing or not rootPart then return end
local rootPos = rootPart.Position
local parts = workspace:GetPartBoundsInRadius(rootPos, DASH_HITBOX_RADIUS)
for _, part in ipairs(parts) do
local hitChar = part.Parent
if hitChar and hitChar:FindFirstChild("Humanoid") and hitChar ~= character then
onHitDuringDash(hitChar)
end
end
end)
end
local function setupCharacter(char)
cleanup()
character = char
task.wait(0.3)
humanoid = character:WaitForChild("Humanoid", 5)
rootPart = character:WaitForChild("HumanoidRootPart", 5)
if not humanoid or not rootPart then return end
animator = humanoid:FindFirstChildOfClass("Animator") or Instance.new("Animator", humanoid)
local animate = character:FindFirstChild("Animate")
if animate then animate.Enabled = false end
idleTrack = makeTrack("rbxassetid://111792319821341", Enum.AnimationPriority.Action, true)
forwardTrack = makeTrack("rbxassetid://138795419712161", Enum.AnimationPriority.Action, true)
backwardTrack = makeTrack("rbxassetid://95970874156673", Enum.AnimationPriority.Action, true)
sprintTrack = makeTrack("rbxassetid://94467125495426", Enum.AnimationPriority.Action4, true)
applyWalkSpeed()
updateAnimations()
setupDashHitDetection()
speedLoopTask = task.spawn(function()
while character and character.Parent do
applyWalkSpeed()
task.wait(0.1)
end
end)
heartbeatConn = RunService.Heartbeat:Connect(function()
if isSprinting and sprintTrack and sprintTrack.IsPlaying then
sprintTrack:AdjustSpeed(2.5)
end
updateAnimations()
end)
end
-- ===================== KEYBOARD (PC) =====================
UserInputService.InputBegan:Connect(function(input, gp)
if gp then return end
if input.KeyCode == Enum.KeyCode.R then
toggleSprint()
elseif input.KeyCode == Enum.KeyCode.Q then
dash()
end
end)
-- ===================== MOBILE GUI (black/yellow, "hacker" style) =====================
local function createStroke(parent, thickness, color)
local stroke = Instance.new("UIStroke")
stroke.Thickness = thickness or 1
stroke.Color = color or THEME.Stroke
stroke.Parent = parent
return stroke
end
local function createCorner(parent, radius)
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0, radius or 12)
corner.Parent = parent
return corner
end
-- ---------- Intro (black screen, yellow text, scanline + glitch) ----------
local function playIntro(onFinished)
local introGui = Instance.new("ScreenGui")
introGui.Name = "IntroGui"
introGui.ResetOnSpawn = false
introGui.IgnoreGuiInset = true
introGui.DisplayOrder = 100
introGui.Parent = playerGui
local bg = Instance.new("Frame")
bg.Size = UDim2.fromScale(1, 1)
bg.BackgroundColor3 = THEME.Background
bg.BackgroundTransparency = 1
bg.BorderSizePixel = 0
bg.Parent = introGui
local scan = Instance.new("Frame")
scan.Size = UDim2.new(1, 0, 0, 2)
scan.BackgroundColor3 = THEME.Accent
scan.BackgroundTransparency = 0.4
scan.BorderSizePixel = 0
scan.Position = UDim2.new(0, 0, 0, -10)
scan.ZIndex = 5
scan.Parent = bg
local title = Instance.new("TextLabel")
title.Size = UDim2.new(0.9, 0, 0.15, 0)
title.Position = UDim2.new(0.05, 0, 0.42, 0)
title.BackgroundTransparency = 1
title.Font = Enum.Font.Code
title.Text = "SYSTEM INITIALIZING"
title.TextColor3 = THEME.Accent
title.TextTransparency = 1
title.TextScaled = true
title.TextStrokeTransparency = 0.6
title.TextStrokeColor3 = Color3.new(0, 0, 0)
title.Parent = bg
local subtitle = Instance.new("TextLabel")
subtitle.Size = UDim2.new(0.9, 0, 0.06, 0)
subtitle.Position = UDim2.new(0.05, 0, 0.58, 0)
subtitle.BackgroundTransparency = 1
subtitle.Font = Enum.Font.Code
subtitle.Text = "loading controls..."
subtitle.TextColor3 = THEME.AccentDim
subtitle.TextTransparency = 1
subtitle.TextScaled = true
subtitle.Parent = bg
TweenService:Create(bg, TweenInfo.new(0.5, Enum.EasingStyle.Sine), {BackgroundTransparency = 0.05}):Play()
TweenService:Create(title, TweenInfo.new(0.6, Enum.EasingStyle.Sine), {TextTransparency = 0}):Play()
TweenService:Create(subtitle, TweenInfo.new(0.6, Enum.EasingStyle.Sine), {TextTransparency = 0.2}):Play()
-- scanline moving down repeatedly
task.spawn(function()
for _ = 1, 3 do
scan.Position = UDim2.new(0, 0, 0, -10)
TweenService:Create(scan, TweenInfo.new(1, Enum.EasingStyle.Linear), {Position = UDim2.new(0, 0, 1, 10)}):Play()
task.wait(1)
end
end)
-- slight flicker on the title (glitch effect)
task.spawn(function()
for _ = 1, 6 do
task.wait(math.random(15, 30) / 100)
title.TextTransparency = (math.random(0, 100) < 15) and 0.5 or 0
end
end)
task.wait(2.4)
local fadeOut = TweenService:Create(bg, TweenInfo.new(0.6, Enum.EasingStyle.Quad), {BackgroundTransparency = 1})
TweenService:Create(title, TweenInfo.new(0.4, Enum.EasingStyle.Quad), {TextTransparency = 1}):Play()
TweenService:Create(subtitle, TweenInfo.new(0.4, Enum.EasingStyle.Quad), {TextTransparency = 1}):Play()
fadeOut:Play()
fadeOut.Completed:Connect(function()
introGui:Destroy()
if onFinished then onFinished() end
end)
end
-- ---------- Fake CAPTCHA ("prove you're not a bot") ----------
local CAPTCHA_CHARS = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" -- no ambiguous chars (I, O, 0, 1)
local function generateCaptchaCode(length)
length = length or 5
local code = ""
for _ = 1, length do
local index = math.random(1, #CAPTCHA_CHARS)
code = code .. CAPTCHA_CHARS:sub(index, index)
end
return code
end
local function showCaptcha(onFinished)
local captchaGui = Instance.new("ScreenGui")
captchaGui.Name = "CaptchaGui"
captchaGui.ResetOnSpawn = false
captchaGui.IgnoreGuiInset = true
captchaGui.DisplayOrder = 95
captchaGui.Parent = playerGui
local overlay = Instance.new("Frame")
overlay.Size = UDim2.fromScale(1, 1)
overlay.BackgroundColor3 = THEME.Background
overlay.BackgroundTransparency = 1
overlay.BorderSizePixel = 0
overlay.Parent = captchaGui
local panel = Instance.new("Frame")
panel.Size = UDim2.fromOffset(380, 280)
panel.AnchorPoint = Vector2.new(0.5, 0.5)
panel.Position = UDim2.fromScale(0.5, 0.5)
panel.BackgroundColor3 = THEME.Background
panel.BackgroundTransparency = 1
panel.BorderSizePixel = 0
panel.Parent = overlay
createCorner(panel, 14)
local panelStroke = createStroke(panel, 2, THEME.Accent)
panelStroke.Transparency = 1
local titleLabel = Instance.new("TextLabel")
titleLabel.Size = UDim2.new(1, -30, 0, 32)
titleLabel.Position = UDim2.new(0, 15, 0, 15)
titleLabel.BackgroundTransparency = 1
titleLabel.Font = Enum.Font.Code
titleLabel.Text = "VERIFY YOU ARE NOT A BOT"
titleLabel.TextColor3 = THEME.Accent
titleLabel.TextTransparency = 1
titleLabel.TextScaled = true
titleLabel.Parent = panel
-- code display area
local codeHolder = Instance.new("Frame")
codeHolder.Size = UDim2.new(1, -30, 0, 60)
codeHolder.Position = UDim2.new(0, 15, 0, 60)
codeHolder.BackgroundColor3 = Color3.fromRGB(15, 15, 15)
codeHolder.BackgroundTransparency = 1
codeHolder.Parent = panel
createCorner(codeHolder, 8)
local codeStroke = createStroke(codeHolder, 1, THEME.AccentDim)
codeStroke.Transparency = 1
local codeLayout = Instance.new("UIListLayout")
codeLayout.FillDirection = Enum.FillDirection.Horizontal
codeLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
codeLayout.VerticalAlignment = Enum.VerticalAlignment.Center
codeLayout.Padding = UDim.new(0, 6)
codeLayout.Parent = codeHolder
local currentCode = ""
local codeLabels = {}
-- draws the distorted code (random tilt per character, like a real captcha)
local function renderCode()
for _, lbl in ipairs(codeLabels) do lbl:Destroy() end
codeLabels = {}
currentCode = generateCaptchaCode(5)
for i = 1, #currentCode do
local ch = currentCode:sub(i, i)
local lbl = Instance.new("TextLabel")
lbl.Size = UDim2.fromOffset(36, 44)
lbl.BackgroundTransparency = 1
lbl.Font = Enum.Font.Code
lbl.Text = ch
lbl.TextScaled = true
lbl.TextColor3 = THEME.Accent
lbl.Rotation = math.random(-12, 12)
lbl.Parent = codeHolder
table.insert(codeLabels, lbl)
end
end
renderCode()
local inputBox = Instance.new("TextBox")
inputBox.Size = UDim2.new(1, -30, 0, 40)
inputBox.Position = UDim2.new(0, 15, 0, 135)
inputBox.BackgroundColor3 = Color3.fromRGB(10, 10, 10)
inputBox.BackgroundTransparency = 1
inputBox.PlaceholderText = "Type the code above"
inputBox.PlaceholderColor3 = THEME.AccentDim
inputBox.Text = ""
inputBox.Font = Enum.Font.Code
inputBox.TextScaled = true
inputBox.TextColor3 = THEME.Accent
inputBox.ClearTextOnFocus = false
inputBox.Parent = panel
createCorner(inputBox, 8)
local inputStroke = createStroke(inputBox, 1.5, THEME.AccentDim)
inputStroke.Transparency = 1
local errorLabel = Instance.new("TextLabel")
errorLabel.Size = UDim2.new(1, -30, 0, 20)
errorLabel.Position = UDim2.new(0, 15, 0, 180)
errorLabel.BackgroundTransparency = 1
errorLabel.Font = Enum.Font.Code
errorLabel.Text = "Incorrect code, try again."
errorLabel.TextColor3 = Color3.fromRGB(255, 90, 90)
errorLabel.TextTransparency = 1
errorLabel.TextScaled = true
errorLabel.Parent = panel
local verifyButton = Instance.new("TextButton")
verifyButton.Size = UDim2.fromOffset(140, 40)
verifyButton.AnchorPoint = Vector2.new(0.5, 1)
verifyButton.Position = UDim2.new(0.5, 0, 1, -15)
verifyButton.BackgroundColor3 = THEME.Background
verifyButton.BackgroundTransparency = 1
verifyButton.Text = "VERIFY"
verifyButton.Font = Enum.Font.Code
verifyButton.TextScaled = true
verifyButton.TextColor3 = THEME.Accent
verifyButton.TextTransparency = 1
verifyButton.AutoButtonColor = false
verifyButton.Parent = panel
createCorner(verifyButton, 8)
local verifyStroke = createStroke(verifyButton, 2, THEME.Accent)
verifyStroke.Transparency = 1
-- fade in everything
TweenService:Create(overlay, TweenInfo.new(0.4), {BackgroundTransparency = 0.35}):Play()
TweenService:Create(panel, TweenInfo.new(0.4), {BackgroundTransparency = 0.1}):Play()
TweenService:Create(panelStroke, TweenInfo.new(0.4), {Transparency = 0}):Play()
TweenService:Create(titleLabel, TweenInfo.new(0.4), {TextTransparency = 0}):Play()
TweenService:Create(codeHolder, TweenInfo.new(0.4), {BackgroundTransparency = 0.2}):Play()
TweenService:Create(codeStroke, TweenInfo.new(0.4), {Transparency = 0.2}):Play()
TweenService:Create(inputBox, TweenInfo.new(0.4), {BackgroundTransparency = 0.15}):Play()
TweenService:Create(inputStroke, TweenInfo.new(0.4), {Transparency = 0.2}):Play()
TweenService:Create(verifyButton, TweenInfo.new(0.4), {BackgroundTransparency = 0.2, TextTransparency = 0}):Play()
TweenService:Create(verifyStroke, TweenInfo.new(0.4), {Transparency = 0}):Play()
-- shake effect when the code is wrong
local function shakePanel()
local originalPos = panel.Position
task.spawn(function()
for _, offset in ipairs({-12, 10, -8, 6, 0}) do
TweenService:Create(panel, TweenInfo.new(0.06, Enum.EasingStyle.Linear), {
Position = originalPos + UDim2.fromOffset(offset, 0)
}):Play()
task.wait(0.06)
end
end)
end
local function closeCaptcha()
local fade = TweenService:Create(overlay, TweenInfo.new(0.35), {BackgroundTransparency = 1})
TweenService:Create(panel, TweenInfo.new(0.35), {BackgroundTransparency = 1}):Play()
TweenService:Create(panelStroke, TweenInfo.new(0.35), {Transparency = 1}):Play()
TweenService:Create(titleLabel, TweenInfo.new(0.35), {TextTransparency = 1}):Play()
TweenService:Create(codeHolder, TweenInfo.new(0.35), {BackgroundTransparency = 1}):Play()
TweenService:Create(codeStroke, TweenInfo.new(0.35), {Transparency = 1}):Play()
TweenService:Create(inputBox, TweenInfo.new(0.35), {BackgroundTransparency = 1}):Play()
TweenService:Create(inputStroke, TweenInfo.new(0.35), {Transparency = 1}):Play()
TweenService:Create(verifyButton, TweenInfo.new(0.35), {BackgroundTransparency = 1, TextTransparency = 1}):Play()
TweenService:Create(verifyStroke, TweenInfo.new(0.35), {Transparency = 1}):Play()
for _, lbl in ipairs(codeLabels) do
TweenService:Create(lbl, TweenInfo.new(0.35), {TextTransparency = 1}):Play()
end
fade:Play()
fade.Completed:Connect(function()
captchaGui:Destroy()
if onFinished then onFinished() end
end)
end
local function attemptVerify()
local typed = inputBox.Text:upper():gsub("%s", "")
if typed == currentCode then
closeCaptcha()
else
shakePanel()
inputBox.Text = ""
errorLabel.TextTransparency = 0
task.delay(1.5, function()
if errorLabel.Parent then
TweenService:Create(errorLabel, TweenInfo.new(0.3), {TextTransparency = 1}):Play()
end
end)
renderCode()
end
end
verifyButton.MouseButton1Click:Connect(attemptVerify)
inputBox.FocusLost:Connect(function(enterPressed)
if enterPressed then attemptVerify() end
end)
end
-- ---------- Mobile buttons ----------
local function createMobileButton(name, text, position)
local button = Instance.new("TextButton")
button.Name = name
button.Size = UDim2.fromOffset(80, 80)
button.Position = position
button.AnchorPoint = Vector2.new(0.5, 0.5)
button.BackgroundColor3 = THEME.Background
button.BackgroundTransparency = 0.25
button.Text = text
button.Font = Enum.Font.Code
button.TextScaled = true
button.TextColor3 = THEME.Accent
button.AutoButtonColor = false
createCorner(button, 40)
local stroke = createStroke(button, 2, THEME.Accent)
button.MouseButton1Down:Connect(function()
TweenService:Create(button, TweenInfo.new(0.1), {BackgroundTransparency = 0}):Play()
TweenService:Create(stroke, TweenInfo.new(0.1), {Thickness = 4}):Play()
end)
button.MouseButton1Up:Connect(function()
TweenService:Create(button, TweenInfo.new(0.15), {BackgroundTransparency = 0.25}):Play()
TweenService:Create(stroke, TweenInfo.new(0.15), {Thickness = 2}):Play()
end)
return button
end
-- Pulsing yellow halo behind the button (glow effect)
local function createGlow(button)
local glow = Instance.new("Frame")
glow.Name = "Glow"
glow.AnchorPoint = Vector2.new(0.5, 0.5)
glow.Position = UDim2.fromScale(0.5, 0.5)
glow.Size = UDim2.fromOffset(button.Size.X.Offset + 20, button.Size.Y.Offset + 20)
glow.BackgroundColor3 = THEME.Accent
glow.BackgroundTransparency = 0.85
glow.ZIndex = button.ZIndex - 1
glow.Parent = button
createCorner(glow, 999)
task.spawn(function()
while glow.Parent do
local grow = TweenService:Create(glow, TweenInfo.new(1.1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), {
BackgroundTransparency = 0.55,
Size = UDim2.fromOffset(button.Size.X.Offset + 45, button.Size.Y.Offset + 45),
})
grow:Play()
grow.Completed:Wait()
if not glow.Parent then break end
local shrink = TweenService:Create(glow, TweenInfo.new(1.1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), {
BackgroundTransparency = 0.85,
Size = UDim2.fromOffset(button.Size.X.Offset + 20, button.Size.Y.Offset + 20),
})
shrink:Play()
shrink.Completed:Wait()
end
end)
return glow
end
-- "Floating" effect (smoothly moves up and down)
local function applyFloatingEffect(guiObject, amplitude, duration)
amplitude = amplitude or 6
duration = duration or 1.5
task.spawn(function()
while guiObject.Parent do
local basePos = guiObject.Position
local up = TweenService:Create(guiObject, TweenInfo.new(duration, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), {
Position = basePos - UDim2.fromOffset(0, amplitude)
})
up:Play()
up.Completed:Wait()
if not guiObject.Parent then break end
local down = TweenService:Create(guiObject, TweenInfo.new(duration, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), {
Position = basePos
})
down:Play()
down.Completed:Wait()
end
end)
end
-- ---------- Explanatory menu (PC + Mobile) ----------
local function showControlsMenu(onFinished)
local menuGui = Instance.new("ScreenGui")
menuGui.Name = "ControlsMenu"
menuGui.ResetOnSpawn = false
menuGui.IgnoreGuiInset = true
menuGui.DisplayOrder = 90
menuGui.Parent = playerGui
local overlay = Instance.new("Frame")
overlay.Size = UDim2.fromScale(1, 1)
overlay.BackgroundColor3 = THEME.Background
overlay.BackgroundTransparency = 1
overlay.BorderSizePixel = 0
overlay.Parent = menuGui
local panel = Instance.new("Frame")
panel.Size = UDim2.fromOffset(420, 260)
panel.AnchorPoint = Vector2.new(0.5, 0.5)
panel.Position = UDim2.fromScale(0.5, 0.55)
panel.BackgroundColor3 = THEME.Background
panel.BackgroundTransparency = 1
panel.BorderSizePixel = 0
panel.Parent = overlay
createCorner(panel, 14)
local panelStroke = createStroke(panel, 2, THEME.Accent)
panelStroke.Transparency = 1
local titleLabel = Instance.new("TextLabel")
titleLabel.Size = UDim2.new(1, -30, 0, 40)
titleLabel.Position = UDim2.new(0, 15, 0, 15)
titleLabel.BackgroundTransparency = 1
titleLabel.Font = Enum.Font.Code
titleLabel.Text = "COMPATIBLE: PC + MOBILE"
titleLabel.TextColor3 = THEME.Accent
titleLabel.TextTransparency = 1
titleLabel.TextScaled = true
titleLabel.Parent = panel
local bodyLabel = Instance.new("TextLabel")
bodyLabel.Size = UDim2.new(1, -30, 0, 130)
bodyLabel.Position = UDim2.new(0, 15, 0, 65)
bodyLabel.BackgroundTransparency = 1
bodyLabel.Font = Enum.Font.Code
bodyLabel.TextColor3 = THEME.AccentDim
bodyLabel.TextTransparency = 1
bodyLabel.TextWrapped = true
bodyLabel.TextXAlignment = Enum.TextXAlignment.Left
bodyLabel.TextYAlignment = Enum.TextYAlignment.Top
bodyLabel.TextSize = 18
bodyLabel.Text = "> On PC: press [R] to sprint and [Q] to dash.\n\n> On Mobile: use the floating buttons on screen for the same actions."
bodyLabel.Parent = panel
local okButton = Instance.new("TextButton")
okButton.Size = UDim2.fromOffset(140, 40)
okButton.AnchorPoint = Vector2.new(0.5, 1)
okButton.Position = UDim2.new(0.5, 0, 1, -15)
okButton.BackgroundColor3 = THEME.Background
okButton.BackgroundTransparency = 1
okButton.Text = "GOT IT"
okButton.Font = Enum.Font.Code
okButton.TextScaled = true
okButton.TextColor3 = THEME.Accent
okButton.TextTransparency = 1
okButton.AutoButtonColor = false
okButton.Parent = panel
createCorner(okButton, 8)
local okStroke = createStroke(okButton, 2, THEME.Accent)
okStroke.Transparency = 1
-- fade in everything
TweenService:Create(overlay, TweenInfo.new(0.4), {BackgroundTransparency = 0.35}):Play()
TweenService:Create(panel, TweenInfo.new(0.4), {BackgroundTransparency = 0.1}):Play()
TweenService:Create(panelStroke, TweenInfo.new(0.4), {Transparency = 0}):Play()
TweenService:Create(titleLabel, TweenInfo.new(0.4), {TextTransparency = 0}):Play()
TweenService:Create(bodyLabel, TweenInfo.new(0.4), {TextTransparency = 0.1}):Play()
TweenService:Create(okButton, TweenInfo.new(0.4), {BackgroundTransparency = 0.2}):Play()
TweenService:Create(okStroke, TweenInfo.new(0.4), {Transparency = 0}):Play()
TweenService:Create(okButton, TweenInfo.new(0.4), {TextTransparency = 0}):Play()
local function closeMenu()
local fade = TweenService:Create(overlay, TweenInfo.new(0.35), {BackgroundTransparency = 1})
TweenService:Create(panel, TweenInfo.new(0.35), {BackgroundTransparency = 1}):Play()
TweenService:Create(panelStroke, TweenInfo.new(0.35), {Transparency = 1}):Play()
TweenService:Create(titleLabel, TweenInfo.new(0.35), {TextTransparency = 1}):Play()
TweenService:Create(bodyLabel, TweenInfo.new(0.35), {TextTransparency = 1}):Play()
TweenService:Create(okButton, TweenInfo.new(0.35), {BackgroundTransparency = 1, TextTransparency = 1}):Play()
TweenService:Create(okStroke, TweenInfo.new(0.35), {Transparency = 1}):Play()
fade:Play()
fade.Completed:Connect(function()
menuGui:Destroy()
if onFinished then onFinished() end
end)
end
okButton.MouseButton1Click:Connect(closeMenu)
end
local function createMobileControls()
local gui = Instance.new("ScreenGui")
gui.Name = "MobileControls"
gui.ResetOnSpawn = false
gui.IgnoreGuiInset = true
gui.Enabled = false
gui.Parent = playerGui
local holder = Instance.new("Frame")
holder.Name = "Holder"
holder.Size = UDim2.fromScale(1, 1)
holder.BackgroundTransparency = 1
holder.Parent = gui
local sprintButton = createMobileButton("SprintButton", "R", UDim2.new(1, -170, 1, -110))
sprintButton.Parent = holder
createGlow(sprintButton)
local dashButton = createMobileButton("DashButton", "Q", UDim2.new(1, -80, 1, -110))
dashButton.Parent = holder
createGlow(dashButton)
for _, btn in ipairs({sprintButton, dashButton}) do
local finalPos = btn.Position
btn.Position = finalPos + UDim2.fromOffset(0, 120)
btn.BackgroundTransparency = 1
local entrance = TweenService:Create(btn, TweenInfo.new(0.4, Enum.EasingStyle.Back, Enum.EasingDirection.Out), {
Position = finalPos,
BackgroundTransparency = 0.25,
})
entrance:Play()
entrance.Completed:Connect(function()
applyFloatingEffect(btn, 6, 1.4)
end)
end
sprintButton.MouseButton1Click:Connect(toggleSprint)
dashButton.MouseButton1Click:Connect(dash)
RunService.Heartbeat:Connect(function()
sprintButton.TextColor3 = isSprinting and THEME.Accent or THEME.AccentDim
end)
return gui
end
-- ===================== INITIALIZATION =====================
player.CharacterAdded:Connect(setupCharacter)
player.CharacterRemoving:Connect(cleanup)
if player.Character then
task.spawn(setupCharacter, player.Character)
end
if isMobile then
playIntro(function()
showCaptcha(function()
showControlsMenu(function()
local mobileGui = createMobileControls()
mobileGui.Enabled = true
end)
end)
end)
endNo comments yet for this script.



