robloxexploits.lol
KeylessUniversal

The Full Sonic Script

Ps4sro 2 years ago 65K views

Run it

Copy the script and paste it into your executor.

The Full Sonic Script.lua · 388 lines
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local ContextActionService = game:GetService("ContextActionService")
local TweenService = game:GetService("TweenService")

local player = Players.LocalPlayer
local camera = workspace.CurrentCamera

-- --- CONFIGURATION ---
local CONFIG = {
	-- Movement
	DoubleJumpPower = 60,
	RollDuration = 0.5,
	RollDistance = 50,
	BaseWalkSpeed = 16,
	MaxWalkSpeed = 150,
	Acceleration = 30,
	BrakingDuration = 0.7,
	StopThreshold = 1,
	BaseFOV = 70,
	MaxFOV = 120,
	
	-- Tool
	DashSpeed = 200,
	DashMaxTime = 1,
	
	-- Assets
	RollAnimID = "rbxassetid://18537367238",
	RunAnimID = "rbxassetid://85752365414182",
	GreenCursorID = "rbxassetid://1460596350"
}

local DECELERATION = CONFIG.MaxWalkSpeed / CONFIG.BrakingDuration

-- --- STATE VARIABLES ---
local isMobileMode = false
local selectionMade = false
local currentCharacter = nil

-- --- GUI CREATION ---
local function createIntroGUI()
	local existing = player:WaitForChild("PlayerGui"):FindFirstChild("MaldixIntroGUI")
	if existing then existing:Destroy() end

	local screenGui = Instance.new("ScreenGui")
	screenGui.Name = "MaldixIntroGUI"
	screenGui.Parent = player:WaitForChild("PlayerGui")
	screenGui.ResetOnSpawn = false
	
	local frame = Instance.new("Frame")
	frame.Name = "MainFrame"
	frame.Size = UDim2.new(0, 400, 0, 350)
	frame.Position = UDim2.new(0.5, 0, 0.5, 0)
	frame.AnchorPoint = Vector2.new(0.5, 0.5)
	frame.BackgroundColor3 = Color3.new(0.14, 0.14, 0.14) 
	frame.BorderSizePixel = 0
	frame.Parent = screenGui
	
	local uiCorner = Instance.new("UICorner")
	uiCorner.CornerRadius = UDim.new(0, 12)
	uiCorner.Parent = frame
	
	local header = Instance.new("TextLabel")
	header.Text = "Maldix's Sonic Script"
	header.Size = UDim2.new(1, 0, 0, 50)
	header.BackgroundTransparency = 1
	header.TextColor3 = Color3.new(0.33, 1, 0.5) 
	header.Font = Enum.Font.FredokaOne
	header.TextSize = 28
	header.Parent = frame
	
	local desc = Instance.new("TextLabel")
	desc.Text = [[
Controls:
• WASD / Joystick: Move (Accelerate)
• Space: Jump (Double tap to Double Jump)
• R / Button: Roll (Spam to go fast)
• Dash Tool: Click in air to Homing Dash

Please select your device type:
]]
	desc.Size = UDim2.new(1, -40, 0, 200)
	desc.Position = UDim2.new(0, 20, 0, 50)
	desc.BackgroundTransparency = 1
	desc.TextColor3 = Color3.new(0.86, 0.86, 0.86)
	desc.Font = Enum.Font.GothamMedium
	desc.TextSize = 16
	desc.TextXAlignment = Enum.TextXAlignment.Left
	desc.TextYAlignment = Enum.TextYAlignment.Top
	desc.TextWrapped = true
	desc.Parent = frame
	
	local btnPC = Instance.new("TextButton")
	btnPC.Name = "PCButton"
	btnPC.Text = "PC"
	btnPC.Size = UDim2.new(0.4, 0, 0, 50)
	btnPC.Position = UDim2.new(0.05, 0, 1, -60)
	btnPC.BackgroundColor3 = Color3.new(0.23, 0.23, 0.23)
	btnPC.TextColor3 = Color3.new(1, 1, 1)
	btnPC.Font = Enum.Font.GothamBold
	btnPC.TextSize = 18
	btnPC.Parent = frame
	
	local btnCorner1 = Instance.new("UICorner")
	btnCorner1.CornerRadius = UDim.new(0, 8)
	btnCorner1.Parent = btnPC
	
	local btnMobile = Instance.new("TextButton")
	btnMobile.Name = "MobileButton"
	btnMobile.Text = "Mobile"
	btnMobile.Size = UDim2.new(0.4, 0, 0, 50)
	btnMobile.Position = UDim2.new(0.55, 0, 1, -60)
	btnMobile.BackgroundColor3 = Color3.new(0.23, 0.23, 0.23)
	btnMobile.TextColor3 = Color3.new(1, 1, 1)
	btnMobile.Font = Enum.Font.GothamBold
	btnMobile.TextSize = 18
	btnMobile.Parent = frame

	local btnCorner2 = Instance.new("UICorner")
	btnCorner2.CornerRadius = UDim.new(0, 8)
	btnCorner2.Parent = btnMobile
	
	local function closeGui()
		screenGui:Destroy()
	end
	
	btnPC.MouseButton1Click:Connect(function()
		isMobileMode = false
		selectionMade = true
		closeGui()
	end)
	
	btnMobile.MouseButton1Click:Connect(function()
		isMobileMode = true
		selectionMade = true
		closeGui()
	end)
end

-- --- MAIN LOGIC ---

local function onCharacterAdded(character)
	currentCharacter = character
	local humanoid = character:WaitForChild("Humanoid")
	local rootPart = character:WaitForChild("HumanoidRootPart")
	local animator = humanoid:WaitForChild("Animator")

	humanoid.WalkSpeed = CONFIG.BaseWalkSpeed
	local currentSpeed = CONFIG.BaseWalkSpeed
	local lastMoveDirection = Vector3.new(0, 0, -1)
	
	-- --- ANIMATIONS ---
	local runAnim = Instance.new("Animation")
	runAnim.AnimationId = CONFIG.RunAnimID
	local runTrack = animator:LoadAnimation(runAnim)
	runTrack.Priority = Enum.AnimationPriority.Movement
	runTrack.Looped = true

	local rollAnim = Instance.new("Animation")
	rollAnim.AnimationId = CONFIG.RollAnimID
	local rollTrack = animator:LoadAnimation(rollAnim)
	rollTrack.Priority = Enum.AnimationPriority.Action
	rollTrack.Looped = true

	local jumpAnim = Instance.new("Animation")
	jumpAnim.AnimationId = CONFIG.RollAnimID
	local jumpTrack = animator:LoadAnimation(jumpAnim)
	jumpTrack.Priority = Enum.AnimationPriority.Action
	jumpTrack.Looped = false

	-- --- TOOL SETUP ---
	local tool = Instance.new("Tool")
	tool.Name = "Dash Cursor"
	tool.RequiresHandle = false
	tool.CanBeDropped = false
	tool.Parent = player.Backpack
	local mouse = player:GetMouse()

	tool.Equipped:Connect(function() mouse.Icon = CONFIG.GreenCursorID end)
	tool.Unequipped:Connect(function() mouse.Icon = "" end)

	tool.Activated:Connect(function()
		local state = humanoid:GetState()
		local isInAir = (state == Enum.HumanoidStateType.Freefall or state == Enum.HumanoidStateType.Jumping)
		if isInAir then
			local targetPos = mouse.Hit.Position
			local startPos = rootPart.Position
			local direction = (targetPos - startPos).Unit
			local distance = (targetPos - startPos).Magnitude
			local duration = math.min(distance / CONFIG.DashSpeed, CONFIG.DashMaxTime)

			rollTrack:Play()
			local bv = Instance.new("BodyVelocity")
			bv.Velocity = direction * CONFIG.DashSpeed
			bv.MaxForce = Vector3.new(1e5, 1e5, 1e5)
			bv.P = 10000
			bv.Parent = rootPart
			
			local bg = Instance.new("BodyGyro")
			bg.CFrame = CFrame.lookAt(startPos, targetPos)
			bg.MaxTorque = Vector3.new(1e5, 1e5, 1e5)
			bg.P = 20000
			bg.Parent = rootPart

			task.delay(duration, function()
				if bv then bv:Destroy() end
				if bg then bg:Destroy() end
				rollTrack:Stop()
				rootPart.AssemblyLinearVelocity = Vector3.zero
			end)
		end
	end)

	-- --- DOUBLE JUMP ---
	local hasDoubleJumped = false
	local canTriggerDoubleJump = false
	
	humanoid.StateChanged:Connect(function(oldState, newState)
		if newState == Enum.HumanoidStateType.Landed then
			hasDoubleJumped = false
			canTriggerDoubleJump = false
		elseif newState == Enum.HumanoidStateType.Jumping then
			canTriggerDoubleJump = false
			task.wait(0.2)
			canTriggerDoubleJump = true
		elseif newState == Enum.HumanoidStateType.Freefall then
			if oldState == Enum.HumanoidStateType.Landed then
				canTriggerDoubleJump = true
			end
		end
	end)
	
	UserInputService.JumpRequest:Connect(function()
		local state = humanoid:GetState()
		local isInAir = (state == Enum.HumanoidStateType.Freefall or state == Enum.HumanoidStateType.Jumping)
		if canTriggerDoubleJump and not hasDoubleJumped and isInAir then
			hasDoubleJumped = true
			rootPart.AssemblyLinearVelocity = Vector3.new(rootPart.AssemblyLinearVelocity.X, CONFIG.DoubleJumpPower, rootPart.AssemblyLinearVelocity.Z)
			jumpTrack:Stop()
			jumpTrack:Play()
			humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
		end
	end)

	-- --- ROLL LOGIC ---
	local rolling = false
	local holdingRollKey = false

	local function stopRolling()
		rolling = false
		rollTrack:Stop()
	end

	local function performRoll()
		local direction = rootPart.CFrame.LookVector
		local startPos = rootPart.Position
		local targetPos = startPos + (direction * CONFIG.RollDistance)
		local startTime = tick()
		local connection
		connection = RunService.RenderStepped:Connect(function()
			local elapsed = tick() - startTime
			if elapsed > CONFIG.RollDuration then
				connection:Disconnect()
				if holdingRollKey then performRoll() else stopRolling() end
				return
			end
			local rayParams = RaycastParams.new()
			rayParams.FilterDescendantsInstances = {character}
			rayParams.FilterType = Enum.RaycastFilterType.Exclude
			local rayResult = workspace:Raycast(rootPart.Position, direction * 3, rayParams)
			if rayResult and rayResult.Instance.CanCollide then
				connection:Disconnect()
				stopRolling()
				return
			end
			local alpha = elapsed / CONFIG.RollDuration
			local nextPos = startPos:Lerp(targetPos, alpha)
			rootPart.CFrame = CFrame.new(nextPos, nextPos + direction)
		end)
	end

	local function startRoll()
		if rolling then return end
		rolling = true
		rollTrack:Play()
		performRoll()
	end

	-- Define Input Handler
	local function handleRollInput(actionName, inputState)
		if inputState == Enum.UserInputState.Begin then
			holdingRollKey = true
			startRoll()
		elseif inputState == Enum.UserInputState.End then
			holdingRollKey = false
		end
	end

	-- Function to bind controls based on current selection
	local function bindControls()
		ContextActionService:UnbindAction("RollAction")
		-- Bind R key always, add TouchButton only if mobile
		ContextActionService:BindAction("RollAction", handleRollInput, isMobileMode, Enum.KeyCode.R)
		if isMobileMode then
			ContextActionService:SetTitle("RollAction", "Roll")
			-- Moved to Left Side (0.15 = 15% from left edge)
			ContextActionService:SetPosition("RollAction", UDim2.new(0.15, 0, 0.6, 0))
		end
	end

	-- Watch for selection change if not yet made
	task.spawn(function()
		while not selectionMade do
			task.wait(0.5)
		end
		bindControls()
	end)
	
	if selectionMade then
		bindControls()
	end

	-- --- MOVEMENT LOOP ---
	local function getUserInputVector()
		local moveVector = Vector3.new(0, 0, 0)
		-- Explicit assignment used to prevent compiler errors
		if UserInputService:IsKeyDown(Enum.KeyCode.W) then moveVector = moveVector + Vector3.new(0,0,-1) end
		if UserInputService:IsKeyDown(Enum.KeyCode.S) then moveVector = moveVector + Vector3.new(0,0,1) end
		if UserInputService:IsKeyDown(Enum.KeyCode.A) then moveVector = moveVector + Vector3.new(-1,0,0) end
		if UserInputService:IsKeyDown(Enum.KeyCode.D) then moveVector = moveVector + Vector3.new(1,0,0) end
		
		local success, module = pcall(function() return require(player.PlayerScripts.PlayerModule) end)
		if success and module then
			local controls = module:GetControls()
			if controls then
				local touchMove = controls:GetMoveVector()
				if touchMove.Magnitude > 0 then moveVector = touchMove end
			end
		end
		return moveVector
	end

	RunService.RenderStepped:Connect(function(dt)
		local inputVector = getUserInputVector()
		local isInputting = inputVector.Magnitude > 0.1
		
		if isInputting then
			if rootPart.AssemblyLinearVelocity.Magnitude > 1 then
				lastMoveDirection = Vector3.new(rootPart.AssemblyLinearVelocity.X, 0, rootPart.AssemblyLinearVelocity.Z).Unit
			else
				lastMoveDirection = rootPart.CFrame.LookVector
			end
			currentSpeed = math.min(currentSpeed + (CONFIG.Acceleration * dt), CONFIG.MaxWalkSpeed)
			humanoid.WalkSpeed = currentSpeed
		else
			if currentSpeed > CONFIG.BaseWalkSpeed then
				currentSpeed = math.max(currentSpeed - (DECELERATION * dt), CONFIG.BaseWalkSpeed)
				humanoid.WalkSpeed = currentSpeed
				humanoid:Move(lastMoveDirection, false)
			else
				currentSpeed = CONFIG.BaseWalkSpeed
				humanoid.WalkSpeed = CONFIG.BaseWalkSpeed
			end
		end
		
		local velocityMag = Vector3.new(rootPart.AssemblyLinearVelocity.X, 0, rootPart.AssemblyLinearVelocity.Z).Magnitude
		local intensity = math.clamp((velocityMag - CONFIG.BaseWalkSpeed) / (CONFIG.MaxWalkSpeed - CONFIG.BaseWalkSpeed), 0, 1)
		
		local targetFOV = CONFIG.BaseFOV + (intensity * (CONFIG.MaxFOV - CONFIG.BaseFOV))
		camera.FieldOfView = camera.FieldOfView + (targetFOV - camera.FieldOfView) * math.clamp(dt * 5, 0, 1)

		if velocityMag > 1 then
			if not runTrack.IsPlaying then runTrack:Play() end
			runTrack:AdjustSpeed(0.5 + (intensity * 2)) 
		else
			if runTrack.IsPlaying then runTrack:Stop() end
		end
	end)
end

-- Init
createIntroGUI() 
if player.Character then
	onCharacterAdded(player.Character)
end

player.CharacterAdded:Connect(onCharacterAdded)

Features

  • r to roll
  • hold r to hold roll
  • custom jump animation
  • speedy run
  • and of course made in chatgpt cause im an idiot

More universal scripts