function Gamepad.GetHighestPriorityGamepad(V)local y=UserInputService:GetConnectedGamepads()local A=NONE for V,y in pairs(y)do if y.Value<A.Value then A=y end end return A end function Gamepad.BindContextActions(V)if V.activeGamepad==NONE then return false end local y=function(y)if y==Enum.UserInputState.Cancel then V.moveVector=ZERO_VECTOR3 else V.moveVector=Vector3.new(V.leftValue+V.rightValue,0,V.forwardValue+V.backwardValue)end end local A=function(A,j,a)V.forwardValue=j==Enum.UserInputState.Begin and-1 or 0 y(j)end local j=function(A,j,a)V.backwardValue=j==Enum.UserInputState.Begin and 1 or 0 y(j)end local a=function(A,j,a)V.leftValue=j==Enum.UserInputState.Begin and-1 or 0 y(j)end local E=function(A,j,a)V.rightValue=j==Enum.UserInputState.Begin and 1 or 0 y(j)end local K=function(y,A,j)V.isJumping=A==Enum.UserInputState.Begin if FFlagPlayerScriptsBindAtPriority then return Enum.ContextActionResult.Sink end end local F=function(y,A,j)if A==Enum.UserInputState.Cancel then V.moveVector=ZERO_VECTOR3 return FFlagPlayerScriptsBindAtPriority and Enum.ContextActionResult.Sink or nil end if V.activeGamepad~=j.UserInputType then return FFlagPlayerScriptsBindAtPriority and Enum.ContextActionResult.Pass or nil end if j.KeyCode~=Enum.KeyCode.Thumbstick1 then return end if j.Position.magnitude>thumbstickDeadzone then V.moveVector=Vector3.new(j.Position.X,0,-j.Position.Y)else V.moveVector=ZERO_VECTOR3 end if FFlagPlayerScriptsBindAtPriority then return Enum.ContextActionResult.Sink end end ContextActionService:BindActivate(V.activeGamepad,Enum.KeyCode.ButtonR2)if FFlagPlayerScriptsBindAtPriority then ContextActionService:BindActionAtPriority("\106\117\109\112\065\099\116\105\111\110",K,false,V.CONTROL_ACTION_PRIORITY,Enum.KeyCode.ButtonA)ContextActionService:BindActionAtPriority("\109\111\118\101\084\104\117\109\098\115\116\105\099\107",F,false,V.CONTROL_ACTION_PRIORITY,Enum.KeyCode.Thumbstick1)else ContextActionService:BindAction("\106\117\109\112\065\099\116\105\111\110",K,false,Enum.KeyCode.ButtonA)ContextActionService:BindAction("\109\111\118\101\084\104\117\109\098\115\116\105\099\107",F,false,Enum.KeyCode.Thumbstick1)end return true end function Gamepad.UnbindContextActions(V)if V.activeGamepad~=NONE then ContextActionService:UnbindActivate(V.activeGamepad,Enum.KeyCode.ButtonR2)end ContextActionService:UnbindAction("\109\111\118\101\084\104\117\109\098\115\116\105\099\107")ContextActionService:UnbindAction("\106\117\109\112\065\099\116\105\111\110")end function Gamepad.OnNewGamepadConnected(V)local y=V:GetHighestPriorityGamepad()if y==V.activeGamepad then return end if y==NONE then warn("\071\097\109\101\112\097\100\058\079\110\078\101\119\071\097\109\101\112\097\100\067\111\110\110\101\099\116\101\100 \102\111\117\110\100 \110\111 \099\111\110\110\101\099\116\101\100 \103\097\109\101\112\097\100\115")V:UnbindContextActions()return end if V.activeGamepad~=NONE then V:UnbindContextActions()end V.activeGamepad=y V:BindContextActions()end function Gamepad.OnCurrentGamepadDisconnected(V)if V.activeGamepad~=NONE then ContextActionService:UnbindActivate(V.activeGamepad,Enum.KeyCode.ButtonR2)end local y=V:GetHighestPriorityGamepad()if V.activeGamepad~=NONE and y==V.activeGamepad then warn("\071\097\109\101\112\097\100\058\079\110\067\117\114\114\101\110\116\071\097\109\101\112\097\100\068\105\115\099\111\110\110\101\099\116\101\100 \102\111\117\110\100 \116\104\101 \115\117\112\112\111\115\101\100\108\121 \100\105\115\099\111\110\110\101\099\116\101\100 \103\097\109\101\112\097\100 \105\110 \099\111\110\110\101\099\116\101\100\071\097\109\101\112\097\100\115\046")V:UnbindContextActions()V.activeGamepad=NONE return end if y==NONE then V:UnbindContextActions()V.activeGamepad=NONE else V.activeGamepad=y ContextActionService:BindActivate(V.activeGamepad,Enum.KeyCode.ButtonR2)end end function Gamepad.ConnectGamepadConnectionListeners(V)V.gamepadConnectedConn=UserInputService.GamepadConnected:Connect(function(y)V:OnNewGamepadConnected()end)V.gamepadDisconnectedConn=UserInputService.GamepadDisconnected:Connect(function(y)if V.activeGamepad==y then V:OnCurrentGamepadDisconnected()end end)end function Gamepad.DisconnectGamepadConnectionListeners(V)if V.gamepadConnectedConn then V.gamepadConnectedConn:Disconnect()V.gamepadConnectedConn=nil end if V.gamepadDisconnectedConn then V.gamepadDisconnectedConn:Disconnect()V.gamepadDisconnectedConn=nil end end return Gamepad

function Gamepad:GetHighestPriorityGamepad()
	local connectedGamepads = UserInputService:GetConnectedGamepads()
	local bestGamepad = NONE -- Note that this value is higher than all valid gamepad values
	for _, gamepad in pairs(connectedGamepads) do
		if gamepad.Value < bestGamepad.Value then
			bestGamepad = gamepad
		end
	end
	return bestGamepad
end

function Gamepad:BindContextActions()
	
	if self.activeGamepad == NONE then
		-- There must be an active gamepad to set up bindings
		return false
	end
	
	
	local updateMovement = function(inputState)
		if inputState == Enum.UserInputState.Cancel then
			self.moveVector = ZERO_VECTOR3
		else
			self.moveVector = Vector3.new(self.leftValue + self.rightValue, 0, self.forwardValue + self.backwardValue)
		end
	end
	
	-- Note: In the previous version of this code, the movement values were not zeroed-out on UserInputState. Cancel, now they are,
	-- which fixes them from getting stuck on.
	local handleMoveForward = function(actionName, inputState, inputObject)			
		self.forwardValue = (inputState == Enum.UserInputState.Begin) and -1 or 0
		updateMovement(inputState)
	end
	
	local handleMoveBackward = function(actionName, inputState, inputObject)	
		self.backwardValue = (inputState == Enum.UserInputState.Begin) and 1 or 0
		updateMovement(inputState)
	end
	
	local handleMoveLeft = function(actionName, inputState, inputObject)	
		self.leftValue = (inputState == Enum.UserInputState.Begin) and -1 or 0
		updateMovement(inputState)
	end
	
	local handleMoveRight = function(actionName, inputState, inputObject)	
		self.rightValue = (inputState == Enum.UserInputState.Begin) and 1 or 0
		updateMovement(inputState)
	end
	
	local handleJumpAction = function(actionName, inputState, inputObject)
		self.isJumping = (inputState == Enum.UserInputState.Begin)
		if FFlagPlayerScriptsBindAtPriority then
			return Enum.ContextActionResult.Sink
		end
	end
	
	local handleThumbstickInput = function(actionName, inputState, inputObject)
		
		if inputState == Enum.UserInputState.Cancel then
			self.moveVector = ZERO_VECTOR3
			return FFlagPlayerScriptsBindAtPriority and Enum.ContextActionResult.Sink or nil
		end
		
		if self.activeGamepad ~= inputObject.UserInputType then 
			return FFlagPlayerScriptsBindAtPriority and Enum.ContextActionResult.Pass or nil
		end
		if inputObject.KeyCode ~= Enum.KeyCode.Thumbstick1 then return end
		
		if inputObject.Position.magnitude > thumbstickDeadzone then
			self.moveVector  =  Vector3.new(inputObject.Position.X, 0, -inputObject.Position.Y)
		else
			self.moveVector = ZERO_VECTOR3
		end
		if FFlagPlayerScriptsBindAtPriority then
			return Enum.ContextActionResult.Sink
		end
	end
	
	ContextActionService:BindActivate(self.activeGamepad, Enum.KeyCode.ButtonR2)
	if FFlagPlayerScriptsBindAtPriority then
		ContextActionService:BindActionAtPriority("jumpAction", handleJumpAction, false,
			self.CONTROL_ACTION_PRIORITY, Enum.KeyCode.ButtonA)
		ContextActionService:BindActionAtPriority("moveThumbstick", handleThumbstickInput, false,
			self.CONTROL_ACTION_PRIORITY, Enum.KeyCode.Thumbstick1)
	else
		ContextActionService:BindAction("jumpAction",handleJumpAction, false, Enum.KeyCode.ButtonA)
		ContextActionService:BindAction("moveThumbstick",handleThumbstickInput, false, Enum.KeyCode.Thumbstick1)
	end
	
	return true
end

function Gamepad:UnbindContextActions()
	if self.activeGamepad ~= NONE then
		ContextActionService:UnbindActivate(self.activeGamepad, Enum.KeyCode.ButtonR2)
	end
	ContextActionService:UnbindAction("moveThumbstick")
	ContextActionService:UnbindAction("jumpAction")
end

function Gamepad:OnNewGamepadConnected()
	-- A new gamepad has been connected.
	local bestGamepad = self:GetHighestPriorityGamepad()
	
	if bestGamepad == self.activeGamepad then
		-- A new gamepad was connected, but our active gamepad is not changing
		return
	end
	
	if bestGamepad == NONE then
		-- There should be an active gamepad when GamepadConnected fires, so this should not
		-- normally be hit. If there is no active gamepad, unbind actions but leave
		-- the module enabled and continue to listen for a new gamepad connection.
		warn("Gamepad:OnNewGamepadConnected found no connected gamepads")
		self:UnbindContextActions()
		return
	end
	
	if self.activeGamepad ~= NONE then
		-- Switching from one active gamepad to another
		self:UnbindContextActions()
	end
	
	self.activeGamepad = bestGamepad
	self:BindContextActions()
end

function Gamepad:OnCurrentGamepadDisconnected()
	if self.activeGamepad ~= NONE then
		ContextActionService:UnbindActivate(self.activeGamepad, Enum.KeyCode.ButtonR2)
	end
	
	local bestGamepad = self:GetHighestPriorityGamepad()

	if self.activeGamepad ~= NONE and bestGamepad == self.activeGamepad then
		warn("Gamepad:OnCurrentGamepadDisconnected found the supposedly disconnected gamepad in connectedGamepads.")
		self:UnbindContextActions()
		self.activeGamepad = NONE
		return
	end	
	
	if bestGamepad == NONE then
		-- No active gamepad, unbinding actions but leaving gamepad connection listener active
		self:UnbindContextActions()
		self.activeGamepad = NONE
	else
		-- Set new gamepad as active and bind to tool activation
		self.activeGamepad = bestGamepad
		ContextActionService:BindActivate(self.activeGamepad, Enum.KeyCode.ButtonR2)
	end
end

function Gamepad:ConnectGamepadConnectionListeners()
	self.gamepadConnectedConn = UserInputService.GamepadConnected:Connect(function(gamepadEnum)
		self:OnNewGamepadConnected()
	end)
	
	self.gamepadDisconnectedConn = UserInputService.GamepadDisconnected:Connect(function(gamepadEnum)
		if self.activeGamepad == gamepadEnum then
			self:OnCurrentGamepadDisconnected()
		end
	end)

end

function Gamepad:DisconnectGamepadConnectionListeners()
	if self.gamepadConnectedConn then
		self.gamepadConnectedConn:Disconnect()
		self.gamepadConnectedConn = nil
	end
	
	if self.gamepadDisconnectedConn then
		self.gamepadDisconnectedConn:Disconnect()
		self.gamepadDisconnectedConn = nil
	end
end

return Gamepad
