local Z={}local e=require(script.Parent.Parent:WaitForChild("\067\111\110\102\105\103\117\114\097\116\105\111\110"))local t=e.MoveControllerCreator.MAGNITUDE_THRESHOLD local U={None=Enum.KeyCode.Thumbstick1,[Enum.VRTouchpad.Left]=Enum.KeyCode.Thumbstick1;[Enum.VRTouchpad.Right]=Enum.KeyCode.Thumbstick2}local J=game:GetService("\086\082\083\101\114\118\105\099\101")local f=game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101")local B=game:GetService("\082\117\110\083\101\114\118\105\099\101")local D,i,N=math.sin,math.cos,math.atan2 local h local s,E=0,0 local A,b,u,G=0,0,0,0 local L=0 local p=false B.RenderStepped:Connect(function(Z)if h and u>0 then local e=L+G local t=(h.Humanoid.WalkSpeed*Z)*u local U,J=D(e)*t,-i(e)*t s,E=s+U,E+J h:SetCharacterXZOffset(s,E)end end)function Z.CreateMoveController(B,Z,e)h=e local D={}local i=e.CharacterModel if Z then J:SetTouchpadMode(Z,Enum.VRTouchpadMode.Touch)else Z="\078\111\110\101"end local C=U[Z]local S,R=Enum.VRTouchpad.Left,Enum.VRTouchpad.Right local o,M=Enum.UserCFrame.LeftHand,Enum.UserCFrame.RightHand local function n()if Z=="\078\111\110\101"then if C==U[S]then return not J:GetUserCFrameEnabled(o)else return not J:GetUserCFrameEnabled(M)end else return J:GetUserCFrameEnabled(Z==S and o or M)end end local k=0 function D.UpdateController(e,Z)k=N(Z.lookVector.X,-Z.lookVector.Z)end local function w()if p==false then p=true e:SetYPlaneLockWorldOffset(true)end end local function I()A,b=0,0 u=0 if(s~=0 or E~=0)and p then p=false e:SetYPlaneLockWorldOffset(false)local Z=e:GetWorldOffset()e:SetCharacterXZOffset(0,0)e:SetWorldXZOffset(s+Z.X,E+Z.Z)s,E=0,0 end end local T=f.InputEnded:Connect(function(Z)local e=Z.KeyCode if e==C and n()then I()end end)local y=f.InputChanged:Connect(function(Z)if Z.KeyCode==C and n()then local e,U=Z.Position.X,Z.Position.Y local J=(e^2+U^2)^.5 local f=N(e,U)G=f L=k if J>t then w()A,b=e,U u=J else I()end end end)function D.Disconnect(Z)T:Disconnect()y:Disconnect()end return D end return Z
--[[




MoveControllerCreator:CreateMoveController(VRTouchpad,CharacterClass)
	Creates an Move controller given a VRTouchpad and CharacterClass
	RETURNS: MoveControllerClass

CLASS MoveControllerClass
	MoveControllerClass:UpdateController(ControllerCF)
		Updates controller with given Controller CFrame
	MoveControllerClass:Disconnect()
		Disconnects all events
	
--]]

local MoveControllerCreator = {}

local Configuration = require(script.Parent.Parent:WaitForChild("Configuration"))
local MAGNITUDE_THRESHOLD = Configuration.MoveControllerCreator.MAGNITUDE_THRESHOLD

local TouchpadThumbstickToInput = {
	["None"] = Enum.KeyCode.Thumbstick1,
	[Enum.VRTouchpad.Left] = Enum.KeyCode.Thumbstick1,
	[Enum.VRTouchpad.Right] = Enum.KeyCode.Thumbstick2,
}

local VRService = game:GetService("VRService")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")

local sin, cos, atan2 = math.sin, math.cos, math.atan2

local GlobalCharacterClass
local CurCharX, CurCharZ = 0, 0
local ControllerX, ControllerY, ControllerMag, ControllerAngle = 0, 0, 0, 0
local CurrentControllerLookAngle = 0
local CameraYLocked = false
RunService.RenderStepped:Connect(function(DeltaTime)
	if GlobalCharacterClass and ControllerMag > 0 then
		local FinalAngle = CurrentControllerLookAngle + ControllerAngle
		local TotalWalkspeed = GlobalCharacterClass.Humanoid.WalkSpeed * DeltaTime * ControllerMag
		local MoveX, MoveZ = sin(FinalAngle) * TotalWalkspeed, -cos(FinalAngle) * TotalWalkspeed

		CurCharX, CurCharZ = CurCharX + MoveX, CurCharZ + MoveZ
		GlobalCharacterClass:SetCharacterXZOffset(CurCharX, CurCharZ)
	end
end)

function MoveControllerCreator:CreateMoveController(VRTouchpad, CharacterClass)
	GlobalCharacterClass = CharacterClass
	local MoveControllerClass = {}
	local CharacterModel = CharacterClass.CharacterModel

	if VRTouchpad then
		VRService:SetTouchpadMode(VRTouchpad, Enum.VRTouchpadMode.Touch)
	else
		VRTouchpad = "None"
	end
	local ThumbstickInput = TouchpadThumbstickToInput[VRTouchpad]

	local Left, Right = Enum.VRTouchpad.Left, Enum.VRTouchpad.Right
	local LeftHand, RightHand = Enum.UserCFrame.LeftHand, Enum.UserCFrame.RightHand
	local function ValidInput()
		if VRTouchpad == "None" then
			if ThumbstickInput == TouchpadThumbstickToInput[Left] then
				return not VRService:GetUserCFrameEnabled(LeftHand)
			else
				return not VRService:GetUserCFrameEnabled(RightHand)
			end
		else
			return VRService:GetUserCFrameEnabled((VRTouchpad == Left and LeftHand or RightHand))
		end
	end

	local ControllerLookAngle = 0
	function MoveControllerClass:UpdateController(ControllerCF)
		ControllerLookAngle = atan2(ControllerCF.lookVector.X, -ControllerCF.lookVector.Z)
	end

	local function StartInput()
		if CameraYLocked == false then
			CameraYLocked = true
			CharacterClass:SetYPlaneLockWorldOffset(true)
		end
	end

	local function EndInput()
		ControllerX, ControllerY = 0, 0
		ControllerMag = 0
		if (CurCharX ~= 0 or CurCharZ ~= 0) and CameraYLocked then
			CameraYLocked = false
			CharacterClass:SetYPlaneLockWorldOffset(false)
			local CurOffset = CharacterClass:GetWorldOffset()
			CharacterClass:SetCharacterXZOffset(0, 0)
			CharacterClass:SetWorldXZOffset(CurCharX + CurOffset.X, CurCharZ + CurOffset.Z)
			CurCharX, CurCharZ = 0, 0
		end
	end

	local UserInputEvent1 = UserInputService.InputEnded:Connect(function(Input)
		local KeyCode = Input.KeyCode
		if KeyCode == ThumbstickInput and ValidInput() then
			EndInput()
		end
	end)

	local UserInputEvent2 = UserInputService.InputChanged:Connect(function(Input)
		if Input.KeyCode == ThumbstickInput and ValidInput() then
			local X, Y = Input.Position.X, Input.Position.Y
			local Magnitude = ((X ^ 2) + (Y ^ 2)) ^ 0.5
			local Angle = atan2(X, Y)

			ControllerAngle = Angle
			CurrentControllerLookAngle = ControllerLookAngle
			if Magnitude > MAGNITUDE_THRESHOLD then
				StartInput()
				ControllerX, ControllerY = X, Y
				ControllerMag = Magnitude
			else
				EndInput()
			end
		end
	end)

	function MoveControllerClass:Disconnect()
		UserInputEvent1:Disconnect()
		UserInputEvent2:Disconnect()
	end

	return MoveControllerClass
end

return MoveControllerCreator
