local j=require(script.Parent:WaitForChild("\066\097\115\101\067\104\097\114\097\099\116\101\114\067\111\110\116\114\111\108\108\101\114"))local Z=setmetatable({},j)Z.__index=Z function Z.new()local h=setmetatable(j.new(),Z)h.isFollowStick=false h.thumbstickFrame=nil h.moveTouchObject=nil h.onTouchMovedConn=nil h.onTouchEndedConn=nil h.screenPos=nil h.stickImage=nil h.thumbstickSize=nil return h end function Z.Enable(h,j,Z)if j==nil then return false end j=j and true or false if h.enabled==j then return true end h.moveVector=ZERO_VECTOR3 h.isJumping=false if j then if not h.thumbstickFrame then h:Create(Z)end h.thumbstickFrame.Visible=true else h.thumbstickFrame.Visible=false h:OnInputEnded()end h.enabled=j end function Z.OnInputEnded(j)j.thumbstickFrame.Position=j.screenPos j.stickImage.Position=UDim2.new(0,j.thumbstickFrame.Size.X.Offset/2-j.thumbstickSize/4,0,j.thumbstickFrame.Size.Y.Offset/2-j.thumbstickSize/4)j.moveVector=ZERO_VECTOR3 j.isJumping=false j.thumbstickFrame.Position=j.screenPos j.moveTouchObject=nil end function Z.Create(Z,j)if Z.thumbstickFrame then Z.thumbstickFrame:Destroy()Z.thumbstickFrame=nil if Z.onTouchMovedConn then Z.onTouchMovedConn:Disconnect()Z.onTouchMovedConn=nil end if Z.onTouchEndedConn then Z.onTouchEndedConn:Disconnect()Z.onTouchEndedConn=nil end end local h=math.min(j.AbsoluteSize.x,j.AbsoluteSize.y)local n=h<=500 Z.thumbstickSize=n and 70 or 120 Z.screenPos=n and UDim2.new(0,Z.thumbstickSize/2-10,1,-Z.thumbstickSize-20)or UDim2.new(0,Z.thumbstickSize/2,1,-Z.thumbstickSize*1.75)Z.thumbstickFrame=Instance.new("\070\114\097\109\101")Z.thumbstickFrame.Name="\084\104\117\109\098\115\116\105\099\107\070\114\097\109\101"Z.thumbstickFrame.Active=true Z.thumbstickFrame.Visible=false Z.thumbstickFrame.Size=UDim2.new(0,Z.thumbstickSize,0,Z.thumbstickSize)Z.thumbstickFrame.Position=Z.screenPos Z.thumbstickFrame.BackgroundTransparency=1 local W=Instance.new("\073\109\097\103\101\076\097\098\101\108")W.Name="\079\117\116\101\114\073\109\097\103\101"W.Image=TOUCH_CONTROL_SHEET W.ImageRectOffset=Vector2.new()W.ImageRectSize=Vector2.new(220,220)W.BackgroundTransparency=1 W.Size=UDim2.new(0,Z.thumbstickSize,0,Z.thumbstickSize)W.Position=UDim2.new(0,0,0,0)W.Parent=Z.thumbstickFrame Z.stickImage=Instance.new("\073\109\097\103\101\076\097\098\101\108")Z.stickImage.Name="\083\116\105\099\107\073\109\097\103\101"Z.stickImage.Image=TOUCH_CONTROL_SHEET Z.stickImage.ImageRectOffset=Vector2.new(220,0)Z.stickImage.ImageRectSize=Vector2.new(111,111)Z.stickImage.BackgroundTransparency=1 Z.stickImage.Size=UDim2.new(0,Z.thumbstickSize/2,0,Z.thumbstickSize/2)Z.stickImage.Position=UDim2.new(0,Z.thumbstickSize/2-Z.thumbstickSize/4,0,Z.thumbstickSize/2-Z.thumbstickSize/4)Z.stickImage.ZIndex=2 Z.stickImage.Parent=Z.thumbstickFrame local S=nil local f=.05 local function x(j)local h=j/(Z.thumbstickSize/2)local n=h.magnitude if n<f then h=Vector3.new()else h=h.unit*((n-f)/(1-f))h=Vector3.new(h.x,0,h.y)end Z.moveVector=h end local function a(j)local h=Vector2.new(j.x-S.x,j.y-S.y)local n=h.magnitude local W=Z.thumbstickFrame.AbsoluteSize.x/2 if Z.isFollowStick and n>W then local n=h.unit*W Z.thumbstickFrame.Position=UDim2.new(0,(j.x-Z.thumbstickFrame.AbsoluteSize.x/2)-n.x,0,(j.y-Z.thumbstickFrame.AbsoluteSize.y/2)-n.y)else n=math.min(n,W)h=h.unit*n end Z.stickImage.Position=UDim2.new(0,h.x+Z.stickImage.AbsoluteSize.x/2,0,h.y+Z.stickImage.AbsoluteSize.y/2)end Z.thumbstickFrame.InputBegan:Connect(function(j)if Z.moveTouchObject or j.UserInputType~=Enum.UserInputType.Touch or j.UserInputState~=Enum.UserInputState.Begin then return end Z.moveTouchObject=j Z.thumbstickFrame.Position=UDim2.new(0,j.Position.x-Z.thumbstickFrame.Size.X.Offset/2,0,j.Position.y-Z.thumbstickFrame.Size.Y.Offset/2)S=Vector2.new(Z.thumbstickFrame.AbsolutePosition.x+Z.thumbstickFrame.AbsoluteSize.x/2,Z.thumbstickFrame.AbsolutePosition.y+Z.thumbstickFrame.AbsoluteSize.y/2)local h=Vector2.new(j.Position.x-S.x,j.Position.y-S.y)end)Z.onTouchMovedConn=UserInputService.TouchMoved:Connect(function(j,h)if j==Z.moveTouchObject then S=Vector2.new(Z.thumbstickFrame.AbsolutePosition.x+Z.thumbstickFrame.AbsoluteSize.x/2,Z.thumbstickFrame.AbsolutePosition.y+Z.thumbstickFrame.AbsoluteSize.y/2)local h=Vector2.new(j.Position.x-S.x,j.Position.y-S.y)x(h)a(j.Position)end end)Z.onTouchEndedConn=UserInputService.TouchEnded:Connect(function(j,h)if j==Z.moveTouchObject then Z:OnInputEnded()end end)GuiService.MenuOpened:Connect(function()if Z.moveTouchObject then Z:OnInputEnded()end end)Z.thumbstickFrame.Parent=j end return Z
--[[ The Module ]]
--
local BaseCharacterController = require(script.Parent:WaitForChild("BaseCharacterController"))
local TouchThumbstick = setmetatable({}, BaseCharacterController)
TouchThumbstick.__index = TouchThumbstick
function TouchThumbstick.new()
	local self = setmetatable(BaseCharacterController.new(), TouchThumbstick)

	self.isFollowStick = false

	self.thumbstickFrame = nil
	self.moveTouchObject = nil
	self.onTouchMovedConn = nil
	self.onTouchEndedConn = nil
	self.screenPos = nil
	self.stickImage = nil
	self.thumbstickSize = nil -- Float

	return self
end
function TouchThumbstick:Enable(enable, uiParentFrame)
	if enable == nil then
		return false
	end -- If nil, return false (invalid argument)
	enable = enable and true or false -- Force anything non-nil to boolean before comparison
	if self.enabled == enable then
		return true
	end -- If no state change, return true indicating already in requested state

	self.moveVector = ZERO_VECTOR3
	self.isJumping = false

	if enable then
		-- Enable
		if not self.thumbstickFrame then
			self:Create(uiParentFrame)
		end
		self.thumbstickFrame.Visible = true
	else
		-- Disable
		self.thumbstickFrame.Visible = false
		self:OnInputEnded()
	end
	self.enabled = enable
end
function TouchThumbstick:OnInputEnded()
	self.thumbstickFrame.Position = self.screenPos
	self.stickImage.Position = UDim2.new(
		0,
		self.thumbstickFrame.Size.X.Offset / 2 - self.thumbstickSize / 4,
		0,
		self.thumbstickFrame.Size.Y.Offset / 2 - self.thumbstickSize / 4
	)

	self.moveVector = ZERO_VECTOR3
	self.isJumping = false
	self.thumbstickFrame.Position = self.screenPos
	self.moveTouchObject = nil
end
function TouchThumbstick:Create(parentFrame)
	if self.thumbstickFrame then
		self.thumbstickFrame:Destroy()
		self.thumbstickFrame = nil
		if self.onTouchMovedConn then
			self.onTouchMovedConn:Disconnect()
			self.onTouchMovedConn = nil
		end
		if self.onTouchEndedConn then
			self.onTouchEndedConn:Disconnect()
			self.onTouchEndedConn = nil
		end
	end

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

	self.thumbstickFrame = Instance.new("Frame")
	self.thumbstickFrame.Name = "ThumbstickFrame"
	self.thumbstickFrame.Active = true
	self.thumbstickFrame.Visible = false
	self.thumbstickFrame.Size = UDim2.new(0, self.thumbstickSize, 0, self.thumbstickSize)
	self.thumbstickFrame.Position = self.screenPos
	self.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, self.thumbstickSize, 0, self.thumbstickSize)
	outerImage.Position = UDim2.new(0, 0, 0, 0)
	outerImage.Parent = self.thumbstickFrame

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

	local centerPosition = nil
	local deadZone = 0.05

	local function DoMove(direction)
		local currentMoveVector = direction / (self.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

		self.moveVector = currentMoveVector
	end

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

	-- input connections
	self.thumbstickFrame.InputBegan:Connect(function(inputObject)
		--A touch that starts elsewhere on the screen will be sent to a frame's InputBegan event
		--if it moves over the frame. So we check that this is actually a new touch (inputObject.UserInputState ~= Enum.UserInputState.Begin)
		if
			self.moveTouchObject
			or inputObject.UserInputType ~= Enum.UserInputType.Touch
			or inputObject.UserInputState ~= Enum.UserInputState.Begin
		then
			return
		end

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

	self.onTouchMovedConn = UserInputService.TouchMoved:Connect(function(inputObject, isProcessed)
		if inputObject == self.moveTouchObject then
			centerPosition = Vector2.new(
				self.thumbstickFrame.AbsolutePosition.x + self.thumbstickFrame.AbsoluteSize.x / 2,
				self.thumbstickFrame.AbsolutePosition.y + self.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)

	self.onTouchEndedConn = UserInputService.TouchEnded:Connect(function(inputObject, isProcessed)
		if inputObject == self.moveTouchObject then
			self:OnInputEnded()
		end
	end)

	GuiService.MenuOpened:Connect(function()
		if self.moveTouchObject then
			self:OnInputEnded()
		end
	end)

	self.thumbstickFrame.Parent = parentFrame
end
return TouchThumbstick
