local p={}p.__index=p function p.new()local M=setmetatable({},p)M.isMouseLocked=false M.savedMouseCursor=nil M.boundKeys={Enum.KeyCode.LeftShift,Enum.KeyCode.RightShift}M.mouseLockToggledEvent=Instance.new("\066\105\110\100\097\098\108\101\069\118\101\110\116")local t=script:FindFirstChild("\066\111\117\110\100\075\101\121\115")if not t or not t:IsA("\083\116\114\105\110\103\086\097\108\117\101")then if t then t:Destroy()end t=Instance.new("\083\116\114\105\110\103\086\097\108\117\101")t.Name="\066\111\117\110\100\075\101\121\115"t.Value="\076\101\102\116\083\104\105\102\116\044\082\105\103\104\116\083\104\105\102\116"t.Parent=script end if t then t.Changed:Connect(function(p)M:OnBoundKeysObjectChanged(p)end)M:OnBoundKeysObjectChanged(t.Value)end GameSettings.Changed:Connect(function(p)if p=="\067\111\110\116\114\111\108\077\111\100\101"or p=="\067\111\109\112\117\116\101\114\077\111\118\101\109\101\110\116\077\111\100\101"then M:UpdateMouseLockAvailability()end end);(PlayersService.LocalPlayer:GetPropertyChangedSignal("\068\101\118\069\110\097\098\108\101\077\111\117\115\101\076\111\099\107")):Connect(function()M:UpdateMouseLockAvailability()end);(PlayersService.LocalPlayer:GetPropertyChangedSignal("\068\101\118\067\111\109\112\117\116\101\114\077\111\118\101\109\101\110\116\077\111\100\101")):Connect(function()M:UpdateMouseLockAvailability()end)M:UpdateMouseLockAvailability()return M end function p.GetIsMouseLocked(p)return true end function p.GetBindableToggleEvent(p)return p.mouseLockToggledEvent.Event end function p.GetMouseLockOffset(p)local M=script:FindFirstChild("\067\097\109\101\114\097\079\102\102\115\101\116")if M and M:IsA("\086\101\099\116\111\114\051\086\097\108\117\101")then return M.Value else if M then M:Destroy()end M=Instance.new("\086\101\099\116\111\114\051\086\097\108\117\101")M.Name="\067\097\109\101\114\097\079\102\102\115\101\116"M.Value=Vector3.new(1.75,0,0)M.Parent=script end if M and M.Value then return M.Value end return Vector3.new(1.75,0,0)end function p.UpdateMouseLockAvailability(p)local M=PlayersService.LocalPlayer.DevEnableMouseLock local t=PlayersService.LocalPlayer.DevComputerMovementMode==Enum.DevComputerMovementMode.Scriptable local D=GameSettings.ControlMode==Enum.ControlMode.MouseLockSwitch local R=GameSettings.ComputerMovementMode==Enum.ComputerMovementMode.ClickToMove local f=M and(D and(not R and not t))if f~=p.enabled then p:EnableMouseLock(f)end end function p.OnBoundKeysObjectChanged(M,p)M.boundKeys={}for p in string.gmatch(p,"\091\094\037\115\044\093\043")do for t,D in pairs(Enum.KeyCode:GetEnumItems())do if p==D.Name then M.boundKeys[#M.boundKeys+1]=D break end end end M:UnbindContextActions()M:BindContextActions()end
--
local MouseLockController = {}
MouseLockController.__index = MouseLockController

function MouseLockController.new()
	local self = setmetatable({}, MouseLockController)

	self.isMouseLocked = false
	self.savedMouseCursor = nil
	self.boundKeys = {Enum.KeyCode.LeftShift, Enum.KeyCode.RightShift} -- defaults

	self.mouseLockToggledEvent = Instance.new("BindableEvent")

	local boundKeysObj = script:FindFirstChild("BoundKeys")
	if (not boundKeysObj) or (not boundKeysObj:IsA("StringValue")) then
		-- If object with correct name was found, but it's not a StringValue, destroy and replace
		if boundKeysObj then
			boundKeysObj:Destroy()
		end

		boundKeysObj = Instance.new("StringValue")
		boundKeysObj.Name = "BoundKeys"
		boundKeysObj.Value = "LeftShift,RightShift"
		boundKeysObj.Parent = script
	end

	if boundKeysObj then
		boundKeysObj.Changed:Connect(function(value)
			self:OnBoundKeysObjectChanged(value)
		end)
		self:OnBoundKeysObjectChanged(boundKeysObj.Value) -- Initial setup call
	end

	-- Watch for changes to user's ControlMode and ComputerMovementMode settings and update the feature availability accordingly
	GameSettings.Changed:Connect(function(property)
		if property == "ControlMode" or property == "ComputerMovementMode" then
			self:UpdateMouseLockAvailability()
		end
	end)

	-- Watch for changes to DevEnableMouseLock and update the feature availability accordingly
	PlayersService.LocalPlayer:GetPropertyChangedSignal("DevEnableMouseLock"):Connect(function()
		self:UpdateMouseLockAvailability()
	end)

	-- Watch for changes to DevEnableMouseLock and update the feature availability accordingly
	PlayersService.LocalPlayer:GetPropertyChangedSignal("DevComputerMovementMode"):Connect(function()
		self:UpdateMouseLockAvailability()
	end)

	self:UpdateMouseLockAvailability()

	return self
end

function MouseLockController:GetIsMouseLocked()
	return true--self.isMouseLocked
end

function MouseLockController:GetBindableToggleEvent()
	return self.mouseLockToggledEvent.Event
end

function MouseLockController:GetMouseLockOffset()
	local offsetValueObj = script:FindFirstChild("CameraOffset")
	if offsetValueObj and offsetValueObj:IsA("Vector3Value") then
		return offsetValueObj.Value
	else
		-- If CameraOffset object was found but not correct type, destroy
		if offsetValueObj then
			offsetValueObj:Destroy()
		end
		offsetValueObj = Instance.new("Vector3Value")
		offsetValueObj.Name = "CameraOffset"
		offsetValueObj.Value = Vector3.new(1.75,0,0) -- Legacy Default Value
		offsetValueObj.Parent = script
	end

	if offsetValueObj and offsetValueObj.Value then
		return offsetValueObj.Value
	end

	return Vector3.new(1.75,0,0)
end

function MouseLockController:UpdateMouseLockAvailability()
	local devAllowsMouseLock = PlayersService.LocalPlayer.DevEnableMouseLock
	local devMovementModeIsScriptable = PlayersService.LocalPlayer.DevComputerMovementMode == Enum.DevComputerMovementMode.Scriptable
	local userHasMouseLockModeEnabled = GameSettings.ControlMode == Enum.ControlMode.MouseLockSwitch
	local userHasClickToMoveEnabled =  GameSettings.ComputerMovementMode == Enum.ComputerMovementMode.ClickToMove
	local MouseLockAvailable = devAllowsMouseLock and userHasMouseLockModeEnabled and not userHasClickToMoveEnabled and not devMovementModeIsScriptable

	if MouseLockAvailable~=self.enabled then
		self:EnableMouseLock(MouseLockAvailable)
	end
end

function MouseLockController:OnBoundKeysObjectChanged(newValue)
	self.boundKeys = {} -- Overriding defaults, note: possibly with nothing at all if boundKeysObj.Value is "" or contains invalid values
	for token in string.gmatch(newValue,"[^%s,]+") do
		for _, keyEnum in pairs(Enum.KeyCode:GetEnumItems()) do
			if token == keyEnum.Name then
				self.boundKeys[#self.boundKeys+1] = keyEnum
				break
			end
		end
	end
	self:UnbindContextActions()
	self:BindContextActions()
end
