FULL 2008 TO 2014 MOUSE
Key RequiredUniversal

FULL 2008 TO 2014 MOUSE

Universal ScriptMOCCOHACMOCCOHAC 111 views 882 executesUpdated Jul 6, 2026
Unrated
00
Lua Script•432 lines (14512 chars)
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local CoreGui = game:GetService("CoreGui")
local GuiService = game:GetService("GuiService")
local Workspace = game:GetService("Workspace")

local LocalPlayer = Players.LocalPlayer
local PlayerGui = LocalPlayer:WaitForChild("PlayerGui", 5)

-- Clean up any existing custom cursors to avoid duplicates
if CoreGui:FindFirstChild("Cursor") then 
	CoreGui.Cursor:Destroy() 
end

-- State tracking
local isEscMenuOpen = false
local originalCursorImage = nil
local outOfRangeTexture = "rbxassetid://113797540507637"

-- Load and clone the authentic custom GUI cursor asset
local success, assets = pcall(function()
	return game:GetObjects("rbxassetid://17895536995")
end)

if success and assets and assets[1] then
	local eazywin = assets[1]:Clone()
	
	-- Clean up configuration and match requested specifications
	if eazywin:FindFirstChild("LocalScript") then
		eazywin.LocalScript:Destroy()
	end
	
	eazywin.DisplayOrder = 1999999999
	eazywin.IgnoreGuiInset = true
	eazywin.Y.Value = 6
	eazywin.Parent = CoreGui

	local imageLabel = eazywin:FindFirstChild("ImageLabel")
	local actionLabel = imageLabel and imageLabel:FindFirstChild("action")
	
	-- Save the original texture asset string so we can restore it dynamically
	if imageLabel then
		originalCursorImage = imageLabel.Image
	end
	
	-- Listen to core Esc Menu states to handle automatic hiding
	GuiService.MenuOpened:Connect(function()
		isEscMenuOpen = true
	end)

	GuiService.MenuClosed:Connect(function()
		isEscMenuOpen = false
	end)
	
	-- Helper function to check if the cursor is hovering over a clickable UI element
	local function isHoveringClickableUI(mousePos)
		if not PlayerGui then return false end
		local guiObjects = PlayerGui:GetGuiObjectsAtPosition(mousePos.X, mousePos.Y)
		for _, obj in ipairs(guiObjects) do
			if obj:IsA("GuiButton") or obj:IsA("TextButton") or obj:IsA("ImageButton") then
				return true
			end
		end
		return false
	end
	
	-- Frame-by-frame execution loop
	RunService.RenderStepped:Connect(function(step)
		if not eazywin or not eazywin.Parent then return end
		
		local mouse = LocalPlayer:GetMouse()
		local mousePos = Vector2.new(mouse.X, mouse.Y)
		local character = LocalPlayer.Character
		local rootPart = character and character:FindFirstChild("HumanoidRootPart")
		
		-- 1. Distance Calculation Logic
		local isOutOfRange = false
		if rootPart and mouse.Hit then
			local distance = (rootPart.Position - mouse.Hit.Position).Magnitude
			if distance > 60 then
				isOutOfRange = true
			end
		end
		
		-- Update the texture depending on range limits
		if imageLabel then
			if isOutOfRange and not isHoveringClickableUI(mousePos) and not isEscMenuOpen then
				imageLabel.Image = outOfRangeTexture
			else
				imageLabel.Image = originalCursorImage
			end
		end
		
		-- 2. 3D World Interaction: Hovering over a physical ClickDetector
		local isHoveringWorldClickable = false
		if mouse.Target and mouse.Target:FindFirstChildOfClass("ClickDetector") then
			isHoveringWorldClickable = true
		end
		
		-- 3. 2D Screen Interaction: Hovering over a Clickable UI Button
		local isHoveringUIButton = isHoveringClickableUI(mousePos)
		
		-- Visibility layout switches
		if isEscMenuOpen then
			UserInputService.MouseIconEnabled = true
			if imageLabel then imageLabel.Visible = false end
			if actionLabel then actionLabel.Visible = false end
			
		elseif isHoveringWorldClickable then
			UserInputService.MouseIconEnabled = true
			if imageLabel then imageLabel.Visible = false end
			
		elseif isHoveringUIButton then
			UserInputService.MouseIconEnabled = false
			if imageLabel then imageLabel.Visible = true end
			if actionLabel then actionLabel.Visible = true end
			
		else
			UserInputService.MouseIconEnabled = false
			if imageLabel then imageLabel.Visible = true end
			if actionLabel then actionLabel.Visible = false end
		end
		
		-- perfectly position the custom cursor (shifted down 26 pixels to aling)
		if imageLabel and imageLabel.Visible then
			local targetX = mouse.X - eazywin.X.Value
			local targetY = mouse.Y - eazywin.Y.Value + 26
			
			local tweenInfo = TweenInfo.new(step, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
			local goalProperties = {Position = UDim2.new(0, targetX, 0, targetY)}
			
			TweenService:Create(imageLabel, tweenInfo, goalProperties):Play()
		end
	end)
else
	warn("Failed to fetch custom cursor asset.")
end

-- old click to move, compatible with mobile! :D
--OLD ROBLOX CLICK TO MOVE

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local UserInputService = game:GetService("UserInputService")

local LocalPlayer = Players.LocalPlayer
local PlayerGui = LocalPlayer:WaitForChild("PlayerGui", 5)
local Mouse = LocalPlayer:GetMouse()
local Camera = Workspace.CurrentCamera

-- =========================================================
-- ATTEMPT TO WIPE ROBLOX DEFAULT CLICK-TO-MOVE SYSTEM(doesn't work)
-- =========================================================
local StarterPlayer = game:GetService("StarterPlayer")
local StarterPlayerScripts = StarterPlayer:WaitForChild("StarterPlayerScripts")

if not StarterPlayerScripts:FindFirstChild("PlayerModule") then
	local fakePlayerModule = Instance.new("Folder")
	fakePlayerModule.Name = "PlayerModule"
	
	local fakeControlModule = Instance.new("Folder")
	fakeControlModule.Name = "ControlModule"
	fakeControlModule.Parent = fakePlayerModule
	
	local fakeCTM = Instance.new("ModuleScript")
	fakeCTM.Name = "ClickToMoveController"
	fakeCTM.Source = "local m = {}; function m:Disconnect() end; return m;"
	fakeCTM.Parent = fakeControlModule
	
	fakePlayerModule.Parent = StarterPlayerScripts
end

pcall(function()
	LocalPlayer.DevComputerMovementMode = Enum.DevComputerMovementMode.UserChoice
	LocalPlayer.DevTouchMovementMode = Enum.DevTouchMovementMode.UserChoice
end)

local oldModel = Workspace:FindFirstChild("MouseFollowerDodecagon")
if oldModel then oldModel:Destroy() end
local oldClone = Workspace:FindFirstChild("DodecagonClone")
if oldClone then oldClone:Destroy() end

local isFollowerVisible = false
local currentClone = nil
local isPathfinding = false
local touchConnection = nil

local activeTouches = {}
local touchStartPositions = {}

local dodecagonModel = Instance.new("Model")
dodecagonModel.Name = "MouseFollowerDodecagon"
dodecagonModel.Parent = Workspace

local cylinderPart = Instance.new("Part")
cylinderPart.Name = "Hitbox"
cylinderPart.Size = Vector3.new(0.25, 2, 2) 
cylinderPart.Shape = Enum.PartType.Cylinder
cylinderPart.Color = Color3.fromRGB(0, 255, 0)
cylinderPart.Material = Enum.Material.SmoothPlastic
cylinderPart.CanCollide = false
cylinderPart.CanTouch = true
cylinderPart.CanQuery = true
cylinderPart.Anchored = true
cylinderPart.CFrame = CFrame.new(0, 0, 0) * CFrame.Angles(0, 0, math.rad(90))
cylinderPart.Parent = dodecagonModel
dodecagonModel.PrimaryPart = cylinderPart

local function isHoldingTool()
	local character = LocalPlayer.Character
	return character and character:FindFirstChildOfClass("Tool") ~= nil
end

local function isHoveringInteractivePart(target)
	if not target then return false end
	if target == cylinderPart or target:IsDescendantOf(dodecagonModel) or (currentClone and target:IsDescendantOf(currentClone)) then return false end
	if target:FindFirstChildOfClass("ClickDetector") or target.Parent:FindFirstChildOfClass("ClickDetector") then return true end
	if target:IsA("Seat") or target:IsA("VehicleSeat") then return true end
	if target:FindFirstChildOfClass("ProximityPrompt") or target.Parent:FindFirstChildOfClass("ProximityPrompt") then return true end
	return false
end

local function isHoveringUIAtPosition(screenPos)
	if not PlayerGui then return false end
	local guiObjects = PlayerGui:GetGuiObjectsAtPosition(screenPos.X, screenPos.Y)
	for _, obj in ipairs(guiObjects) do
		if obj:IsA("GuiButton") or obj:IsA("TextBox") or obj.Active then
			return true
		end
	end
	return false
end

local function removeClone()
	if touchConnection then
		touchConnection:Disconnect()
		touchConnection = nil
	end
	if currentClone then
		currentClone:Destroy()
		currentClone = nil
	end
	isPathfinding = false
end

-- Check if the camera is zoomed completely into the character's head
local function isFirstPerson()
	local character = LocalPlayer.Character
	local head = character and character:FindFirstChild("Head")
	if head and Camera then
		return (Camera.CFrame.Position - head.Position).Magnitude < 1.5
	end
	return false
end

-- Setup character listeners for seat transitions
local function setupCharacter(character)
	removeClone()
	local humanoid = character:WaitForChild("Humanoid", 5)
	local rootPart = character:WaitForChild("HumanoidRootPart", 5)
	
	if humanoid and rootPart then
		humanoid.Seated:Connect(function(isSitting, seat)
			if isSitting then
				removeClone()
				humanoid:MoveTo(rootPart.Position)
			end
		end)
	end
end

if LocalPlayer.Character then setupCharacter(LocalPlayer.Character) end
LocalPlayer.CharacterAdded:Connect(setupCharacter)

local function handlePlacement(targetWorldPos)
	local character = LocalPlayer.Character
	local humanoid = character and character:FindFirstChildOfClass("Humanoid")
	
	-- BLOCK PLACEMENT: Do not allow click destination drop if in first person, moving, or sitting
	if isFirstPerson() or (humanoid and (humanoid.MoveDirection.Magnitude > 0 or humanoid.Sit)) then 
		return 
	end

	removeClone()
	
	dodecagonModel.Archivable = true
	currentClone = dodecagonModel:Clone()
	currentClone.Name = "DodecagonClone"
	currentClone:PivotTo(CFrame.new(targetWorldPos) * CFrame.Angles(0, 0, math.rad(90)))
	
	local cloneHitbox = currentClone:FindFirstChild("Hitbox")
	if cloneHitbox then
		cloneHitbox.CanCollide = false
		touchConnection = cloneHitbox.Touched:Connect(function(hit)
			local character = LocalPlayer.Character
			if character and hit:IsDescendantOf(character) then
				removeClone()
			end
		end)
	end
	
	local cloneCylinder = currentClone:FindFirstChild("Hitbox")
	if cloneCylinder then
		cloneCylinder.LocalTransparencyModifier = 0
	end
	
	currentClone.Parent = Workspace
	isPathfinding = true
end

-- PC Click Input
Mouse.Button1Down:Connect(function()
	if not isFollowerVisible or not dodecagonModel.PrimaryPart then return end
	handlePlacement(dodecagonModel.PrimaryPart.Position)
end)

-- Mobile Touch Processing
UserInputService.TouchStarted:Connect(function(touch, gameProcessedEvent)
	if gameProcessedEvent then return end
	activeTouches[touch] = true
	touchStartPositions[touch] = touch.Position
end)

UserInputService.TouchEnded:Connect(function(touch, gameProcessedEvent)
	local startPos = touchStartPositions[touch]
	activeTouches[touch] = nil
	touchStartPositions[touch] = nil
	
	if gameProcessedEvent then return end
	
	local activeCount = 0
	for _ in pairs(activeTouches) do activeCount = activeCount + 1 end
	if activeCount > 0 then return end
	
	if startPos then
		local dragDistance = (touch.Position - startPos).Magnitude
		if dragDistance > 10 then return end
		
		local touchPos = Vector2.new(touch.Position.X, touch.Position.Y)
		if isHoveringUIAtPosition(touchPos) or isHoldingTool() then return end
		
		local unitRay = Camera:ScreenPointToRay(touchPos.X, touchPos.Y)
		local raycastParams = RaycastParams.new()
		raycastParams.FilterType = Enum.RaycastFilterType.Exclude
		raycastParams.FilterDescendantsInstances = {LocalPlayer.Character, dodecagonModel}
		
		local raycastResult = Workspace:Raycast(unitRay.Origin, unitRay.Direction * 500, raycastParams)
		
		if raycastResult and not isHoveringInteractivePart(raycastResult.Instance) then
			local character = LocalPlayer.Character
			local rootPart = character and character:FindFirstChild("HumanoidRootPart")
			
			if rootPart then
				local distanceFromPlayer = (rootPart.Position - raycastResult.Position).Magnitude
				if distanceFromPlayer <= 60 then
					handlePlacement(raycastResult.Position)
				end
			end
		end
	end
end)

-- Frame-by-frame execution loop
local connection
connection = RunService.RenderStepped:Connect(function()
	if not dodecagonModel or not dodecagonModel.Parent then
		connection:Disconnect()
		return
	end

	local character = LocalPlayer.Character
	local humanoid = character and character:FindFirstChildOfClass("Humanoid")
	local rootPart = character and character:FindFirstChild("HumanoidRootPart")

	-- Basic Movement and Cancel Checking (Active clones will continue moving)
	if isPathfinding and currentClone and humanoid and rootPart then
		local horizontalMove = Vector3.new(humanoid.MoveDirection.X, 0, humanoid.MoveDirection.Z)
		
		if horizontalMove.Magnitude > 0 then
			removeClone()
		else
			local clonePos = currentClone.PrimaryPart.Position
			humanoid:MoveTo(clonePos)
			
			if (rootPart.Position - clonePos).Magnitude <= 3 then
				removeClone()
			end
		end
	end

	-- Check if a mouse pointer is being used
	local hasMouse = UserInputService.MouseEnabled
	local shouldShow = false
	
	-- BLOCK MAIN CYLINDER VISIBILITY: Hide if player is moving, sitting, or in first person mode
	if hasMouse and humanoid and (humanoid.MoveDirection.Magnitude == 0 and not humanoid.Sit) and not isFirstPerson() then
		local unitRay = Camera:ScreenPointToRay(Mouse.X, Mouse.Y)
		local raycastParams = RaycastParams.new()
		raycastParams.FilterType = Enum.RaycastFilterType.Exclude
		local ignoreList = {LocalPlayer.Character, dodecagonModel}
		if currentClone then table.insert(ignoreList, currentClone) end
		raycastParams.FilterDescendantsInstances = ignoreList
		
		local raycastResult = Workspace:Raycast(unitRay.Origin, unitRay.Direction * 500, raycastParams)
		shouldShow = true
		
		if isHoldingTool() or isHoveringUIAtPosition(Vector2.new(Mouse.X, Mouse.Y)) then
			shouldShow = false
		end
		
		if raycastResult and shouldShow then
			if rootPart then
				local distanceFromPlayer = (rootPart.Position - raycastResult.Position).Magnitude
				if distanceFromPlayer > 60 or isHoveringInteractivePart(raycastResult.Instance) then
					shouldShow = false
				else
					dodecagonModel:PivotTo(CFrame.new(raycastResult.Position) * CFrame.Angles(0, 0, math.rad(90)))
				end
			else
				shouldShow = false
			end
		else
			shouldShow = false
		end
	end
	
	isFollowerVisible = shouldShow
	cylinderPart.LocalTransparencyModifier = (hasMouse and shouldShow) and 0 or 1
end)

Features & Information

this script has all the machanics the roblox mouse cursor had beetween 2008 and 2014, click to move mechanic included, this script also supports mobile, where the mouse won't show and the click to move mechanic only works with a one click where there are no uis and the player is standing still, fully working on all devices! :P

Community Comments (0)

No comments yet for this script.

More Scripts for Universal Scripts