function ControlModule.SelectTouchModule(s)if not UserInputService.TouchEnabled then return nil,false end local W local c=Players.LocalPlayer.DevTouchMovementMode if c==Enum.DevTouchMovementMode.UserChoice then W=movementEnumToModuleMap[UserGameSettings.TouchMovementMode]elseif c==Enum.DevTouchMovementMode.Scriptable then return nil,true else W=movementEnumToModuleMap[c]end return W,true end local function s(s,W)local c=Workspace.CurrentCamera if not c then return W end if s:GetState()==Enum.HumanoidStateType.Swimming then return c.CFrame:VectorToWorldSpace(W)end local E,F local n,e,o,u,w,G,d,P,a,z,U,L=c.CFrame:GetComponents()if a<1 and a>-1 then E=L F=G else E=u F=-w*math.sign(a)end local m=math.sqrt(E*E+F*F)return Vector3.new((E*W.x+F*W.z)/m,0,(E*W.z-F*W.x)/m)end function ControlModule.OnRenderStepped(c,W)if c.activeController and(c.activeController.enabled and c.humanoid)then c.activeController:OnRenderStepped(W)local E=c.activeController:GetMoveVector()local F=c.activeController:IsMoveVectorCameraRelative()local n=c:GetClickToMoveController()if c.activeController~=n then if E.magnitude>0 then n:CleanupPath()else n:OnRenderStepped(W)E=n:GetMoveVector()F=n:IsMoveVectorCameraRelative()end end local e=false if c.vehicleController then E,e=c.vehicleController:Update(E,F,c.activeControlModule==Gamepad)end if F then E=s(c.humanoid,E)end c.moveFunction(Players.LocalPlayer,E,false)c.humanoid.Jump=c.activeController:GetIsJumping()or c.touchJumpController and c.touchJumpController:GetIsJumping()end end function ControlModule.OnHumanoidSeated(c,s,W)if s then if W and W:IsA("\086\101\104\105\099\108\101\083\101\097\116")then if not c.vehicleController then c.vehicleController=c.vehicleController.new(CONTROL_ACTION_PRIORITY)end c.vehicleController:Enable(true,W)end else if c.vehicleController then c.vehicleController:Enable(false,W)end end end function ControlModule.OnCharacterAdded(W,s)W.humanoid=s:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")while not W.humanoid do s.ChildAdded:wait()W.humanoid=s:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")end if W.touchGui then W.touchGui.Enabled=true end if W.humanoidSeatedConn then W.humanoidSeatedConn:Disconnect()W.humanoidSeatedConn=nil end W.humanoidSeatedConn=W.humanoid.Seated:Connect(function(s,c)W:OnHumanoidSeated(s,c)end)end function ControlModule.OnCharacterRemoving(W,s)W.humanoid=nil if W.touchGui then W.touchGui.Enabled=false end end

function ControlModule:SelectTouchModule()
	if not UserInputService.TouchEnabled then
		return nil, false
	end
	local touchModule
	local DevMovementMode = Players.LocalPlayer.DevTouchMovementMode
	if DevMovementMode == Enum.DevTouchMovementMode.UserChoice then
		touchModule = movementEnumToModuleMap[UserGameSettings.TouchMovementMode]
	elseif DevMovementMode == Enum.DevTouchMovementMode.Scriptable then
		return nil, true
	else
		touchModule = movementEnumToModuleMap[DevMovementMode]
	end
	return touchModule, true
end

local function calculateRawMoveVector(humanoid, cameraRelativeMoveVector)
	local camera = Workspace.CurrentCamera
	if not camera then
		return cameraRelativeMoveVector
	end

	if humanoid:GetState() == Enum.HumanoidStateType.Swimming then
		return camera.CFrame:VectorToWorldSpace(cameraRelativeMoveVector)
	end

	local c, s
	local _, _, _, R00, R01, R02, _, _, R12, _, _, R22 = camera.CFrame:GetComponents()
	if R12 < 1 and R12 > -1 then
		-- X and Z components from back vector.
		c = R22
		s = R02
	else
		-- In this case the camera is looking straight up or straight down.
		-- Use X components from right and up vectors.
		c = R00
		s = -R01*math.sign(R12)
	end
	local norm = math.sqrt(c*c + s*s)
	return Vector3.new(
		(c*cameraRelativeMoveVector.x + s*cameraRelativeMoveVector.z)/norm,
		0,
		(c*cameraRelativeMoveVector.z - s*cameraRelativeMoveVector.x)/norm
	)
end

function ControlModule:OnRenderStepped(dt)
	if self.activeController and self.activeController.enabled and self.humanoid then
		-- Give the controller a chance to adjust its state
		self.activeController:OnRenderStepped(dt)

		-- Now retrieve info from the controller
		local moveVector = self.activeController:GetMoveVector()
		local cameraRelative = self.activeController:IsMoveVectorCameraRelative()

		local clickToMoveController = self:GetClickToMoveController()
		if self.activeController ~= clickToMoveController then
			if moveVector.magnitude > 0 then
				-- Clean up any developer started MoveTo path
				clickToMoveController:CleanupPath()
			else
				-- Get move vector for developer started MoveTo
				clickToMoveController:OnRenderStepped(dt)
				moveVector = clickToMoveController:GetMoveVector()
				cameraRelative = clickToMoveController:IsMoveVectorCameraRelative()
			end
		end

		-- Are we driving a vehicle ?
		local vehicleConsumedInput = false
		if self.vehicleController then
			moveVector, vehicleConsumedInput = self.vehicleController:Update(moveVector, cameraRelative, self.activeControlModule==Gamepad)
		end

		-- If not, move the player
		-- Verification of vehicleConsumedInput is commented out to preserve legacy behavior,
		-- in case some game relies on Humanoid.MoveDirection still being set while in a VehicleSeat
		--if not vehicleConsumedInput then
			if cameraRelative then
				moveVector = calculateRawMoveVector(self.humanoid, moveVector)
			end
			self.moveFunction(Players.LocalPlayer, moveVector, false)
		--end

		-- And make them jump if needed
		self.humanoid.Jump = self.activeController:GetIsJumping() or (self.touchJumpController and self.touchJumpController:GetIsJumping())
	end
end

function ControlModule:OnHumanoidSeated(active, currentSeatPart)
	if active then
		if currentSeatPart and currentSeatPart:IsA("VehicleSeat") then
			if not self.vehicleController then
				self.vehicleController = self.vehicleController.new(CONTROL_ACTION_PRIORITY)
			end
			self.vehicleController:Enable(true, currentSeatPart)
		end
	else
		if self.vehicleController then
			self.vehicleController:Enable(false, currentSeatPart)
		end
	end
end

function ControlModule:OnCharacterAdded(char)
	self.humanoid = char:FindFirstChildOfClass("Humanoid")
	while not self.humanoid do
		char.ChildAdded:wait()
		self.humanoid = char:FindFirstChildOfClass("Humanoid")
	end

	if self.touchGui then
		self.touchGui.Enabled = true
	end

	if self.humanoidSeatedConn then
		self.humanoidSeatedConn:Disconnect()
		self.humanoidSeatedConn = nil
	end
	self.humanoidSeatedConn = self.humanoid.Seated:Connect(function(active, currentSeatPart)
		self:OnHumanoidSeated(active, currentSeatPart)
	end)
end

function ControlModule:OnCharacterRemoving(char)
	self.humanoid = nil

	if self.touchGui then
		self.touchGui.Enabled = false
	end
end
