<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
	<External>null</External>
	<External>nil</External>
	<Item class="LocalScript" referent="RBXCDA097EECF134E9A9DE7A8ED65B8C529">
		<Properties>
			<bool name="Disabled">false</bool>
			<Content name="LinkedSource"><null></null></Content>
			<string name="Name">ControlScript</string>
			<ProtectedString name="Source"><![CDATA[--[[
	// FileName: ControlScript.lua
	// Version 1.0
	// Written by: jmargh
	// Description: Manages in game controls for both touch and keyboard/mouse devices.
	
	// This script will be inserted into PlayerScripts under each player by default. If you want to
	// create your own custom controls or modify these controls, you must place a script with this
	// name, ControlScript, under StarterPlayer -> PlayerScripts.
	
	// Required Modules:
		ClickToMove
		DPad
		KeyboardMovement
		Thumbpad
		Thumbstick
		TouchJump
		MasterControl
		VehicleController
--]]

--[[ Services ]]--
local ContextActionService = game:GetService('ContextActionService')
local Players = game:GetService('Players')
local UserInputService = game:GetService('UserInputService')
-- Settings and GameSettings are read only
local Settings = UserSettings()
local GameSettings = Settings.GameSettings

-- Issue with play solo? (F6)
while not UserInputService.KeyboardEnabled and not UserInputService.TouchEnabled and not UserInputService.GamepadEnabled do
	wait()
end

--[[ Script Variables ]]--
while not Players.LocalPlayer do
	wait()
end
local LocalPlayer = Players.LocalPlayer
local PlayerGui = LocalPlayer:WaitForChild('PlayerGui')
local IsTouchDevice = UserInputService.TouchEnabled
local UserMovementMode = IsTouchDevice and GameSettings.TouchMovementMode or GameSettings.ComputerMovementMode
local DevMovementMode = IsTouchDevice and LocalPlayer.DevTouchMovementMode or LocalPlayer.DevComputerMovementMode
local IsUserChoice = (IsTouchDevice and DevMovementMode == Enum.DevTouchMovementMode.UserChoice) or
	DevMovementMode == Enum.DevComputerMovementMode.UserChoice
local TouchGui = nil
local TouchControlFrame = nil
local TouchJumpModule = nil
local IsModalEnabled = UserInputService.ModalEnabled
local BindableEvent_OnFailStateChanged = nil
local isJumpEnabled = false


--[[ Modules ]]--
local CurrentControlModule = nil
local ClickToMoveTouchControls = nil
local ControlModules = {}

local MasterControl = require(script:WaitForChild('MasterControl'))

if IsTouchDevice then
	ControlModules.Thumbstick = require(script.MasterControl:WaitForChild('Thumbstick'))
	ControlModules.Thumbpad = require(script.MasterControl:WaitForChild('Thumbpad'))
	ControlModules.DPad = require(script.MasterControl:WaitForChild('DPad'))
	ControlModules.Default = ControlModules.Thumbstick
	TouchJumpModule = require(script.MasterControl:WaitForChild('TouchJump'))
	BindableEvent_OnFailStateChanged = script.Parent:WaitForChild('OnClickToMoveFailStateChange')
else
	ControlModules.Keyboard = require(script.MasterControl:WaitForChild('KeyboardMovement'))
end
ControlModules.Gamepad = require(script.MasterControl:WaitForChild('Gamepad'))
local success, value = pcall(function() return UserSettings():IsUserFeatureEnabled("UserUseLuaVehicleController") end)
if success and value then
	local VehicleController = require(script.MasterControl:WaitForChild('VehicleController')) 	-- Not used, but needs to be required
end


--[[ Initialization/Setup ]]--
local function createTouchGuiContainer()
	if TouchGui then TouchGui:Destroy() end
	
	-- Container for all touch device guis
	TouchGui = Instance.new('ScreenGui')
	TouchGui.Name = "TouchGui"
	TouchGui.Parent = PlayerGui
	
	TouchControlFrame = Instance.new('Frame')
	TouchControlFrame.Name = "TouchControlFrame"
	TouchControlFrame.Size = UDim2.new(1, 0, 1, 0)
	TouchControlFrame.BackgroundTransparency = 1
	TouchControlFrame.Parent = TouchGui
	
	ControlModules.Thumbstick:Create(TouchControlFrame)
	ControlModules.DPad:Create(TouchControlFrame)
	ControlModules.Thumbpad:Create(TouchControlFrame)
	TouchJumpModule:Create(TouchControlFrame)
end

--[[ Local Functions ]]--
local function setJumpModule(isEnabled)
	if not isEnabled then
		TouchJumpModule:Disable()
	elseif CurrentControlModule == ControlModules.Thumbpad or CurrentControlModule == ControlModules.Thumbstick or
		CurrentControlModule == ControlModules.Default then
		--
		TouchJumpModule:Enable()
	end
end

local function setClickToMove()
	if DevMovementMode == Enum.DevTouchMovementMode.ClickToMove or DevMovementMode == Enum.DevComputerMovementMode.ClickToMove or
		UserMovementMode == Enum.ComputerMovementMode.ClickToMove or UserMovementMode == Enum.TouchMovementMode.ClickToMove then
		--
		if IsTouchDevice then
			ClickToMoveTouchControls = CurrentControlModule or ControlModules.Default
		end
	else
		if IsTouchDevice and ClickToMoveTouchControls then
			ClickToMoveTouchControls:Disable()
			ClickToMoveTouchControls = nil
		end
	end
end

--[[ Controls State Management ]]--
local onControlsChanged = nil
if IsTouchDevice then
	createTouchGuiContainer()
	onControlsChanged = function()
		local newModuleToEnable = nil
		if not IsUserChoice then
			if DevMovementMode == Enum.DevTouchMovementMode.Thumbstick then
				newModuleToEnable = ControlModules.Thumbstick
				isJumpEnabled = true
			elseif DevMovementMode == Enum.DevTouchMovementMode.Thumbpad then
				newModuleToEnable = ControlModules.Thumbpad
				isJumpEnabled = true
			elseif DevMovementMode == Enum.DevTouchMovementMode.DPad then
				newModuleToEnable = ControlModules.DPad
			elseif DevMovementMode == Enum.DevTouchMovementMode.ClickToMove then
				-- Managed by CameraScript
				newModuleToEnable = nil
			elseif DevMovementMode == Enum.DevTouchMovementMode.Scriptable then
				newModuleToEnable = nil
			end
		else
			if UserMovementMode == Enum.TouchMovementMode.Default or UserMovementMode == Enum.TouchMovementMode.Thumbstick then
				newModuleToEnable = ControlModules.Thumbstick
				isJumpEnabled = true
			elseif UserMovementMode == Enum.TouchMovementMode.Thumbpad then
				newModuleToEnable = ControlModules.Thumbpad
				isJumpEnabled = true
			elseif UserMovementMode == Enum.TouchMovementMode.DPad then
				newModuleToEnable = ControlModules.DPad
			elseif UserMovementMode == Enum.TouchMovementMode.ClickToMove then
				-- Managed by CameraScript
				newModuleToEnable = nil
			end
		end
		setClickToMove()
		if newModuleToEnable ~= CurrentControlModule then
			if CurrentControlModule then
				CurrentControlModule:Disable()
			end
			setJumpModule(isJumpEnabled)
			CurrentControlModule = newModuleToEnable
			if CurrentControlModule and not IsModalEnabled then
				CurrentControlModule:Enable()
				if isJumpEnabled then TouchJumpModule:Enable() end
			end
		end
	end
elseif UserInputService.KeyboardEnabled then
	onControlsChanged = function()
		-- NOTE: Click to move still uses keyboard. Leaving cases in case this ever changes.
		local newModuleToEnable = nil
		if not IsUserChoice then
			if DevMovementMode == Enum.DevComputerMovementMode.KeyboardMouse then
				newModuleToEnable = ControlModules.Keyboard
			elseif DevMovementMode == Enum.DevComputerMovementMode.ClickToMove then
				-- Managed by CameraScript
				newModuleToEnable = ControlModules.Keyboard
			end 
		else
			if UserMovementMode == Enum.ComputerMovementMode.KeyboardMouse or UserMovementMode == Enum.ComputerMovementMode.Default then
				newModuleToEnable = ControlModules.Keyboard
			elseif UserMovementMode == Enum.ComputerMovementMode.ClickToMove then
				-- Managed by CameraScript
				newModuleToEnable = ControlModules.Keyboard
			end
		end
		if newModuleToEnable ~= CurrentControlModule then
			if CurrentControlModule then
				CurrentControlModule:Disable()
			end
			CurrentControlModule = newModuleToEnable
			if CurrentControlModule then
				CurrentControlModule:Enable()
			end
		end
	end
elseif UserInputService.GamepadEnabled then
	onControlsChanged = function()
		-- nil for now, probably needs some stuff later
	end
end

--[[ Settings Changed Connections ]]--
LocalPlayer.Changed:connect(function(property)
	if IsTouchDevice and property == 'DevTouchMovementMode' then
		DevMovementMode = LocalPlayer.DevTouchMovementMode
		IsUserChoice = DevMovementMode == Enum.DevTouchMovementMode.UserChoice
		if IsUserChoice then
			UserMovementMode = GameSettings.TouchMovementMode
		end
		onControlsChanged()
	elseif not IsTouchDevice and property == 'DevComputerMovementMode' then
		DevMovementMode = LocalPlayer.DevComputerMovementMode
		IsUserChoice = DevMovementMode == Enum.DevComputerMovementMode.UserChoice
		if IsUserChoice then
			UserMovementMode = GameSettings.ComputerMovementMode
		end
		onControlsChanged()
	end
end)

GameSettings.Changed:connect(function(property)
	if not IsUserChoice then return end
	if property == 'TouchMovementMode' or property == 'ComputerMovementMode' then
		UserMovementMode = GameSettings[property]
		onControlsChanged()
	end
end)

--[[ Touch Events ]]--
if IsTouchDevice then
	-- On touch devices we need to recreate the guis on character load.
	LocalPlayer.CharacterAdded:connect(function(character)
		createTouchGuiContainer()
		if CurrentControlModule then
			CurrentControlModule:Disable()
			CurrentControlModule = nil
		end
		onControlsChanged()
	end)
	
	UserInputService.Changed:connect(function(property)
		if property == 'ModalEnabled' then
			IsModalEnabled = UserInputService.ModalEnabled
			setJumpModule(not UserInputService.ModalEnabled)
			if UserInputService.ModalEnabled then
				if CurrentControlModule then
					CurrentControlModule:Disable()
				end
			else
				if CurrentControlModule then
					CurrentControlModule:Enable()
				end
			end
		end
	end)

	BindableEvent_OnFailStateChanged.Event:connect(function(isOn)
		if ClickToMoveTouchControls then
			if isOn then
				ClickToMoveTouchControls:Enable()
			else
				ClickToMoveTouchControls:Disable()
			end
			if ClickToMoveTouchControls == ControlModules.Thumbpad or ClickToMoveTouchControls == ControlModules.Thumbstick or
				ClickToMoveTouchControls == ControlModules.Default then
				--
				if isOn then
					TouchJumpModule:Enable()
				else
					TouchJumpModule:Disable()
				end
			end
		end
	end)
end

MasterControl:Init()
onControlsChanged()

-- why do I need a wait here?!?!?!? Sometimes touch controls don't disappear without this
wait()
if UserInputService:GetGamepadConnected(Enum.UserInputType.Gamepad1) then
	if CurrentControlModule and IsTouchDevice then
		CurrentControlModule:Disable()
	end
	if isJumpEnabled and IsTouchDevice then TouchJumpModule:Disable() end

	ControlModules.Gamepad:Enable()
end

UserInputService.GamepadDisconnected:connect(function(gamepadEnum)
	if gamepadEnum ~= Enum.UserInputType.Gamepad1 then return end
	
	if CurrentControlModule and IsTouchDevice then
			CurrentControlModule:Enable()
	end
	if isJumpEnabled and IsTouchDevice then TouchJumpModule:Enable() end
	
	ControlModules.Gamepad:Disable()
end)

UserInputService.GamepadConnected:connect(function(gamepadEnum)
	if gamepadEnum ~= Enum.UserInputType.Gamepad1 then return end
	
	if CurrentControlModule and IsTouchDevice then
		CurrentControlModule:Disable()
	end
	if isJumpEnabled and IsTouchDevice then TouchJumpModule:Disable() end
	
	ControlModules.Gamepad:Enable()
end)

]]></ProtectedString>
		</Properties>
		<Item class="ModuleScript" referent="RBX32BC74A117AE433697E588A77C2E4619">
			<Properties>
				<Content name="LinkedSource"><null></null></Content>
				<string name="Name">MasterControl</string>
				<ProtectedString name="Source"><![CDATA[--[[
	// FileName: MasterControl
	// Version 1.0
	// Written by: jeditkacheff
	// Description: All character control scripts go thru this script, this script makes sure all actions are performed
--]]

--[[ Local Variables ]]--
local MasterControl = {}

local Players = game:GetService('Players')
local RunService = game:GetService('RunService')

while not Players.LocalPlayer do
	wait()
end
local LocalPlayer = Players.LocalPlayer
local CachedHumanoid = nil
local RenderSteppedCon = nil
local SeatedCn = nil
local moveFunc = LocalPlayer.Move

local isJumping = false
local isSeated = false
local myVehicleSeat = nil
local moveValue = Vector3.new(0,0,0)

--[[ Local Functions ]]--
local function getHumanoid()
	local character = LocalPlayer and LocalPlayer.Character
	if character then
		if CachedHumanoid and CachedHumanoid.Parent == character then
			return CachedHumanoid
		else
			CachedHumanoid = nil
			for _,child in pairs(character:GetChildren()) do
				if child:IsA('Humanoid') then
					CachedHumanoid = child
					return CachedHumanoid
				end
			end
		end
	end
end

--[[ Public API ]]--
function MasterControl:Init()
	
	local renderStepFunc = function()
		if LocalPlayer and LocalPlayer.Character then
			local humanoid = getHumanoid()
			if not humanoid then return end
			
			if humanoid and not humanoid.PlatformStand and isJumping then
				humanoid.Jump = isJumping
			end
			
			moveFunc(LocalPlayer, moveValue, true)	
		end
	end
	
	local success = pcall(function() RunService:BindToRenderStep("MasterControlStep", Enum.RenderPriority.Input.Value, renderStepFunc) end)
	
	if not success then
		if RenderSteppedCon then return end
		RenderSteppedCon = RunService.RenderStepped:connect(renderStepFunc)
	end
end

function MasterControl:Disable()
	local success = pcall(function() RunService:UnbindFromRenderStep("MasterControlStep") end)
	if not success then
		if RenderSteppedCon then
			RenderSteppedCon:disconnect()
			RenderSteppedCon = nil
		end
	end
	
	moveValue = Vector3.new(0,0,0)
	isJumping = false
end

function MasterControl:AddToPlayerMovement(playerMoveVector)
	moveValue = Vector3.new(moveValue.X + playerMoveVector.X, moveValue.Y + playerMoveVector.Y, moveValue.Z + playerMoveVector.Z)
end

function MasterControl:GetMoveVector()
	return moveValue
end

function MasterControl:SetIsJumping(jumping)
	isJumping = jumping
end

function MasterControl:DoJump()
	local humanoid = getHumanoid()
	if humanoid then
		humanoid.Jump = true
	end
end

return MasterControl
]]></ProtectedString>
			</Properties>
			<Item class="ModuleScript" referent="RBX54AF403FDF86481C8A957949FBE7F81D">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<string name="Name">DPad</string>
					<ProtectedString name="Source"><![CDATA[--[[
	// FileName: DPad
	// Version 1.0
	// Written by: jmargh
	// Description: Implements DPad controls for touch devices
--]]

local Players = game:GetService('Players')

local DPad = {}

local MasterControl = require(script.Parent)

--[[ Script Variables ]]--
while not Players.LocalPlayer do
	wait()
end
local LocalPlayer = Players.LocalPlayer
local DPadFrame = nil
local TouchObject = nil
local OnInputEnded = nil		-- defined in Create()

--[[ Constants ]]--
local DPAD_SHEET = "rbxasset://textures/ui/DPadSheet.png"
local COMPASS_DIR = {
	Vector3.new(1, 0, 0),			-- E
	Vector3.new(1, 0, 1).unit,		-- SE
	Vector3.new(0, 0, 1),			-- S
	Vector3.new(-1, 0, 1).unit,		-- SW
	Vector3.new(-1, 0, 0),			-- W
	Vector3.new(-1, 0, -1).unit,	-- NW
	Vector3.new(0, 0, -1),			-- N
	Vector3.new(1, 0, -1).unit,		-- NE
}

--[[ lua Function Cache ]]--
local ATAN2 = math.atan2
local FLOOR = math.floor
local PI = math.pi

--[[ Local Functions ]]--
local function createArrowLabel(name, position, size, rectOffset, rectSize)
	local image = Instance.new('ImageLabel')
	image.Name = name
	image.Image = DPAD_SHEET
	image.ImageRectOffset = rectOffset
	image.ImageRectSize = rectSize
	image.BackgroundTransparency = 1
	image.Size = size
	image.Position = position
	image.Parent = DPadFrame
	
	return image
end

local function getCenterPosition()
	return Vector2.new(DPadFrame.AbsolutePosition.x + DPadFrame.AbsoluteSize.x/2, DPadFrame.AbsolutePosition.y + DPadFrame.AbsoluteSize.y/2)
end

--[[ Public API ]]--
function DPad:Enable()
	DPadFrame.Visible = true
end

function DPad:Disable()
	DPadFrame.Visible = false
	OnInputEnded()
end

function DPad:Create(parentFrame)
	if DPadFrame then
		DPadFrame:Destroy()
		DPadFrame = nil
	end
	
	local position = UDim2.new(0, 10, 1, -230)
	DPadFrame = Instance.new('Frame')
	DPadFrame.Name = "DPadFrame"
	DPadFrame.Active = true
	DPadFrame.Visible = false
	DPadFrame.Size = UDim2.new(0, 192, 0, 192)
	DPadFrame.Position = position
	DPadFrame.BackgroundTransparency = 1
	
	local smArrowSize = UDim2.new(0, 23, 0, 23)
	local lgArrowSize = UDim2.new(0, 64, 0, 64)
	local smImgOffset = Vector2.new(46, 46)
	local lgImgOffset = Vector2.new(128, 128)
	
	local bBtn = createArrowLabel("BackButton", UDim2.new(0.5, -32, 1, -64), lgArrowSize, Vector2.new(0, 0), lgImgOffset)
	local fBtn = createArrowLabel("ForwardButton", UDim2.new(0.5, -32, 0, 0), lgArrowSize, Vector2.new(0, 258), lgImgOffset)
	local lBtn = createArrowLabel("LeftButton", UDim2.new(0, 0, 0.5, -32), lgArrowSize, Vector2.new(129, 129), lgImgOffset)
	local rBtn = createArrowLabel("RightButton", UDim2.new(1, -64, 0.5, -32), lgArrowSize, Vector2.new(0, 129), lgImgOffset)
	local jumpBtn = createArrowLabel("JumpButton", UDim2.new(0.5, -32, 0.5, -32), lgArrowSize, Vector2.new(129, 0), lgImgOffset)
	local flBtn = createArrowLabel("ForwardLeftButton", UDim2.new(0, 35, 0, 35), smArrowSize, Vector2.new(129, 258), smImgOffset)
	local frBtn = createArrowLabel("ForwardRightButton", UDim2.new(1, -55, 0, 35), smArrowSize, Vector2.new(176, 258), smImgOffset)
	flBtn.Visible = false
	frBtn.Visible = false
	
	-- input connections
	jumpBtn.InputBegan:connect(function(inputObject)
		MasterControl:DoJump()
	end)
	
	local movementVector = Vector3.new(0,0,0)
	local function normalizeDirection(inputPosition)
		local jumpRadius = jumpBtn.AbsoluteSize.x/2
		local centerPosition = getCenterPosition()
		local direction = Vector2.new(inputPosition.x - centerPosition.x, inputPosition.y - centerPosition.y)
		
		if direction.magnitude > jumpRadius then
			local angle = ATAN2(direction.y, direction.x)
			local octant = (FLOOR(8 * angle / (2 * PI) + 8.5)%8) + 1
			movementVector = COMPASS_DIR[octant]
		end
		
		if not flBtn.Visible and movementVector == COMPASS_DIR[7] then
			flBtn.Visible = true
			frBtn.Visible = true
		end
	end
	
	DPadFrame.InputBegan:connect(function(inputObject)
		if TouchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch then
			return
		end
		
		MasterControl:AddToPlayerMovement(-movementVector)
		
		TouchObject = inputObject
		normalizeDirection(TouchObject.Position)
		
		MasterControl:AddToPlayerMovement(movementVector)
	end)
	
	DPadFrame.InputChanged:connect(function(inputObject)
		if inputObject == TouchObject then
			MasterControl:AddToPlayerMovement(-movementVector)
			normalizeDirection(TouchObject.Position)
			MasterControl:AddToPlayerMovement(movementVector)
		end
	end)
	
	OnInputEnded = function()
		TouchObject = nil
		flBtn.Visible = false
		frBtn.Visible = false
		
		MasterControl:AddToPlayerMovement(-movementVector)
		movementVector = Vector3.new(0, 0, 0)
	end
	
	DPadFrame.InputEnded:connect(function(inputObject)
		if inputObject == TouchObject then
			OnInputEnded()
		end
	end)
	
	DPadFrame.Parent = parentFrame
end

return DPad
]]></ProtectedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX3D4DA58BA847457EA409CCC72356F9FF">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<string name="Name">Gamepad</string>
					<ProtectedString name="Source"><![CDATA[--[[
	// FileName: Gamepad
	// Written by: jeditkacheff
	// Description: Implements movement controls for gamepad devices (XBox, PS4, MFi, etc.)
--]]
local Gamepad = {}

local MasterControl = require(script.Parent)

local Players = game:GetService('Players')
local RunService = game:GetService('RunService')
local UserInputService = game:GetService('UserInputService')
local ContextActionService = game:GetService('ContextActionService')
local StarterPlayer = game:GetService('StarterPlayer')
local Settings = UserSettings()
local GameSettings = Settings.GameSettings
local currentMoveVector = Vector3.new(0,0,0)

while not Players.LocalPlayer do
	wait()
end
local LocalPlayer = Players.LocalPlayer

--[[ Constants ]]--
local thumbstickDeadzone = 0.14

local hasCancelType = pcall(function() local test = Enum.UserInputState.Cancel end)

--[[ Public API ]]--
function Gamepad:Enable()
	local forwardValue  = 0
	local backwardValue = 0
	local leftValue = 0
	local rightValue = 0
	
	local moveFunc = LocalPlayer.Move
	local gamepadSupports = UserInputService.GamepadSupports
	
	local controlCharacterGamepad1 = function(actionName, inputState, inputObject)
		if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 then return end
		if inputObject.KeyCode ~= Enum.KeyCode.Thumbstick1 then return end
		
		if hasCancelType and inputState == Enum.UserInputState.Cancel then
			MasterControl:AddToPlayerMovement(-currentMoveVector)
			currentMoveVector =  Vector3.new(0,0,0)
			return
		end
		
		if inputObject.Position.magnitude > thumbstickDeadzone then
			MasterControl:AddToPlayerMovement(-currentMoveVector)
			currentMoveVector =  Vector3.new(inputObject.Position.X, 0, -inputObject.Position.Y)
			MasterControl:AddToPlayerMovement(currentMoveVector)
		else
			MasterControl:AddToPlayerMovement(-currentMoveVector)
			currentMoveVector =  Vector3.new(0,0,0)
		end
	end
	
	local jumpCharacterGamepad1 = function(actionName, inputState, inputObject)		
		if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 then return end
		if inputObject.KeyCode ~= Enum.KeyCode.ButtonA then return end
		
		if hasCancelType and inputState == Enum.UserInputState.Cancel then
			MasterControl:SetIsJumping(false)
			return
		end
		
		MasterControl:SetIsJumping(inputObject.UserInputState == Enum.UserInputState.Begin)
	end
	
	local doDpadMoveUpdate = function()
		if not gamepadSupports(UserInputService, Enum.UserInputType.Gamepad1, Enum.KeyCode.Thumbstick1) then
			if LocalPlayer and LocalPlayer.Character then
				MasterControl:AddToPlayerMovement(-currentMoveVector)
				currentMoveVector = Vector3.new(leftValue + rightValue,0,forwardValue + backwardValue)
				MasterControl:AddToPlayerMovement(currentMoveVector)
			end
		end
	end
	
	local moveForwardFunc = function(actionName, inputState, inputObject)
		if inputState == Enum.UserInputState.End then
			forwardValue = -1
		elseif inputState == Enum.UserInputState.Begin or (hasCancelType and inputState == Enum.UserInputState.Cancel) then
			forwardValue = 0
		end
		
		doDpadMoveUpdate()
	end
	
	local moveBackwardFunc = function(actionName, inputState, inputObject)	
		if inputState == Enum.UserInputState.End then
			backwardValue = 1
		elseif inputState == Enum.UserInputState.Begin or (hasCancelType and inputState == Enum.UserInputState.Cancel) then
			backwardValue = 0
		end
		
		doDpadMoveUpdate()
	end
	
	local moveLeftFunc = function(actionName, inputState, inputObject)	
		if inputState == Enum.UserInputState.End then
			leftValue = -1
		elseif inputState == Enum.UserInputState.Begin or (hasCancelType and inputState == Enum.UserInputState.Cancel) then
			leftValue = 0
		end
		
		doDpadMoveUpdate()
	end
	
	local moveRightFunc = function(actionName, inputState, inputObject)	
		if inputState == Enum.UserInputState.End then
			rightValue = 1
		elseif inputState == Enum.UserInputState.Begin or (hasCancelType and inputState == Enum.UserInputState.Cancel) then
			rightValue = 0
		end
		
		doDpadMoveUpdate()
	end
	
	ContextActionService:BindAction("JumpButton",jumpCharacterGamepad1, false, Enum.KeyCode.ButtonA)
	ContextActionService:BindAction("MoveThumbstick",controlCharacterGamepad1, false, Enum.KeyCode.Thumbstick1)
	
	ContextActionService:BindAction("forwardDpad", moveForwardFunc, false, Enum.KeyCode.DPadUp)
	ContextActionService:BindAction("backwardDpad", moveBackwardFunc, false, Enum.KeyCode.DPadDown)
	ContextActionService:BindAction("leftDpad", moveLeftFunc, false, Enum.KeyCode.DPadLeft)
	ContextActionService:BindAction("rightDpad", moveRightFunc, false, Enum.KeyCode.DPadRight)
	
	ContextActionService:BindActivate(Enum.UserInputType.Gamepad1, Enum.KeyCode.ButtonR2)
	
	
	UserInputService.GamepadDisconnected:connect(function(gamepadEnum)
		if gamepadEnum ~= Enum.UserInputType.Gamepad1 then return end
		
		MasterControl:AddToPlayerMovement(-currentMoveVector)
		currentMoveVector = Vector3.new(0,0,0)
	end)

	UserInputService.GamepadConnected:connect(function(gamepadEnum)
		if gamepadEnum ~= Enum.UserInputType.Gamepad1 then return end
		
		MasterControl:AddToPlayerMovement(-currentMoveVector)
		currentMoveVector = Vector3.new(0,0,0)
	end)
end

function Gamepad:Disable()
	
	ContextActionService:UnbindAction("forwardDpad")
	ContextActionService:UnbindAction("backwardDpad")
	ContextActionService:UnbindAction("leftDpad")
	ContextActionService:UnbindAction("rightDpad")
	
	ContextActionService:UnbindAction("MoveThumbstick")
	ContextActionService:UnbindAction("JumpButton")
	ContextActionService:UnbindActivate(Enum.UserInputType.Gamepad1, Enum.KeyCode.ButtonR2)
	
	MasterControl:AddToPlayerMovement(-currentMoveVector)
	currentMoveVector = Vector3.new(0,0,0)
end

return Gamepad
]]></ProtectedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBXB4C4411EA2734CFF9A6656AB6AFB7FDC">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<string name="Name">KeyboardMovement</string>
					<ProtectedString name="Source"><![CDATA[--[[
	// FileName: ComputerMovementKeyboardMovement
	// Version 1.2
	// Written by: jeditkacheff/jmargh
	// Description: Implements movement controls for keyboard devices
--]]
local Players = game:GetService('Players')
local UserInputService = game:GetService('UserInputService')
local ContextActionService = game:GetService('ContextActionService')
local StarterPlayer = game:GetService('StarterPlayer')
local Settings = UserSettings()
local GameSettings = Settings.GameSettings

local KeyboardMovement = {}

while not Players.LocalPlayer do
	wait()
end
local LocalPlayer = Players.LocalPlayer
local CachedHumanoid = nil
local SeatJumpCn = nil
local TextFocusReleasedCn = nil
local TextFocusGainedCn = nil
local WindowFocusReleasedCn = nil

local MasterControl = require(script.Parent)
local currentMoveVector = Vector3.new(0,0,0)

--[[ Local Functions ]]--
local function getHumanoid()
	local character = LocalPlayer and LocalPlayer.Character
	if character then
		if CachedHumanoid and CachedHumanoid.Parent == character then
			return CachedHumanoid
		else
			CachedHumanoid = nil
			for _,child in pairs(character:GetChildren()) do
				if child:IsA('Humanoid') then
					CachedHumanoid = child
					return CachedHumanoid
				end
			end
		end
	end
end

--[[ Public API ]]--
function KeyboardMovement:Enable()
	if not UserInputService.KeyboardEnabled then
		return
	end
	
	local forwardValue  = 0
	local backwardValue = 0
	local leftValue = 0
	local rightValue = 0
	
	local updateMovement = function()
		MasterControl:AddToPlayerMovement(-currentMoveVector)
		currentMoveVector = Vector3.new(leftValue + rightValue,0,forwardValue + backwardValue)
		MasterControl:AddToPlayerMovement(currentMoveVector)
	end
	
	local moveForwardFunc = function(actionName, inputState, inputObject)
		if inputState == Enum.UserInputState.Begin then
			forwardValue = -1
		elseif inputState == Enum.UserInputState.End then
			forwardValue = 0
		end
		updateMovement()
	end
	
	local moveBackwardFunc = function(actionName, inputState, inputObject)	
		if inputState == Enum.UserInputState.Begin then
			backwardValue = 1
		elseif inputState == Enum.UserInputState.End then
			backwardValue = 0
		end
		updateMovement()
	end
	
	local moveLeftFunc = function(actionName, inputState, inputObject)	
		if inputState == Enum.UserInputState.Begin then
			leftValue = -1
		elseif inputState == Enum.UserInputState.End then
			leftValue = 0
		end
		updateMovement()
	end
	
	local moveRightFunc = function(actionName, inputState, inputObject)	
		if inputState == Enum.UserInputState.Begin then
			rightValue = 1
		elseif inputState == Enum.UserInputState.End then
			rightValue = 0
		end
		updateMovement()
	end
	
	local jumpFunc = function(actionName, inputState, inputObject)
		MasterControl:SetIsJumping(inputState == Enum.UserInputState.Begin)
	end
	
	-- TODO: remove up and down arrows, these seem unnecessary
	ContextActionService:BindActionToInputTypes("forwardMovement", moveForwardFunc, false, Enum.PlayerActions.CharacterForward)
	ContextActionService:BindActionToInputTypes("backwardMovement", moveBackwardFunc, false, Enum.PlayerActions.CharacterBackward)
	ContextActionService:BindActionToInputTypes("leftMovement", moveLeftFunc, false, Enum.PlayerActions.CharacterLeft)
	ContextActionService:BindActionToInputTypes("rightMovement", moveRightFunc, false, Enum.PlayerActions.CharacterRight)
	ContextActionService:BindActionToInputTypes("jumpAction", jumpFunc, false, Enum.PlayerActions.CharacterJump)
	-- TODO: make sure we check key state before binding to check if key is already down
	
	local function onFocusReleased()
		local humanoid = getHumanoid()
		if humanoid then
			MasterControl:AddToPlayerMovement(-currentMoveVector)
			currentMoveVector = Vector3.new(0, 0, 0)
			forwardValue, backwardValue, leftValue, rightValue = 0, 0, 0, 0
			MasterControl:SetIsJumping(false)
		end
	end
	
	local function onTextFocusGained(textboxFocused)
		MasterControl:SetIsJumping(false)
	end
	
	SeatJumpCn = UserInputService.InputBegan:connect(function(inputObject, isProcessed)
		if inputObject.KeyCode == Enum.KeyCode.Backspace and not isProcessed then
			local humanoid = getHumanoid()
			if humanoid and (humanoid.Sit or humanoid.PlatformStand) then
				MasterControl:DoJump()
			end
		end
	end)
	
	TextFocusReleasedCn = UserInputService.TextBoxFocusReleased:connect(onFocusReleased)
	TextFocusGainedCn = UserInputService.TextBoxFocused:connect(onTextFocusGained)
	-- TODO: remove pcall when API is live
	WindowFocusReleasedCn = UserInputService.WindowFocused:connect(onFocusReleased)
end

function KeyboardMovement:Disable()
	ContextActionService:UnbindAction("forwardMovement")
	ContextActionService:UnbindAction("backwardMovement")
	ContextActionService:UnbindAction("leftMovement")
	ContextActionService:UnbindAction("rightMovement")
	ContextActionService:UnbindAction("jumpAction")
	
	if SeatJumpCn then
		SeatJumpCn:disconnect()
		SeatJumpCn = nil
	end
	if TextFocusReleasedCn then
		TextFocusReleasedCn:disconnect()
		TextFocusReleasedCn = nil
	end
	if TextFocusGainedCn then
		TextFocusGainedCn:disconnect()
		TextFocusGainedCn = nil
	end
	if WindowFocusReleasedCn then
		WindowFocusReleasedCn:disconnect()
		WindowFocusReleasedCn = nil
	end
	
	MasterControl:AddToPlayerMovement(-currentMoveVector)
	currentMoveVector = Vector3.new(0,0,0)
end

return KeyboardMovement
]]></ProtectedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX1E3E090B922241488CF1527B6A17D7C7">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<string name="Name">Thumbpad</string>
					<ProtectedString name="Source"><![CDATA[--[[
	// FileName: Thumbpad
	// Version 1.0
	// Written by: jmargh
	// Description: Implements thumbpad controls for touch devices
--]]

local Players = game:GetService('Players')
local UserInputService = game:GetService('UserInputService')

local Thumbpad = {}

local MasterControl = require(script.Parent)

--[[ Script Variables ]]--
while not Players.LocalPlayer do
	wait()
end
local LocalPlayer = Players.LocalPlayer
local ThumbpadFrame = nil
local TouchObject = nil
local OnInputEnded = nil	-- is defined in Create()
local OnTouchChangedCn = nil
local OnTouchEndedCn = nil
local currentMoveVector = Vector3.new(0,0,0)

--[[ Constants ]]--
local DPAD_SHEET = "rbxasset://textures/ui/DPadSheet.png"
local TOUCH_CONTROL_SHEET = "rbxasset://textures/ui/TouchControlsSheet.png"

--[[ Local Functions ]]--
local function createArrowLabel(name, parent, position, size, rectOffset, rectSize)
	local image = Instance.new('ImageLabel')
	image.Name = name
	image.Image = DPAD_SHEET
	image.ImageRectOffset = rectOffset
	image.ImageRectSize = rectSize
	image.BackgroundTransparency = 1
	image.ImageColor3 = Color3.new(190/255, 190/255, 190/255)
	image.Size = size
	image.Position = position
	image.Parent = parent
	
	return image
end

--[[ Public API ]]--
function Thumbpad:Enable()
	ThumbpadFrame.Visible = true
end

function Thumbpad:Disable()
	ThumbpadFrame.Visible = false
	OnInputEnded()
end

function Thumbpad:Create(parentFrame)
	if ThumbpadFrame then
		ThumbpadFrame:Destroy()
		ThumbpadFrame = nil
		if OnTouchChangedCn then
			OnTouchChangedCn:disconnect()
			OnTouchChangedCn = nil
		end
		if OnTouchEndedCn then
			OnTouchEndedCn:disconnect()
			OnTouchEndedCn = nil
		end
	end
	
	local isSmallScreen = parentFrame.AbsoluteSize.y <= 500
	local thumbpadSize = isSmallScreen and 70 or 120
	local position = isSmallScreen and UDim2.new(0, thumbpadSize * 1.25, 1, -thumbpadSize - 20) or
		UDim2.new(0, thumbpadSize/2 - 10, 1, -thumbpadSize * 1.75 - 10)
	
	ThumbpadFrame = Instance.new('Frame')
	ThumbpadFrame.Name = "ThumbpadFrame"
	ThumbpadFrame.Visible = false
	ThumbpadFrame.Active = true
	ThumbpadFrame.Size = UDim2.new(0, thumbpadSize + 20, 0, thumbpadSize + 20)
	ThumbpadFrame.Position = position
	ThumbpadFrame.BackgroundTransparency = 1
	
	local outerImage = Instance.new('ImageLabel')
	outerImage.Name = "OuterImage"
	outerImage.Image = TOUCH_CONTROL_SHEET
	outerImage.ImageRectOffset = Vector2.new(0, 0)
	outerImage.ImageRectSize = Vector2.new(220, 220)
	outerImage.BackgroundTransparency = 1
	outerImage.Size = UDim2.new(0, thumbpadSize, 0, thumbpadSize)
	outerImage.Position = UDim2.new(0, 10, 0, 10)
	outerImage.Parent = ThumbpadFrame
	
	local smArrowSize = isSmallScreen and UDim2.new(0, 32, 0, 32) or UDim2.new(0, 64, 0, 64)
	local lgArrowSize = UDim2.new(0, smArrowSize.X.Offset * 2, 0, smArrowSize.Y.Offset * 2)
	local imgRectSize = Vector2.new(110, 110)
	local smImgOffset = isSmallScreen and -4 or -9
	local lgImgOffset = isSmallScreen and -28 or -55
	
	local dArrow = createArrowLabel("DownArrow", outerImage, UDim2.new(0.5, -smArrowSize.X.Offset/2, 1, lgImgOffset), smArrowSize, Vector2.new(8, 8), imgRectSize)
	local uArrow = createArrowLabel("UpArrow", outerImage, UDim2.new(0.5, -smArrowSize.X.Offset/2, 0, smImgOffset), smArrowSize, Vector2.new(8, 266), imgRectSize)
	local lArrow = createArrowLabel("LeftArrow", outerImage, UDim2.new(0, smImgOffset, 0.5, -smArrowSize.Y.Offset/2), smArrowSize, Vector2.new(137, 137), imgRectSize)
	local rArrow = createArrowLabel("RightArrow", outerImage, UDim2.new(1, lgImgOffset, 0.5, -smArrowSize.Y.Offset/2), smArrowSize, Vector2.new(8, 137), imgRectSize)
	
	local function doTween(guiObject, endSize, endPosition)
		guiObject:TweenSizeAndPosition(endSize, endPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Linear, 0.15, true)
	end
	
	local padOrigin = nil
	local deadZone = 0.1
	local isRight, isLeft, isUp, isDown = false, false, false, false
	local vForward = Vector3.new(0, 0, -1)
	local vRight = Vector3.new(1, 0, 0)
	local function doMove(pos)
		MasterControl:AddToPlayerMovement(-currentMoveVector)
		
		local delta = Vector2.new(pos.x, pos.y) - padOrigin
		currentMoveVector = delta / (thumbpadSize/2)
		
		-- Scaled Radial Dead Zone
		local inputAxisMagnitude = currentMoveVector.magnitude
		if inputAxisMagnitude < deadZone then
			currentMoveVector = Vector3.new(0, 0, 0)
		else
			currentMoveVector = currentMoveVector.unit * ((inputAxisMagnitude - deadZone) / (1 - deadZone))
			-- catch possible NAN Vector
			if currentMoveVector.magnitude == 0 then
				currentMoveVector = Vector3.new(0, 0, 0)
			else
				currentMoveVector = Vector3.new(currentMoveVector.x, 0, currentMoveVector.y).unit
			end
		end
		
		MasterControl:AddToPlayerMovement(currentMoveVector)
		
		local forwardDot = currentMoveVector:Dot(vForward)
		local rightDot = currentMoveVector:Dot(vRight)
		if forwardDot > 0.5 then		-- UP
			if not isUp then
				isUp, isDown = true, false
				doTween(uArrow, lgArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset, 0, smImgOffset - smArrowSize.Y.Offset * 1.5))
				doTween(dArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 1, lgImgOffset))
			end
		elseif forwardDot < -0.5 then	-- DOWN
			if not isDown then
				isDown, isUp = true, false
				doTween(dArrow, lgArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset, 1, lgImgOffset + smArrowSize.Y.Offset/2))
				doTween(uArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 0, smImgOffset))
			end
		else
			isUp, isDown = false, false
			doTween(dArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 1, lgImgOffset))
			doTween(uArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 0, smImgOffset))
		end
		
		if rightDot > 0.5 then
			if not isRight then
				isRight, isLeft = true, false
				doTween(rArrow, lgArrowSize, UDim2.new(1, lgImgOffset + smArrowSize.X.Offset/2, 0.5, -smArrowSize.Y.Offset))
				doTween(lArrow, smArrowSize, UDim2.new(0, smImgOffset, 0.5, -smArrowSize.Y.Offset/2))
			end
		elseif rightDot < -0.5 then
			if not isLeft then
				isLeft, isRight = true, false
				doTween(lArrow, lgArrowSize, UDim2.new(0, smImgOffset - smArrowSize.X.Offset * 1.5, 0.5, -smArrowSize.Y.Offset))
				doTween(rArrow, smArrowSize, UDim2.new(1, lgImgOffset, 0.5, -smArrowSize.Y.Offset/2))
			end
		else
			isRight, isLeft = false, false
			doTween(lArrow, smArrowSize, UDim2.new(0, smImgOffset, 0.5, -smArrowSize.Y.Offset/2))
			doTween(rArrow, smArrowSize, UDim2.new(1, lgImgOffset, 0.5, -smArrowSize.Y.Offset/2))
		end
	end
	
	--input connections
	ThumbpadFrame.InputBegan:connect(function(inputObject)
		if TouchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch then
			return
		end
		
		ThumbpadFrame.Position = UDim2.new(0, inputObject.Position.x - ThumbpadFrame.AbsoluteSize.x/2, 0, inputObject.Position.y - ThumbpadFrame.Size.Y.Offset/2)
		padOrigin = Vector2.new(ThumbpadFrame.AbsolutePosition.x + ThumbpadFrame.AbsoluteSize.x/2,
			ThumbpadFrame.AbsolutePosition.y + ThumbpadFrame.AbsoluteSize.y/2)
		doMove(inputObject.Position)
		TouchObject = inputObject
	end)
	
	OnTouchChangedCn = UserInputService.TouchMoved:connect(function(inputObject, isProcessed)
		if inputObject == TouchObject then
			doMove(TouchObject.Position)
		end
	end)
	
	OnInputEnded = function()
		MasterControl:AddToPlayerMovement(-currentMoveVector)
		currentMoveVector = Vector3.new(0,0,0)

		ThumbpadFrame.Position = position
		TouchObject = nil
		isUp, isDown, isLeft, isRight = false, false, false, false
		doTween(dArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 1, lgImgOffset))
		doTween(uArrow, smArrowSize, UDim2.new(0.5, -smArrowSize.X.Offset/2, 0, smImgOffset))
		doTween(lArrow, smArrowSize, UDim2.new(0, smImgOffset, 0.5, -smArrowSize.Y.Offset/2))
		doTween(rArrow, smArrowSize, UDim2.new(1, lgImgOffset, 0.5, -smArrowSize.Y.Offset/2))
	end
	
	OnTouchEndedCn = UserInputService.TouchEnded:connect(function(inputObject)
		if inputObject == TouchObject then
			OnInputEnded()
		end
	end)
	
	ThumbpadFrame.Parent = parentFrame
end

return Thumbpad
]]></ProtectedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX4085E7D84B9F4D049BA1EB9C1D13F5D2">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<string name="Name">Thumbstick</string>
					<ProtectedString name="Source"><![CDATA[--[[
	// FileName: Thumbstick
	// Version 1.0
	// Written by: jmargh
	// Description: Implements thumbstick controls for touch devices
--]]
local Players = game:GetService('Players')
local UserInputService = game:GetService('UserInputService')
local MasterControl = require(script.Parent)

local Thumbstick = {}

--[[ Script Variables ]]--
while not Players.LocalPlayer do
	wait()
end
local LocalPlayer = Players.LocalPlayer
local IsFollowStick = true
local ThumbstickFrame = nil
local MoveTouchObject = nil
local OnTouchEnded = nil		-- defined in Create()
local OnTouchMovedCn = nil
local OnTouchEndedCn = nil
local currentMoveVector = Vector3.new(0,0,0)

--[[ Constants ]]--
local TOUCH_CONTROL_SHEET = "rbxasset://textures/ui/TouchControlsSheet.png"

--[[ Public API ]]--
function Thumbstick:Enable()
	ThumbstickFrame.Visible = true
end

function Thumbstick:Disable()
	ThumbstickFrame.Visible = false
	OnTouchEnded()
end

function Thumbstick:Create(parentFrame)
	if ThumbstickFrame then
		ThumbstickFrame:Destroy()
		ThumbstickFrame = nil
		if OnTouchMovedCn then
			OnTouchMovedCn:disconnect()
			OnTouchMovedCn = nil
		end
		if OnTouchEndedCn then
			OnTouchEndedCn:disconnect()
			OnTouchEndedCn = nil
		end
	end
		
	local isSmallScreen = parentFrame.AbsoluteSize.y <= 500
	local thumbstickSize = isSmallScreen and 70 or 120
	local position = isSmallScreen and UDim2.new(0, (thumbstickSize/2) - 10, 1, -thumbstickSize - 20) or
		UDim2.new(0, thumbstickSize/2, 1, -thumbstickSize * 1.75)
		
	ThumbstickFrame = Instance.new('Frame')
	ThumbstickFrame.Name = "ThumbstickFrame"
	ThumbstickFrame.Active = true
	ThumbstickFrame.Visible = false
	ThumbstickFrame.Size = UDim2.new(0, thumbstickSize, 0, thumbstickSize)
	ThumbstickFrame.Position = position
	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, thumbstickSize, 0, thumbstickSize)
	outerImage.Position = UDim2.new(0, 0, 0, 0)
	outerImage.Parent = ThumbstickFrame
	
	StickImage = Instance.new('ImageLabel')
	StickImage.Name = "StickImage"
	StickImage.Image = TOUCH_CONTROL_SHEET
	StickImage.ImageRectOffset = Vector2.new(220, 0)
	StickImage.ImageRectSize = Vector2.new(111, 111)
	StickImage.BackgroundTransparency = 1
	StickImage.Size = UDim2.new(0, thumbstickSize/2, 0, thumbstickSize/2)
	StickImage.Position = UDim2.new(0, thumbstickSize/2 - thumbstickSize/4, 0, thumbstickSize/2 - thumbstickSize/4)
	StickImage.ZIndex = 2
	StickImage.Parent = ThumbstickFrame
	
	local centerPosition = nil
	local deadZone = 0.05
	local function doMove(direction)
		MasterControl:AddToPlayerMovement(-currentMoveVector)
		
		currentMoveVector = direction / (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
		
		MasterControl:AddToPlayerMovement(currentMoveVector)
	end
	
	local function moveStick(pos)
		local relativePosition = Vector2.new(pos.x - centerPosition.x, pos.y - centerPosition.y)
		local length = relativePosition.magnitude
		local maxLength = ThumbstickFrame.AbsoluteSize.x/2
		if IsFollowStick and length > maxLength then
			local offset = relativePosition.unit * maxLength
			ThumbstickFrame.Position = UDim2.new(
				0, pos.x - ThumbstickFrame.AbsoluteSize.x/2 - offset.x,
				0, pos.y - ThumbstickFrame.AbsoluteSize.y/2 - offset.y)
		else
			length = math.min(length, maxLength)
			relativePosition = relativePosition.unit * length
		end
		StickImage.Position = UDim2.new(0, relativePosition.x + StickImage.AbsoluteSize.x/2, 0, relativePosition.y + StickImage.AbsoluteSize.y/2)
	end
	
	-- input connections
	ThumbstickFrame.InputBegan:connect(function(inputObject)
		if MoveTouchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch then
			return
		end
		
		MoveTouchObject = inputObject
		ThumbstickFrame.Position = UDim2.new(0, inputObject.Position.x - ThumbstickFrame.Size.X.Offset/2, 0, inputObject.Position.y - ThumbstickFrame.Size.Y.Offset/2)
		centerPosition = Vector2.new(ThumbstickFrame.AbsolutePosition.x + ThumbstickFrame.AbsoluteSize.x/2,
			ThumbstickFrame.AbsolutePosition.y + ThumbstickFrame.AbsoluteSize.y/2)
		local direction = Vector2.new(inputObject.Position.x - centerPosition.x, inputObject.Position.y - centerPosition.y)
		moveStick(inputObject.Position)
	end)
	
	OnTouchMovedCn = UserInputService.TouchMoved:connect(function(inputObject, isProcessed)
		if inputObject == MoveTouchObject then
			centerPosition = Vector2.new(ThumbstickFrame.AbsolutePosition.x + ThumbstickFrame.AbsoluteSize.x/2,
				ThumbstickFrame.AbsolutePosition.y + 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)
	
	OnTouchEnded = function()
		ThumbstickFrame.Position = position
		StickImage.Position = UDim2.new(0, ThumbstickFrame.Size.X.Offset/2 - thumbstickSize/4, 0, ThumbstickFrame.Size.Y.Offset/2 - thumbstickSize/4)
		MoveTouchObject = nil
		
		MasterControl:AddToPlayerMovement(-currentMoveVector)
		currentMoveVector = Vector3.new(0,0,0)
	end
	
	OnTouchEndedCn = UserInputService.TouchEnded:connect(function(inputObject, isProcessed)
		if inputObject == MoveTouchObject then
			OnTouchEnded()
		end
	end)
	
	ThumbstickFrame.Parent = parentFrame
end

return Thumbstick
]]></ProtectedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBXD76DF8ABD3DC4228B34596375A6D3BCC">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<string name="Name">TouchJump</string>
					<ProtectedString name="Source"><![CDATA[--[[
	// FileName: TouchJump
	// Version 1.0
	// Written by: jmargh
	// Description: Implements jump controls for touch devices. Use with Thumbstick and Thumbpad
--]]

local Players = game:GetService('Players')

local TouchJump = {}

local MasterControl = require(script.Parent)

--[[ Script Variables ]]--
while not Players.LocalPlayer do
	wait()
end
local LocalPlayer = Players.LocalPlayer
local JumpButton = nil
local OnInputEnded = nil		-- defined in Create()

--[[ Constants ]]--
local TOUCH_CONTROL_SHEET = "rbxasset://textures/ui/TouchControlsSheet.png"

--[[ Public API ]]--
function TouchJump:Enable()
	JumpButton.Visible = true
end

function TouchJump:Disable()
	JumpButton.Visible = false
	OnInputEnded()
end

function TouchJump:Create(parentFrame)
	if JumpButton then
		JumpButton:Destroy()
		JumpButton = nil
	end
	
	local isSmallScreen = parentFrame.AbsoluteSize.y <= 500
	local jumpButtonSize = isSmallScreen and 70 or 90
	
	JumpButton = Instance.new('ImageButton')
	JumpButton.Name = "JumpButton"
	JumpButton.Visible = false
	JumpButton.BackgroundTransparency = 1
	JumpButton.Image = TOUCH_CONTROL_SHEET
	JumpButton.ImageRectOffset = Vector2.new(176, 222)
	JumpButton.ImageRectSize = Vector2.new(174, 174)
	JumpButton.Size = UDim2.new(0, jumpButtonSize, 0, jumpButtonSize)
	JumpButton.Position = isSmallScreen and UDim2.new(1, jumpButtonSize * -2.25, 1, -jumpButtonSize - 20) or
		UDim2.new(1, jumpButtonSize * -2.75, 1, -jumpButtonSize - 120)
	
	local touchObject = nil	
	JumpButton.InputBegan:connect(function(inputObject)
		if touchObject or inputObject.UserInputType ~= Enum.UserInputType.Touch then
			return
		end
		
		touchObject = inputObject
		JumpButton.ImageRectOffset = Vector2.new(0, 222)
		MasterControl:SetIsJumping(true)
	end)
	
	OnInputEnded = function()
		touchObject = nil
		MasterControl:SetIsJumping(false)
		JumpButton.ImageRectOffset = Vector2.new(176, 222)
	end
	
	JumpButton.InputEnded:connect(function(inputObject)
		if inputObject == touchObject then
			OnInputEnded()
		end
	end)
	
	JumpButton.Parent = parentFrame
end

return TouchJump
]]></ProtectedString>
				</Properties>
			</Item>
			<Item class="ModuleScript" referent="RBX897F449FE4DD4FC9A5138C94EA70571C">
				<Properties>
					<Content name="LinkedSource"><null></null></Content>
					<string name="Name">VehicleController</string>
					<ProtectedString name="Source"><![CDATA[--[[
	// FileName: VehicleControl
	// Version 1.0
	// Written by: jmargh
	// Description: Implements in-game vehicle controls for all input devices
	
	// NOTE: This works for basic vehicles (single vehicle seat). If you use custom VehicleSeat code,
	// multiple VehicleSeats or your own implementation of a VehicleSeat this will not work.
--]]

local VehicleController = {}

local ContextActionService = game:GetService('ContextActionService')
local Players = game:GetService('Players')
local RunService = game:GetService('RunService')

local MasterControl = require(script.Parent)

while not Players.LocalPlayer do
	wait()
end
local LocalPlayer = Players.LocalPlayer
local CurrentVehicleSeat = nil
local CurrentThrottle = 0
local HumanoidSeatedCn = nil
local RenderSteppedCn = nil
local Accelerating = false
local Deccelerating = false
-- Set this to true if you want to instead use the triggers for the throttle
local useTriggersForThrottle = true
-- Also set this to true if you want the thumbstick to not affect throttle, only triggers when a gamepad is conected
local onlyTriggersForThrottle = false

local function onThrottleAccel(actionName, inputState, inputObject)
	MasterControl:AddToPlayerMovement(Vector3.new(0, 0, -CurrentThrottle))
	CurrentThrottle = (inputState == Enum.UserInputState.End or Deccelerating) and 0 or -1
	MasterControl:AddToPlayerMovement(Vector3.new(0, 0, CurrentThrottle))
	Accelerating = not (inputState == Enum.UserInputState.End)
	if (inputState == Enum.UserInputState.End) and Deccelerating then
		CurrentThrottle = 1
		MasterControl:AddToPlayerMovement(Vector3.new(0, 0, CurrentThrottle))
	end
end

local function onThrottleDeccel(actionName, inputState, inputObject)
	MasterControl:AddToPlayerMovement(Vector3.new(0, 0, -CurrentThrottle))
	CurrentThrottle = (inputState == Enum.UserInputState.End or Accelerating) and 0 or 1
	MasterControl:AddToPlayerMovement(Vector3.new(0, 0, CurrentThrottle))
	Deccelerating = not (inputState == Enum.UserInputState.End)
	if (inputState == Enum.UserInputState.End) and Accelerating then
		CurrentThrottle = -1
		MasterControl:AddToPlayerMovement(Vector3.new(0, 0, CurrentThrottle))
	end
end

local function getHumanoid()
	local character = LocalPlayer and LocalPlayer.Character
	if character then
		for _,child in pairs(character:GetChildren()) do
			if child:IsA('Humanoid') then
				return child
			end
		end
	end
end

local function getClosestFittingValue(value)
	if value > 0.5 then
		return 1
	elseif value < -0.5 then
		return -1
	end
	return 0 
end

local function onRenderStepped()
	if CurrentVehicleSeat then
		local moveValue = MasterControl:GetMoveVector()
		if game:GetService("UserInputService"):GetGamepadConnected(Enum.UserInputType.Gamepad1) and onlyTriggersForThrottle and useTriggersForThrottle then
			CurrentVehicleSeat.Throttle = -CurrentThrottle
		else
			CurrentVehicleSeat.Throttle = getClosestFittingValue(-moveValue.z)
		end
		CurrentVehicleSeat.Steer = getClosestFittingValue(moveValue.x)
	end
end

local function onSeated(active, currentSeatPart)
	if active then
		if currentSeatPart and currentSeatPart:IsA('VehicleSeat') then
			CurrentVehicleSeat = currentSeatPart
			if useTriggersForThrottle then
				ContextActionService:BindAction("throttleAccel", onThrottleAccel, false, Enum.KeyCode.ButtonR2)
				ContextActionService:BindAction("throttleDeccel", onThrottleDeccel, false, Enum.KeyCode.ButtonL2)
			end
			local success = pcall(function() RunService:BindToRenderStep("VehicleControlStep", Enum.RenderPriority.Input.Value, onRenderStepped) end)

			if not success then
				if RenderSteppedCn then return end
				RenderSteppedCn = RunService.RenderStepped:connect(onRenderStepped)
			end
		end
	else
		CurrentVehicleSeat = nil
		if useTriggersForThrottle then
			ContextActionService:UnbindAction("throttleAccel")
			ContextActionService:UnbindAction("throttleDeccel")
		end
		MasterControl:AddToPlayerMovement(Vector3.new(0, 0, -CurrentThrottle))
		CurrentThrottle = 0
		local success = pcall(function() RunService:UnbindFromRenderStep("VehicleControlStep") end)
		if not success and RenderSteppedCn then
			RenderSteppedCn:disconnect()
			RenderSteppedCn = nil
		end
	end
end

local function CharacterAdded(character)
	local humanoid = getHumanoid()
	while not humanoid do
		wait()
		humanoid = getHumanoid()
	end
	--
	if HumanoidSeatedCn then
		HumanoidSeatedCn:disconnect()
		HumanoidSeatedCn = nil
	end
	HumanoidSeatedCn = humanoid.Seated:connect(onSeated)
end

if LocalPlayer.Character then
	CharacterAdded(LocalPlayer.Character)
end
LocalPlayer.CharacterAdded:connect(CharacterAdded)

return VehicleController
]]></ProtectedString>
				</Properties>
			</Item>
		</Item>
	</Item>
</roblox>