function Thumbstick.Enable(w)ThumbstickFrame.Visible=true end function Thumbstick.Disable(w)ThumbstickFrame.Visible=false OnTouchEnded()end function Thumbstick.Create(n,w)if ThumbstickFrame then ThumbstickFrame:Destroy()ThumbstickFrame=nil if OnTouchMovedCn then OnTouchMovedCn:disconnect()OnTouchMovedCn=nil end if OnTouchEndedCn then OnTouchEndedCn:disconnect()OnTouchEndedCn=nil end end local a=w.AbsoluteSize.y<=500 local g=a and 70 or 120 local Q=a and UDim2.new(0,g/2-10,1,-g-20)or UDim2.new(0,g/2,1,-g*1.75)ThumbstickFrame=Instance.new("\070\114\097\109\101")ThumbstickFrame.Name="\084\104\117\109\098\115\116\105\099\107\070\114\097\109\101"ThumbstickFrame.Active=true ThumbstickFrame.Visible=false ThumbstickFrame.Size=UDim2.new(0,g,0,g)ThumbstickFrame.Position=Q ThumbstickFrame.BackgroundTransparency=1 local I=Instance.new("\073\109\097\103\101\076\097\098\101\108")I.Name="\079\117\116\101\114\073\109\097\103\101"I.Image=TOUCH_CONTROL_SHEET I.ImageRectOffset=Vector2.new()I.ImageRectSize=Vector2.new(220,220)I.BackgroundTransparency=1 I.Size=UDim2.new(0,g,0,g)I.Position=UDim2.new(0,0,0,0)I.Parent=ThumbstickFrame StickImage=Instance.new("\073\109\097\103\101\076\097\098\101\108")StickImage.Name="\083\116\105\099\107\073\109\097\103\101"StickImage.Image=TOUCH_CONTROL_SHEET StickImage.ImageRectOffset=Vector2.new(220,0)StickImage.ImageRectSize=Vector2.new(111,111)StickImage.BackgroundTransparency=1 StickImage.Size=UDim2.new(0,g/2,0,g/2)StickImage.Position=UDim2.new(0,g/2-g/4,0,g/2-g/4)StickImage.ZIndex=2 StickImage.Parent=ThumbstickFrame local C=nil local W=.05 local function P(w)MasterControl:AddToPlayerMovement(-currentMoveVector)currentMoveVector=w/(g/2)local n=currentMoveVector.magnitude if n<W then currentMoveVector=Vector3.new()else currentMoveVector=currentMoveVector.unit*((n-W)/(1-W))currentMoveVector=Vector3.new(currentMoveVector.x,0,currentMoveVector.y)end MasterControl:AddToPlayerMovement(currentMoveVector)end local function V(w)local n=Vector2.new(w.x-C.x,w.y-C.y)local a=n.magnitude local g=ThumbstickFrame.AbsoluteSize.x/2 if IsFollowStick and a>g then local a=n.unit*g ThumbstickFrame.Position=UDim2.new(0,(w.x-ThumbstickFrame.AbsoluteSize.x/2)-a.x,0,(w.y-ThumbstickFrame.AbsoluteSize.y/2)-a.y)else a=math.min(a,g)n=n.unit*a end StickImage.Position=UDim2.new(0,n.x+StickImage.AbsoluteSize.x/2,0,n.y+StickImage.AbsoluteSize.y/2)end ThumbstickFrame.InputBegan:connect(function(w)if MoveTouchObject or w.UserInputType~=Enum.UserInputType.Touch then return end MoveTouchObject=w ThumbstickFrame.Position=UDim2.new(0,w.Position.x-ThumbstickFrame.Size.X.Offset/2,0,w.Position.y-ThumbstickFrame.Size.Y.Offset/2)C=Vector2.new(ThumbstickFrame.AbsolutePosition.x+ThumbstickFrame.AbsoluteSize.x/2,ThumbstickFrame.AbsolutePosition.y+ThumbstickFrame.AbsoluteSize.y/2)local n=Vector2.new(w.Position.x-C.x,w.Position.y-C.y)V(w.Position)end)OnTouchMovedCn=UserInputService.TouchMoved:connect(function(w,n)if w==MoveTouchObject then C=Vector2.new(ThumbstickFrame.AbsolutePosition.x+ThumbstickFrame.AbsoluteSize.x/2,ThumbstickFrame.AbsolutePosition.y+ThumbstickFrame.AbsoluteSize.y/2)local n=Vector2.new(w.Position.x-C.x,w.Position.y-C.y)P(n)V(w.Position)end end)OnTouchEnded=function()ThumbstickFrame.Position=Q StickImage.Position=UDim2.new(0,ThumbstickFrame.Size.X.Offset/2-g/4,0,ThumbstickFrame.Size.Y.Offset/2-g/4)MoveTouchObject=nil MasterControl:AddToPlayerMovement(-currentMoveVector)currentMoveVector=Vector3.new(0,0,0)end OnTouchEndedCn=UserInputService.TouchEnded:connect(function(w,n)if w==MoveTouchObject then OnTouchEnded()end end)ThumbstickFrame.Parent=w end return Thumbstick
--[[ Public API ]]
--
function Thumbstick:Enable()
	ThumbstickFrame.Visible = true
end

function Thumbstick:Disable()
	ThumbstickFrame.Visible = false
	OnTouchEnded()
end

function Thumbstick:Create(parentFrame)
	if ThumbstickFrame then
		ThumbstickFrame:Destroy()
		ThumbstickFrame = nil
		if OnTouchMovedCn then
			OnTouchMovedCn:disconnect()
			OnTouchMovedCn = nil
		end
		if OnTouchEndedCn then
			OnTouchEndedCn:disconnect()
			OnTouchEndedCn = nil
		end
	end

	local isSmallScreen = parentFrame.AbsoluteSize.y <= 500
	local thumbstickSize = isSmallScreen and 70 or 120
	local position = isSmallScreen and UDim2.new(0, (thumbstickSize / 2) - 10, 1, -thumbstickSize - 20)
		or UDim2.new(0, thumbstickSize / 2, 1, -thumbstickSize * 1.75)

	ThumbstickFrame = Instance.new("Frame")
	ThumbstickFrame.Name = "ThumbstickFrame"
	ThumbstickFrame.Active = true
	ThumbstickFrame.Visible = false
	ThumbstickFrame.Size = UDim2.new(0, thumbstickSize, 0, thumbstickSize)
	ThumbstickFrame.Position = position
	ThumbstickFrame.BackgroundTransparency = 1

	local outerImage = Instance.new("ImageLabel")
	outerImage.Name = "OuterImage"
	outerImage.Image = TOUCH_CONTROL_SHEET
	outerImage.ImageRectOffset = Vector2.new()
	outerImage.ImageRectSize = Vector2.new(220, 220)
	outerImage.BackgroundTransparency = 1
	outerImage.Size = UDim2.new(0, thumbstickSize, 0, thumbstickSize)
	outerImage.Position = UDim2.new(0, 0, 0, 0)
	outerImage.Parent = ThumbstickFrame

	StickImage = Instance.new("ImageLabel")
	StickImage.Name = "StickImage"
	StickImage.Image = TOUCH_CONTROL_SHEET
	StickImage.ImageRectOffset = Vector2.new(220, 0)
	StickImage.ImageRectSize = Vector2.new(111, 111)
	StickImage.BackgroundTransparency = 1
	StickImage.Size = UDim2.new(0, thumbstickSize / 2, 0, thumbstickSize / 2)
	StickImage.Position =
		UDim2.new(0, thumbstickSize / 2 - thumbstickSize / 4, 0, thumbstickSize / 2 - thumbstickSize / 4)
	StickImage.ZIndex = 2
	StickImage.Parent = ThumbstickFrame

	local centerPosition = nil
	local deadZone = 0.05
	local function doMove(direction)
		MasterControl:AddToPlayerMovement(-currentMoveVector)

		currentMoveVector = direction / (thumbstickSize / 2)

		-- Scaled Radial Dead Zone
		local inputAxisMagnitude = currentMoveVector.magnitude
		if inputAxisMagnitude < deadZone then
			currentMoveVector = Vector3.new()
		else
			currentMoveVector = currentMoveVector.unit * ((inputAxisMagnitude - deadZone) / (1 - deadZone))
			-- NOTE: Making currentMoveVector a unit vector will cause the player to instantly go max speed
			-- must check for zero length vector is using unit
			currentMoveVector = Vector3.new(currentMoveVector.x, 0, currentMoveVector.y)
		end

		MasterControl:AddToPlayerMovement(currentMoveVector)
	end

	local function moveStick(pos)
		local relativePosition = Vector2.new(pos.x - centerPosition.x, pos.y - centerPosition.y)
		local length = relativePosition.magnitude
		local maxLength = ThumbstickFrame.AbsoluteSize.x / 2
		if IsFollowStick and length > maxLength then
			local offset = relativePosition.unit * maxLength
			ThumbstickFrame.Position = UDim2.new(
				0,
				pos.x - ThumbstickFrame.AbsoluteSize.x / 2 - offset.x,
				0,
				pos.y - ThumbstickFrame.AbsoluteSize.y / 2 - offset.y
			)
		else
			length = math.min(length, maxLength)
			relativePosition = relativePosition.unit * length
		end
		StickImage.Position = UDim2.new(
			0,
			relativePosition.x + StickImage.AbsoluteSize.x / 2,
			0,
			relativePosition.y + StickImage.AbsoluteSize.y / 2
		)
	end

	-- input connections
	ThumbstickFrame.InputBegan:connect(function(inputObject)
		if MoveTouchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch then
			return
		end

		MoveTouchObject = inputObject
		ThumbstickFrame.Position = UDim2.new(
			0,
			inputObject.Position.x - ThumbstickFrame.Size.X.Offset / 2,
			0,
			inputObject.Position.y - ThumbstickFrame.Size.Y.Offset / 2
		)
		centerPosition = Vector2.new(
			ThumbstickFrame.AbsolutePosition.x + ThumbstickFrame.AbsoluteSize.x / 2,
			ThumbstickFrame.AbsolutePosition.y + ThumbstickFrame.AbsoluteSize.y / 2
		)
		local direction =
			Vector2.new(inputObject.Position.x - centerPosition.x, inputObject.Position.y - centerPosition.y)
		moveStick(inputObject.Position)
	end)

	OnTouchMovedCn = UserInputService.TouchMoved:connect(function(inputObject, isProcessed)
		if inputObject == MoveTouchObject then
			centerPosition = Vector2.new(
				ThumbstickFrame.AbsolutePosition.x + ThumbstickFrame.AbsoluteSize.x / 2,
				ThumbstickFrame.AbsolutePosition.y + ThumbstickFrame.AbsoluteSize.y / 2
			)
			local direction =
				Vector2.new(inputObject.Position.x - centerPosition.x, inputObject.Position.y - centerPosition.y)
			doMove(direction)
			moveStick(inputObject.Position)
		end
	end)

	OnTouchEnded = function()
		ThumbstickFrame.Position = position
		StickImage.Position = UDim2.new(
			0,
			ThumbstickFrame.Size.X.Offset / 2 - thumbstickSize / 4,
			0,
			ThumbstickFrame.Size.Y.Offset / 2 - thumbstickSize / 4
		)
		MoveTouchObject = nil

		MasterControl:AddToPlayerMovement(-currentMoveVector)
		currentMoveVector = Vector3.new(0, 0, 0)
	end

	OnTouchEndedCn = UserInputService.TouchEnded:connect(function(inputObject, isProcessed)
		if inputObject == MoveTouchObject then
			OnTouchEnded()
		end
	end)

	ThumbstickFrame.Parent = parentFrame
end

return Thumbstick
