Prompt: ----------- CLASS DECLARATION --------------

Response:
local function CreateSignal()
	local sig = {}

	local mSignaler = Instance.new('BindableEvent')

	local mArgData = nil
	local mArgDataCount = nil

	function sig:fire(...)
		mArgData = {...}
		mArgDataCount = select('#', ...)
		mSignaler:Fire()
	end

	function sig:connect(f)
		if not f then error("connect(nil)", 2) end
		return mSignaler.Event:Connect(function()
			f(unpack(mArgData, 1, mArgDataCount))
		end)
	end

	function sig:wait()
		mSignaler.Event:wait()
		if not mArgData then
			error("Missing arg data, likely due to :TweenSize/Position corrupting threadrefs.")
		end
		return unpack(mArgData, 1, mArgDataCount)
	end

	return sig
end

local function getViewportSize()
	while not workspace.CurrentCamera do
		workspace.Changed:wait()
	end

	-- ViewportSize is initally set to 1, 1 in Camera.cpp constructor.
	-- Also check against 0, 0 incase this is changed in the future.
	while workspace.CurrentCamera.ViewportSize == Vector2.new(0,0) or
		workspace.CurrentCamera.ViewportSize == Vector2.new(1,1) do
		workspace.CurrentCamera.Changed:wait()
	end

	return workspace.CurrentCamera.ViewportSize
end

local function isSmallTouchScreen()
	local viewportSize = getViewportSize()
	return UserInputService.TouchEnabled and (viewportSize.Y < 500 or viewportSize.X < 700)
end

local function isPortrait()
	local viewport = getViewportSize()
	return viewport.Y > viewport.X
end

local function isTenFootInterface()
	return tenFootInterfaceEnabled
end

local function usesSelectedObject()
	--VR does not use selected objects (in the same way as gamepad)
	if VRService.VREnabled then return false end
	--Touch does not use selected objects unless there's also a gamepad
	if UserInputService.TouchEnabled and not UserInputService.GamepadEnabled then return false end
	--PC with gamepad, console... does use selected objects
	return true
end

local function isPosOverGui(pos, gui, debug) -- does not account for rotation
	local ax, ay = gui.AbsolutePosition.x, gui.AbsolutePosition.y
	local sx, sy = gui.AbsoluteSize.x, gui.AbsoluteSize.y
	local bx, by = ax+sx, ay+sy

	return pos.x > ax and pos.x < bx and pos.y > ay and pos.y < by
end

local function isPosOverGuiWithClipping(pos, gui) -- isPosOverGui, accounts for clipping and visibility, does not account for rotation
	if not isPosOverGui(pos, gui) then
		return false
	end

	local clipping = false
	local check = gui
	while true do
		if check == nil or (not check:IsA'GuiObject' and not check:IsA'LayerCollector') then
			clipping = true
			if check and check:IsA'CoreGui' then
				clipping = false
			end
			break
		end

		if check:IsA'GuiObject' and not check.Visible then
			clipping = true
			break
		end
		if check:IsA'LayerCollector' or check.ClipsDescendants then
			if not isPosOverGui(pos, check) then
				clipping = true
				break
			end
		end

		check = check.Parent
	end

	return not clipping
end

local function areGuisIntersecting(a, b) -- does not account for rotation
	local aax, aay = a.AbsolutePosition.x, a.AbsolutePosition.y
	local asx, asy = a.AbsoluteSize.x, a.AbsoluteSize.y
	local abx, aby = aax+asx, aay+asy
	local bax, bay = b.AbsolutePosition.x, b.AbsolutePosition.y
	local bsx, bsy = b.AbsoluteSize.x, b.AbsoluteSize.y
	local bbx, bby = bax+bsx, bay+bsy

	local intersectingX = aax < bbx and abx > bax
	local intersectingY = aay < bby and aby > bay
	local intersecting = intersectingX and intersectingY

	return intersecting
end

local function isGuiVisible(gui, debug) -- true if any part of the gui is visible on the screen, considers clipping, does not account for rotation
	local clipping = false
	local check = gui
	while true do
		if check == nil or not check:IsA'GuiObject' and not check:IsA'LayerCollector' then
			clipping = true
			if check and check:IsA'CoreGui' then
				clipping = false
			end
			break
		end

		if check:IsA'GuiObject' and not check.Visible then
			clipping = true
			break
		end
		if check:IsA'LayerCollector' or check.ClipsDescendants then
			if not areGuisIntersecting(check, gui) then
				clipping = true
				break
			end
		end

		check = check.Parent
	end

	return not clipping
end

local function addHoverState(button, instance, onNormalButtonState, onHoverButtonState)
	local function onNormalButtonStateCallback()
        if button.Active then
            onNormalButtonState(instance)
        end
	end
	local function onHoverButtonStateCallback()
        if button.Active then
            onHoverButtonState(instance)
        end
	end

	button.MouseEnter:Connect(onHoverButtonStateCallback)
	button.SelectionGained:Connect(onHoverButtonStateCallback)
	button.MouseLeave:Connect(onNormalButtonStateCallback)
	button.SelectionLost:Connect(onNormalButtonStateCallback)

	onNormalButtonState(instance)
end

local function addOnResizedCallback(key, callback)
	onResizedCallbacks[key] = callback
	callback(getViewportSize(), isPortrait())
end

local gamepadSet = {
	[Enum.UserInputType.Gamepad1] = true;
	[Enum.UserInputType.Gamepad2] = true;
	[Enum.UserInputType.Gamepad3] = true;
	[Enum.UserInputType.Gamepad4] = true;
	[Enum.UserInputType.Gamepad5] = true;
	[Enum.UserInputType.Gamepad6] = true;
	[Enum.UserInputType.Gamepad7] = true;
	[Enum.UserInputType.Gamepad8] = true;
}

local function MakeDefaultButton(name, size, clickFunc, pageRef, hubRef)
	local SelectionOverrideObject = Util.Create'ImageLabel'
	{
		Image = "",
		BackgroundTransparency = 1,
	};

	local button = Util.Create'ImageButton'
	{
		Name = name .. "Button",
		Image = "rbxasset://textures/ui/Settings/MenuBarAssets/MenuButton.png",
		ScaleType = Enum.ScaleType.Slice,
		SliceCenter = Rect.new(8,6,46,44),
		AutoButtonColor = false,
		BackgroundTransparency = 1,
		Size = size,
		ZIndex = 2,
		SelectionImageObject = SelectionOverrideObject
	};

	local enabled = Util.Create'BoolValue'
	{
		Name = 'Enabled',
		Parent = button,
		Value = true
	}

	if clickFunc then
		button.MouseButton1Click:Connect(function()
			clickFunc(gamepadSet[UserInputService:GetLastInputType()] or false)
		end)
	end

	local function isPointerInput(inputObject)
		return inputObject.UserInputType == Enum.UserInputType.MouseMovement or inputObject.UserInputType == Enum.UserInputType.Touch
	end

	local rowRef = nil
	local function setRowRef(ref)
		rowRef = ref
	end

	local function selectButton()
		local hub = hubRef
		if hub == nil then
			if pageRef then
				hub = pageRef.HubRef
			end
		end

		if (hub and hub.Active) or hub == nil then
			button.Image = "rbxasset://textures/ui/Settings/MenuBarAssets/MenuButtonSelected.png"

			local scrollTo = button
			if rowRef then
				scrollTo = rowRef
			end
			if hub then
				hub:ScrollToFrame(scrollTo)
			end
		end
	end

	local function deselectButton()
		button.Image = "rbxasset://textures/ui/Settings/MenuBarAssets/MenuButton.png"
	end

	button.InputBegan:Connect(function(inputObject)
		if button.Selectable and isPointerInput(inputObject) then
			selectButton()
		end
	end)
	button.InputEnded:Connect(function(inputObject)
		if button.Selectable and GuiService.SelectedCoreObject ~= button and isPointerInput(inputObject) then
			deselectButton()
		end
	end)

	button.SelectionGained:Connect(function()
		selectButton()
	end)
	button.SelectionLost:Connect(function()
		deselectButton()
	end)

	local guiServiceCon = GuiService.Changed:Connect(function(prop)
		if prop ~= "SelectedCoreObject" then return end
		if not usesSelectedObject() then return end

		if GuiService.SelectedCoreObject == nil or GuiService.SelectedCoreObject ~= button then
			deselectButton()
			return
		end

		if button.Selectable then
			selectButton()
		end
	end)

	return button, setRowRef
end

local function MakeButton(name, text, size, clickFunc, pageRef, hubRef)
	local button, setRowRef = MakeDefaultButton(name, size, clickFunc, pageRef, hubRef)

	local textLabel = Util.Create'TextLabel'
	{
		Name = name .. "TextLabel",
		BackgroundTransparency = 1,
		BorderSizePixel = 0,
		Size = UDim2.new(1, 0, 1, -8),
		Position = UDim2.new(0,0,0,0),
		TextColor3 = Color3.fromRGB(255,255,255),
		TextYAlignment = Enum.TextYAlignment.Center,
		Font = Enum.Font.SourceSansBold,
		TextSize = 24,
		Text = text,
		TextScaled = true,
		TextWrapped = true,
		ZIndex = 2,
		Parent = button
	};
	local constraint = Instance.new("UITextSizeConstraint",textLabel)

	if isSmallTouchScreen() then
		textLabel.TextSize = 18
	elseif isTenFootInterface() then
		textLabel.TextSize = 36
	end
	constraint.MaxTextSize = textLabel.TextSize

	return button, textLabel, setRowRef
end

local function MakeImageButton(name, image, size, imageSize, clickFunc, pageRef, hubRef)
	local button, setRowRef = MakeDefaultButton(name, size, clickFunc, pageRef, hubRef)

	local imageLabel = Util.Create'ImageLabel'
	{
		Name = name .. "ImageLabel",
		BackgroundTransparency = 1,
		BorderSizePixel = 0,
		Size = imageSize,
		Position = UDim2.new(0.5, 0, 0.5, 0),
		AnchorPoint = Vector2.new(0.5, 0.5),
		Image = image,
		ZIndex = 2,
		Parent = button
	};

	return button, imageLabel, setRowRef
end

local function AddButtonRow(pageToAddTo, name, text, size, clickFunc, hubRef)
	local button, textLabel, setRowRef = MakeButton(name, text, size, clickFunc, pageToAddTo, hubRef)
	local row = Util.Create'Frame'
	{
		Name = name .. "Row",
		BackgroundTransparency = 1,
		Size = UDim2.new(1, 0, size.Y.Scale, size.Y.Offset),
		Parent = pageToAddTo.Page
	}
	button.Parent = row
	button.AnchorPoint = Vector2.new(1, 0)
	button.Position = UDim2.new(1, -20, 0, 0)
	return row, button, textLabel, setRowRef
end

local function CreateDropDown(dropDownStringTable, startPosition, settingsHub)
	-------------------- CONSTANTS ------------------------
	local DEFAULT_DROPDOWN_TEXT = "Choose One"
	local SCROLLING_FRAME_PIXEL_OFFSET = 25
	local SELECTION_TEXT_COLOR_NORMAL = Color3.fromRGB(178,178,178)
	local SELECTION_TEXT_COLOR_NORMAL_VR = Color3.fromRGB(229,229,229)
	local SELECTION_TEXT_COLOR_HIGHLIGHTED = Color3.fromRGB(255,255,255)

	-------------------- VARIABLES ------------------------
	local lastSelectedCoreObject = nil

	-------------------- SETUP ------------------------
	local this = {}
	this.CurrentIndex = nil

	local indexChangedEvent = Instance.new("BindableEvent")
	indexChangedEvent.Name = "IndexChanged"

	if type(dropDownStringTable) ~= "table" then
		error("CreateDropDown dropDownStringTable (first arg) is not a table", 2)
		return this
	end

	local indexChangedEvent = Instance.new("BindableEvent")
	indexChangedEvent.Name = "IndexChanged"

	local interactable = true
	local guid = HttpService:GenerateGUID(false)
	local dropDownButtonEnabled
	local lastStringTable = dropDownStringTable

	----------------- GUI SETUP ------------------------
	local DropDownFullscreenFrame = Util.Create'ImageButton'
	{
		Name = "DropDownFullscreenFrame",
		BackgroundTransparency = DROPDOWN_BG_TRANSPARENCY,
		BorderSizePixel = 0,
		Size = UDim2.new(1, 0, 1, 0),
		BackgroundColor3 = Color3.fromRGB(0,0,0),
		ZIndex = 10,
		Active = true,
		Visible = false,
		Selectable = false,
		AutoButtonColor = false,
		Parent = CoreGui.RobloxGui
	};

	local function onVREnabled(prop)
		if prop ~= "VREnabled" then
			return
		end
		if VRService.VREnabled then
			local Panel3D = require(CoreGui.RobloxGui.Modules.VR.Panel3D)
			DropDownFullscreenFrame.Parent = Panel3D.Get("SettingsMenu"):GetGUI()
			DropDownFullscreenFrame.BackgroundTransparency = 1
		else
			DropDownFullscreenFrame.Parent = CoreGui.RobloxGui
			DropDownFullscreenFrame.BackgroundTransparency = DROPDOWN_BG_TRANSPARENCY
		end

		--Force the gui to update, but only if onVREnabled is fired later on
		if this.UpdateDropDownList then
			this:UpdateDropDownList(lastStringTable)
		end
	end
	VRService.Changed:Connect(onVREnabled)
	onVREnabled("VREnabled")

	local DropDownSelectionFrame = Util.Create'ImageLabel'
	{
		Name = "DropDownSelectionFrame",
		Image = "rbxasset://textures/ui/Settings/MenuBarAssets/MenuButton.png",
		ScaleType = Enum.ScaleType.Slice,
		SliceCenter = Rect.new(8,6,46,44),
		BackgroundTransparency = 1,
		Size = UDim2.new(0.6, 0, 0.9, 0),
		Position = UDim2.new(0.5, 0, 0.5, 0),
		AnchorPoint = Vector2.new(0.5, 0.5),
		ZIndex = 10,
		Parent = DropDownFullscreenFrame
	};

	local DropDownScrollingFrame = Util.Create'ScrollingFrame'
	{
		Name = "DropDownScrollingFrame",
		BackgroundTransparency = 1,
		BorderSizePixel = 0,
		Size = UDim2.new(1, -20, 1, -SCROLLING_FRAME_PIXEL_OFFSET),
		Position = UDim2.new(0, 10, 0, 10),
		ZIndex = 10,
		Parent = DropDownSelectionFrame
	};

	local guiServiceChangeCon = nil
	local active = false
	local hideDropDownSelection = function(name, inputState)
		if name ~= nil and inputState ~= Enum.UserInputState.Begin then return end
		this.DropDownFrame.Selectable = interactable

		--Make sure to set the hub to Active again so selecting the
		--dropdown button will highlight it
		settingsHub:SetActive(true)

		if DropDownFullscreenFrame.Visible and usesSelectedObject() then
			GuiService.SelectedCoreObject = lastSelectedCoreObject
		end
		DropDownFullscreenFrame.Visible = false
		if guiServiceChangeCon then guiServiceChangeCon:Disconnect() end
		ContextActionService:UnbindAction(guid .. "Action")
		ContextActionService:UnbindAction(guid .. "FreezeAction")

		dropDownButtonEnabled.Value = interactable
		active = false

		if VRService.VREnabled then
			local Panel3D = require(CoreGui.RobloxGui.Modules.VR.Panel3D)
			Panel3D.Get("SettingsMenu"):SetSubpanelDepth(DropDownFullscreenFrame, 0)
		end
	end
	local noOpFunc = function() end

	local DropDownFrameClicked = function()
		if not interactable then return end

		this.DropDownFrame.Selectable = false
		active = true

		DropDownFullscreenFrame.Visible = true
		if VRService.VREnabled then
			local Panel3D = require(CoreGui.RobloxGui.Modules.VR.Panel3D)
			Panel3D.Get("SettingsMenu"):SetSubpanelDepth(DropDownFullscreenFrame, 0.5)
		end

		lastSelectedCoreObject = this.DropDownFrame
		if this.CurrentIndex and this.CurrentIndex > 0 then
			GuiService.SelectedCoreObject = this.Selections[this.CurrentIndex]
		end

		guiServiceChangeCon = GuiService:GetPropertyChangedSignal("SelectedCoreObject"):Connect(function()
			for i = 1, #this.Selections do
				if GuiService.SelectedCoreObject == this.Selections[i] then
					this.Selections[i].TextColor3 = SELECTION_TEXT_COLOR_HIGHLIGHTED
				else
					this.Selections[i].TextColor3 = VRService.VREnabled and SELECTION_TEXT_COLOR_NORMAL_VR or SELECTION_TEXT_COLOR_NORMAL
				end
			end
		end)

		ContextActionService:BindActionAtPriority(guid .. "FreezeAction", noOpFunc, false, Enum.ContextActionPriority.High.Value, Enum.UserInputType.Keyboard, Enum.UserInputType.Gamepad1)
		ContextActionService:BindActionAtPriority(guid .. "Action", hideDropDownSelection, false, Enum.ContextActionPriority.High.Value, Enum.KeyCode.ButtonB, Enum.KeyCode.Escape)

		settingsHub:SetActive(false)

		dropDownButtonEnabled.Value = false
	end

	local dropDownFrameSize = UDim2.new(0.6, 0, 0, 50)
	this.DropDownFrame = MakeButton("DropDownFrame", DEFAULT_DROPDOWN_TEXT, dropDownFrameSize, DropDownFrameClicked, nil, settingsHub)
	this.DropDownFrame.Position = UDim2.new(1, 0, 0.5, 0)
	this.DropDownFrame.AnchorPoint = Vector2.new(1, 0.5)

	dropDownButtonEnabled = this.DropDownFrame.Enabled
	local selectedTextLabel = this.DropDownFrame.DropDownFrameTextLabel
	selectedTextLabel.Position = UDim2.new(0, 15, 0, 0)
	selectedTextLabel.Size = UDim2.new(1, -50, 1, -8)
	selectedTextLabel.ClipsDescendants = true
	selectedTextLabel.TextXAlignment = Enum.TextXAlignment.Left
	local dropDownImage = Util.Create'ImageLabel'
	{
		Name = "DropDownImage",
		Image = "rbxasset://textures/ui/Settings/DropDown/DropDown.png",
		BackgroundTransparency = 1,
		AnchorPoint = Vector2.new(1, 0.5),
		Size = UDim2.new(0,15,0,10),
		Position = UDim2.new(1,-12,0.5,0),
		ZIndex = 2,
		Parent = this.DropDownFrame
	};
	this.DropDownImage = dropDownImage

	---------------------- FUNCTIONS -----------------------------------
	local function setSelection(index)
		local shouldFireChanged = false
		for i, selectionLabel in pairs(this.Selections) do
			if i == index then
				selectedTextLabel.Text = selectionLabel.Text
				this.CurrentIndex = i

				shouldFireChanged = true
			end
		end

		if shouldFireChanged then
			indexChangedEvent:Fire(index)
		end
	end

	local function setSelectionByValue(value)
		local shouldFireChanged = false
		for i, selectionLabel in pairs(this.Selections) do
			if selectionLabel.Text == value then
				selectedTextLabel.Text = selectionLabel.Text
				this.CurrentIndex = i

				shouldFireChanged = true
			end
		end

		if shouldFireChanged then
			indexChangedEvent:Fire(this.CurrentIndex)
		end
		return shouldFireChanged
	end

	local enterIsDown = false
	local function processInput(input)
		if input.UserInputState == Enum.UserInputState.Begin then
			if input.KeyCode == Enum.KeyCode.Return then
				if GuiService.SelectedCoreObject == this.DropDownFrame or this.SelectionInfo and this.SelectionInfo[GuiService.SelectedCoreObject] then
					enterIsDown = true
				end
			end
		elseif input.UserInputState == Enum.UserInputState.End then
			if input.KeyCode == Enum.KeyCode.Return and enterIsDown then
				enterIsDown = false
				if GuiService.SelectedCoreObject == this.DropDownFrame then
					DropDownFrameClicked()
				elseif this.SelectionInfo and this.SelectionInfo[GuiService.SelectedCoreObject] then
					local info = this.SelectionInfo[GuiService.SelectedCoreObject]
					info.Clicked()
				end
			end
		end
	end

	local function setIsFaded(isFaded)
		if isFaded then
			this.DropDownFrame.DropDownFrameTextLabel.TextTransparency = 0.5
			this.DropDownFrame.ImageTransparency = 0.5
			this.DropDownImage.ImageTransparency = 0.5
		else
			this.DropDownFrame.DropDownFrameTextLabel.TextTransparency = 0
			this.DropDownFrame.ImageTransparency = 0
			this.DropDownImage.ImageTransparency = 0
		end
	end

	--------------------- PUBLIC FACING FUNCTIONS -----------------------
	this.IndexChanged = indexChangedEvent.Event

	function this:SetSelectionIndex(newIndex)
		setSelection(newIndex)
	end

	function this:SetSelectionByValue(value)
		return setSelectionByValue(value)
	end

	function this:ResetSelectionIndex()
		this.CurrentIndex = nil
		selectedTextLabel.Text = DEFAULT_DROPDOWN_TEXT
		hideDropDownSelection()
	end

	function this:GetSelectedIndex()
		return this.CurrentIndex
	end

	function this:SetZIndex(newZIndex)
		this.DropDownFrame.ZIndex = newZIndex
		dropDownImage.ZIndex = newZIndex
		selectedTextLabel.ZIndex = newZIndex
	end

	function this:SetInteractable(value)
		interactable = value
		this.DropDownFrame.Selectable = interactable

		if not interactable then
			hideDropDownSelection()
			setIsFaded(VRService.VREnabled)
			if not VRService.VREnabled then
				this:SetZIndex(1)
			end
		else
			setIsFaded(false)
			if not VRService.VREnabled then
				this:SetZIndex(2)
			end
		end

		dropDownButtonEnabled.Value = value and not active
	end

	function this:UpdateDropDownList(dropDownStringTable)
		lastStringTable = dropDownStringTable

		if this.Selections then
			for i = 1, #this.Selections do
				this.Selections[i]:Destroy()
			end
		end

		this.Selections = {}
		this.SelectionInfo = {}

		local vrEnabled = VRService.VREnabled
		local font = vrEnabled and Enum.Font.SourceSansBold or Enum.Font.SourceSans
		local textSize = vrEnabled and 36 or 24

		local itemHeight = vrEnabled and 70 or 50
		local itemSpacing = itemHeight + 1

		local dropDownWidth = vrEnabled and 600 or 400

		for i,v in pairs(dropDownStringTable) do
			local SelectionOverrideObject =	Util.Create'Frame'
			{
				BackgroundTransparency = 0.7,
				BorderSizePixel = 0,
				Size = UDim2.new(1, 0, 1, 0)
			};

			local nextSelection = Util.Create'TextButton'
			{
				Name = "Selection" .. tostring(i),
				BackgroundTransparency = 1,
				BorderSizePixel = 0,
				AutoButtonColor = false,
				Size = UDim2.new(1, -28, 0, itemHeight),
				Position = UDim2.new(0,14,0, (i - 1) * itemSpacing),
				TextColor3 = VRService.VREnabled and SELECTION_TEXT_COLOR_NORMAL_VR or SELECTION_TEXT_COLOR_NORMAL,
				Font = font,
				TextSize = textSize,
				Text = v,
				ZIndex = 10,
				SelectionImageObject = SelectionOverrideObject,
				Parent = DropDownScrollingFrame
			};

			if i == startPosition then
				this.CurrentIndex = i
				selectedTextLabel.Text = v
				nextSelection.TextColor3 = SELECTION_TEXT_COLOR_HIGHLIGHTED
			elseif not startPosition and i == 1 then
				nextSelection.TextColor3 = SELECTION_TEXT_COLOR_HIGHLIGHTED
			end

			local clicked = function()
				selectedTextLabel.Text = nextSelection.Text
				hideDropDownSelection()
				this.CurrentIndex = i
				indexChangedEvent:Fire(i)
			end

			nextSelection.MouseButton1Click:Connect(clicked)

			nextSelection.MouseEnter:Connect(function()
				if usesSelectedObject() then
					GuiService.SelectedCoreObject = nextSelection
				end
			end)

			this.Selections[i] = nextSelection
			this.SelectionInfo[nextSelection] = {Clicked = clicked}
		end

		GuiService:RemoveSelectionGroup(guid)
		GuiService:AddSelectionTuple(guid, unpack(this.Selections))

		DropDownScrollingFrame.CanvasSize = UDim2.new(1,-20,0,#dropDownStringTable * itemSpacing)

		local function updateDropDownSize()
			if DropDownScrollingFrame.CanvasSize.Y.Offset < (DropDownFullscreenFrame.AbsoluteSize.Y - 10) then
				DropDownSelectionFrame.Size = UDim2.new(0, dropDownWidth,
														0,DropDownScrollingFrame.CanvasSize.Y.Offset + SCROLLING_FRAME_PIXEL_OFFSET)
			else
				DropDownSelectionFrame.Size = UDim2.new(0, dropDownWidth, 0.9, 0)
			end
		end

		DropDownFullscreenFrame.Changed:Connect(function(prop)
			if prop ~= "AbsoluteSize" then return end
			updateDropDownSize()
		end)

		updateDropDownSize()
	end

	----------------------- CONNECTIONS/SETUP --------------------------------
	this:UpdateDropDownList(dropDownStringTable)

	DropDownFullscreenFrame.MouseButton1Click:Connect(hideDropDownSelection)

	settingsHub.PoppedMenu:Connect(function(poppedMenu)
		if poppedMenu == DropDownFullscreenFrame then
			hideDropDownSelection()
		end
	end)

	return this
end

local function CreateSelector(selectionStringTable, startPosition)

	-------------------- VARIABLES ------------------------
	local lastInputDirection = 0
	local TweenTime = 0.15

	-------------------- SETUP ------------------------
	local this = {}
	this.HubRef = nil

	if type(selectionStringTable) ~= "table" then
		error("CreateSelector selectionStringTable (first arg) is not a table", 2)
		return this
	end

	local indexChangedEvent = Instance.new("BindableEvent")
	indexChangedEvent.Name = "IndexChanged"

	local interactable = true

	this.CurrentIndex = 0

	----------------- GUI SETUP ------------------------
	this.SelectorFrame = Util.Create'ImageButton'
	{
		Name = "Selector",
		Image = "",
		AutoButtonColor = false,
		NextSelectionLeft = this.SelectorFrame,
		NextSelectionRight = this.SelectorFrame,
		BackgroundTransparency = 1,
		Size = UDim2.new(0.6,0,0,50),
		Position = UDim2.new(1, 0, 0.5, 0),
		AnchorPoint = Vector2.new(1, 0.5),
		ZIndex = 2,
		SelectionImageObject = noSelectionObject
	};

	local leftButton = Util.Create'ImageButton'
	{
		Name = "LeftButton",
		BackgroundTransparency = 1,
		AnchorPoint = Vector2.new(0, 0.5),
		Position = UDim2.new(0,0,0.5,0),
		Size =  UDim2.new(0,50,0,50),
		Image =  "",
		ZIndex = 3,
		Selectable = false,
		SelectionImageObject = noSelectionObject,
		Parent = this.SelectorFrame
	};
	local rightButton = Util.Create'ImageButton'
	{
		Name = "RightButton",
		BackgroundTransparency = 1,
		AnchorPoint = Vector2.new(1, 0.5),
		Position = UDim2.new(1,0,0.5,0),
		Size =  UDim2.new(0,50,0,50),
		Image =  "",
		ZIndex = 3,
		Selectable = false,
		SelectionImageObject = noSelectionObject,
		Parent = this.SelectorFrame
	};

	local leftButtonImage = Util.Create'ImageLabel'
	{
		Name = "LeftButton",
		BackgroundTransparency = 1,
		AnchorPoint = Vector2.new(0.5, 0.5),
		Position = UDim2.new(0.5,0,0.5,0),
		Size =  UDim2.new(0,18,0,30),
		Image =  "rbxasset://textures/ui/Settings/Slider/Left.png",
		ImageColor3 = ARROW_COLOR,
		ZIndex = 4,
		Parent = leftButton
	};
	local rightButtonImage = Util.Create'ImageLabel'
	{
		Name = "RightButton",
		BackgroundTransparency = 1,
		AnchorPoint = Vector2.new(0.5, 0.5),
		Position = UDim2.new(0.5,0,0.5,0),
		Size =  UDim2.new(0,18,0,30),
		Image =  "rbxasset://textures/ui/Settings/Slider/Right.png",
		ImageColor3 = ARROW_COLOR,
		ZIndex = 4,
		Parent = rightButton
	};
	if not UserInputService.TouchEnabled then
		local applyNormal, applyHover =
			function(instance) instance.ImageColor3 = ARROW_COLOR end,
			function(instance) instance.ImageColor3 = ARROW_COLOR_HOVER end
		addHoverState(leftButton, leftButtonImage, applyNormal, applyHover)
		addHoverState(rightButton, rightButtonImage, applyNormal, applyHover)
	end

	this.Selections = {}
	local isSelectionLabelVisible = {}
	local isAutoSelectButton = {}

	local autoSelectButton = Util.Create'ImageButton'{
		Name = 'AutoSelectButton',
		BackgroundTransparency = 1,
		Image = '',
		Position = UDim2.new(0, leftButton.Size.X.Offset, 0, 0),
		Size = UDim2.new(1, leftButton.Size.X.Offset * -2, 1, 0),
		Parent = this.SelectorFrame,
		ZIndex = 2,
		SelectionImageObject = noSelectionObject
	}
	autoSelectButton.MouseButton1Click:Connect(function()
		if not interactable then return end
		if #this.Selections <= 1 then return end
		local newIndex = this.CurrentIndex + 1
		if newIndex > #this.Selections then
			newIndex = 1
		end
		this:SetSelectionIndex(newIndex)
		if usesSelectedObject() then
			GuiService.SelectedCoreObject = this.SelectorFrame
		end
	end)
	isAutoSelectButton[autoSelectButton] = true

	---------------------- FUNCTIONS -----------------------------------
	local function setSelection(index, direction)
		for i, selectionLabel in pairs(this.Selections) do
			local isSelected = (i == index)

			local leftButtonUDim = UDim2.new(0,leftButton.Size.X.Offset,0,0)
			local tweenPos = UDim2.new(0,leftButton.Size.X.Offset * direction * 3,0,0)

			if isSelectionLabelVisible[selectionLabel] then
				tweenPos = UDim2.new(0,leftButton.Size.X.Offset * -direction * 3,0,0)
			end

			if tweenPos.X.Offset < 0 then
				tweenPos = UDim2.new(0,tweenPos.X.Offset + (selectionLabel.AbsoluteSize.X/4),0,0)
			end

			if isSelected then
				isSelectionLabelVisible[selectionLabel] = true
				selectionLabel.Position = tweenPos
				selectionLabel.Visible = true
				PropertyTweener(selectionLabel, "TextTransparency", 1, 0, TweenTime * 1.1, EaseOutQuad)
				if selectionLabel:IsDescendantOf(game) then
					selectionLabel:TweenPosition(leftButtonUDim, Enum.EasingDirection.In, Enum.EasingStyle.Quad, TweenTime, true)
				else
					selectionLabel.Position = leftButtonUDim
				end
				this.CurrentIndex = i
				indexChangedEvent:Fire(index)
			elseif isSelectionLabelVisible[selectionLabel] then
				isSelectionLabelVisible[selectionLabel] = false
				PropertyTweener(selectionLabel, "TextTransparency", 0, 1, TweenTime * 1.1, EaseOutQuad)
				if selectionLabel:IsDescendantOf(game) then
					selectionLabel:TweenPosition(tweenPos, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, TweenTime * 0.9, true)
				else
					selectionLabel.Position = UDim2.new(tweenPos)
				end
			end
		end
	end

	local function stepFunc(inputObject, step)
		if not interactable then return end

		if inputObject ~= nil and inputObject.UserInputType ~= Enum.UserInputType.MouseButton1 and
			inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 and inputObject.UserInputType ~= Enum.UserInputType.Gamepad2 and
			inputObject.UserInputType ~= Enum.UserInputType.Gamepad3 and inputObject.UserInputType ~= Enum.UserInputType.Gamepad4 and
			inputObject.UserInputType ~= Enum.UserInputType.Keyboard then return end

		if usesSelectedObject() then
			GuiService.SelectedCoreObject = this.SelectorFrame
		end

		local newIndex = step + this.CurrentIndex

		local direction = 0
		if newIndex > this.CurrentIndex then
			direction = 1
		else
			direction = -1
		end

		if newIndex > #this.Selections then
			newIndex = 1
		elseif newIndex < 1 then
			newIndex = #this.Selections
		end

		setSelection(newIndex, direction)
	end

	local guiServiceCon = nil
	local function connectToGuiService()
		guiServiceCon = GuiService:GetPropertyChangedSignal("SelectedCoreObject"):Connect(function()
			if #this.Selections <= 0 then
				return
			end

			if GuiService.SelectedCoreObject == this.SelectorFrame then
				this.Selections[this.CurrentIndex].TextTransparency = 0
			else
				if GuiService.SelectedCoreObject ~= nil and isAutoSelectButton[GuiService.SelectedCoreObject] then
					if VRService.VREnabled then
						this.Selections[this.CurrentIndex].TextTransparency = 0
					else
						GuiService.SelectedCoreObject = this.SelectorFrame
					end
				else
					this.Selections[this.CurrentIndex].TextTransparency = 0.5
				end
			end
		end)
	end

	--------------------- PUBLIC FACING FUNCTIONS -----------------------
	this.IndexChanged = indexChangedEvent.Event

	function this:SetSelectionIndex(newIndex)
		setSelection(newIndex, 1)
	end

	function this:GetSelectedIndex()
		return this.CurrentIndex
	end

	function this:SetZIndex(newZIndex)
		leftButton.ZIndex = newZIndex
		rightButton.ZIndex = newZIndex
		leftButtonImage.ZIndex = newZIndex
		rightButtonImage.ZIndex = newZIndex

		for i = 1, #this.Selections do
			this.Selections[i].ZIndex = newZIndex
		end
	end

	function this:SetInteractable(value)
		interactable = value
		this.SelectorFrame.Selectable = interactable

		leftButton.Active = interactable
		rightButton.Active = interactable

		if not interactable then
			for i, selectionLabel in pairs(this.Selections) do
				selectionLabel.TextColor3 = Color3.fromRGB(49, 49, 49)
			end
			leftButtonImage.ImageColor3 = ARROW_COLOR_INACTIVE
            rightButtonImage.ImageColor3 = ARROW_COLOR_INACTIVE
		else
			for i, selectionLabel in pairs(this.Selections) do
				selectionLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
			end
			leftButtonImage.ImageColor3 = ARROW_COLOR
            rightButtonImage.ImageColor3 = ARROW_COLOR
		end
	end

	function this:UpdateOptions(selectionStringTable)
		for i,v in pairs(this.Selections) do
			v:Destroy()
		end

		isSelectionLabelVisible = {}
		this.Selections = {}

		for i,v in pairs(selectionStringTable) do
			local nextSelection = Util.Create'TextLabel'
			{
				Name = "Selection" .. tostring(i),
				BackgroundTransparency = 1,
				BorderSizePixel = 0,
				Size = UDim2.new(1,leftButton.Size.X.Offset * -2, 1, 0),
				Position = UDim2.new(1,0,0,0),
				TextColor3 = Color3.fromRGB(255, 255, 255),
				TextYAlignment = Enum.TextYAlignment.Center,
				TextTransparency = 0.5,
				Font = Enum.Font.SourceSans,
				TextSize = 24,
				Text = v,
				ZIndex = 2,
				Visible = false,
				Parent = this.SelectorFrame
			};
			if isTenFootInterface() then
				nextSelection.TextSize = 36
			end

			if i == startPosition then
				this.CurrentIndex = i
				nextSelection.Position = UDim2.new(0,leftButton.Size.X.Offset,0,0)
				nextSelection.Visible = true

				isSelectionLabelVisible[nextSelection] = true
			else
				isSelectionLabelVisible[nextSelection] = false
			end

			this.Selections[i] = nextSelection
		end

		local hasMoreThanOneSelection = #this.Selections > 1
		leftButton.Visible = hasMoreThanOneSelection
		rightButton.Visible = hasMoreThanOneSelection
	end

	--------------------- SETUP -----------------------
	local function onVREnabled(prop)
		if prop ~= "VREnabled" then
			return
		end
		local vrEnabled = VRService.VREnabled
		leftButton.Selectable = vrEnabled
		rightButton.Selectable = vrEnabled
		autoSelectButton.Selectable = vrEnabled
	end
	VRService.Changed:Connect(onVREnabled)
	onVREnabled("VREnabled")

	leftButton.InputBegan:Connect(function(inputObject)
		if inputObject.UserInputType == Enum.UserInputType.Touch then
			stepFunc(nil, -1)
		end
	end)
	leftButton.MouseButton1Click:Connect(function()
		if not UserInputService.TouchEnabled then
			stepFunc(nil, -1)
		end
	end)
	rightButton.InputBegan:Connect(function(inputObject)
		if inputObject.UserInputType == Enum.UserInputType.Touch then
			stepFunc(nil, 1)
		end
	end)
	rightButton.MouseButton1Click:Connect(function()
		if not UserInputService.TouchEnabled then
			stepFunc(nil, 1)
		end
	end)

	local isInTree = true
	this:UpdateOptions(selectionStringTable)

	UserInputService.InputBegan:Connect(function(inputObject)
		if not interactable then return end
		if not isInTree then return end

		if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 and inputObject.UserInputType ~= Enum.UserInputType.Keyboard then return end
		if GuiService.SelectedCoreObject ~= this.SelectorFrame then return end

		if inputObject.KeyCode == Enum.KeyCode.DPadLeft or inputObject.KeyCode == Enum.KeyCode.Left or inputObject.KeyCode == Enum.KeyCode.A then
			stepFunc(inputObject, -1)
		elseif inputObject.KeyCode == Enum.KeyCode.DPadRight or inputObject.KeyCode == Enum.KeyCode.Right or inputObject.KeyCode == Enum.KeyCode.D then
			stepFunc(inputObject, 1)
		end
	end)

	UserInputService.InputChanged:Connect(function(inputObject)
		if not interactable then return end
		if not isInTree then lastInputDirection = 0 return end

		if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 then return end

		local selected = GuiService.SelectedCoreObject
		if not selected or not selected:IsDescendantOf(this.SelectorFrame.Parent) then return end

		if inputObject.KeyCode ~= Enum.KeyCode.Thumbstick1 then return end

		if inputObject.Position.X > CONTROLLER_THUMBSTICK_DEADZONE and inputObject.Delta.X > 0 and lastInputDirection ~= 1 then
			lastInputDirection = 1
			stepFunc(inputObject, lastInputDirection)
		elseif inputObject.Position.X < -CONTROLLER_THUMBSTICK_DEADZONE and inputObject.Delta.X < 0 and lastInputDirection ~= -1 then
			lastInputDirection = -1
			stepFunc(inputObject, lastInputDirection)
		elseif math.abs(inputObject.Position.X) < CONTROLLER_THUMBSTICK_DEADZONE then
			lastInputDirection = 0
		end
	end)

	this.SelectorFrame.AncestryChanged:Connect(function(child, parent)
		isInTree = parent
		if not isInTree then
			if guiServiceCon then guiServiceCon:Disconnect() end
		else
			connectToGuiService()
		end
	end)

	local function onResized(viewportSize, portrait)
		local textSize = 0
		if portrait then
			textSize = 16
		else
			textSize = isTenFootInterface() and 36 or 24
		end

		for i, selection in pairs(this.Selections) do
			selection.TextSize = textSize
		end
	end
	addOnResizedCallback(this.SelectorFrame, onResized)

	connectToGuiService()

	return this
end

local function ShowAlert(alertMessage, okButtonText, settingsHub, okPressedFunc, hasBackground)
	local parent = CoreGui.RobloxGui
	if parent:FindFirstChild("AlertViewFullScreen") then return end

	--Declare AlertViewBacking so onVREnabled can take it as an upvalue
	local AlertViewBacking = nil

	--Handle VR toggle while alert is open
	--Future consideration: maybe rebuild gui when VR toggles mid-game; right now only subpaneling is handled rather than visual style
	local function onVREnabled(prop)
		if prop ~= "VREnabled" then return end
		local Panel3D, settingsPanel = nil, nil
		if VRService.VREnabled then
			Panel3D = require(CoreGui.RobloxGui.Modules.VR.Panel3D)
			settingsPanel = Panel3D.Get("SettingsMenu")
			parent = settingsPanel:GetGUI()
		else
			parent = CoreGui.RobloxGui
		end
		if AlertViewBacking and AlertViewBacking.Parent ~= nil then
			AlertViewBacking.Parent = parent
			if VRService.VREnabled then
				settingsPanel:SetSubpanelDepth(AlertViewBacking, 0.5)
			end
		end
	end
	local vrEnabledConn = VRService.Changed:Connect(onVREnabled)

	local NON_SELECTED_TEXT_COLOR = Color3.fromRGB(59, 166, 241)
	local SELECTED_TEXT_COLOR = Color3.fromRGB(255, 255, 255)

	AlertViewBacking = Util.Create'ImageLabel'
	{
		Name = "AlertViewBacking",
		Image = "rbxasset://textures/ui/Settings/MenuBarAssets/MenuButton.png",
		ScaleType = Enum.ScaleType.Slice,
		SliceCenter = Rect.new(8,6,46,44),
		BackgroundTransparency = 1,

		ImageTransparency = 1,
		Size = UDim2.new(0, 400, 0, 350),
		Position = UDim2.new(0.5, -200, 0.5, -175),
		ZIndex = 9,
		Parent = parent
	};
	onVREnabled("VREnabled")
	if hasBackground or VRService.VREnabled then
		AlertViewBacking.ImageTransparency = 0
	else
		AlertViewBacking.Size = UDim2.new(0.8, 0, 0, 350)
		AlertViewBacking.Position = UDim2.new(0.1, 0, 0.1, 0)
	end

	if CoreGui.RobloxGui.AbsoluteSize.Y <= AlertViewBacking.Size.Y.Offset then
		AlertViewBacking.Size = UDim2.new(AlertViewBacking.Size.X.Scale, AlertViewBacking.Size.X.Offset,
											AlertViewBacking.Size.Y.Scale, CoreGui.RobloxGui.AbsoluteSize.Y)
		AlertViewBacking.Position = UDim2.new(AlertViewBacking.Position.X.Scale, -AlertViewBacking.Size.X.Offset/2, 0.5, -AlertViewBacking.Size.Y.Offset/2)
	end

	local AlertViewText = Util.Create'TextLabel'
	{
		Name = "AlertViewText",
		BackgroundTransparency = 1,
		Size = UDim2.new(0.95, 0, 0.6, 0),
		Position = UDim2.new(0.025, 0, 0.05, 0),
		Font = Enum.Font.SourceSansBold,
		TextSize = 36,
		Text = alertMessage,
		TextWrapped = true,
		TextColor3 = Color3.fromRGB(255, 255, 255),
		TextXAlignment = Enum.TextXAlignment.Center,
		TextYAlignment = Enum.TextYAlignment.Center,
		ZIndex = 10,
		Parent = AlertViewBacking
	};

	local SelectionOverrideObject = Util.Create'ImageLabel'
	{
		Image = "",
		BackgroundTransparency = 1
	};

	local removeId = HttpService:GenerateGUID(false)

	local destroyAlert = function(actionName, inputState)
		if VRService.VREnabled and (inputState == Enum.UserInputState.Begin or inputState == Enum.UserInputState.Cancel) then
			return
		end
		if not AlertViewBacking then
			return
		end
		if VRService.VREnabled then
			local Panel3D = require(CoreGui.RobloxGui.Modules.VR.Panel3D)
			Panel3D.Get("SettingsMenu"):SetSubpanelDepth(AlertViewBacking, 0)
		end
		AlertViewBacking:Destroy()
		AlertViewBacking = nil
		if okPressedFunc then
			okPressedFunc()
		end
		ContextActionService:UnbindAction(removeId)
		GuiService.SelectedCoreObject = nil
		if settingsHub then
			settingsHub:ShowBar()
		end
		if vrEnabledConn then
			vrEnabledConn:Disconnect()
		end
	end

	local AlertViewButtonSize = UDim2.new(1, -20, 0, 60)
	local AlertViewButtonPosition = UDim2.new(0, 10, 0.65, 0)
	if not hasBackground then
		AlertViewButtonSize = UDim2.new(0, 200, 0, 50)
		AlertViewButtonPosition = UDim2.new(0.5, -100, 0.65, 0)
	end

	local AlertViewButton, AlertViewText = MakeButton("AlertViewButton", okButtonText, AlertViewButtonSize, destroyAlert)
	AlertViewButton.Position = AlertViewButtonPosition
	AlertViewButton.NextSelectionLeft = AlertViewButton
	AlertViewButton.NextSelectionRight = AlertViewButton
	AlertViewButton.NextSelectionUp = AlertViewButton
	AlertViewButton.NextSelectionDown = AlertViewButton
	AlertViewButton.ZIndex = 9
	AlertViewText.ZIndex = AlertViewButton.ZIndex
	AlertViewButton.Parent = AlertViewBacking

	if usesSelectedObject() then
		GuiService.SelectedCoreObject = AlertViewButton
	end

	GuiService.SelectedCoreObject = AlertViewButton

	ContextActionService:BindActionAtPriority(removeId, destroyAlert, false, Enum.ContextActionPriority.High.Value, Enum.KeyCode.Escape, Enum.KeyCode.ButtonB, Enum.KeyCode.ButtonA)

	if settingsHub and not VRService.VREnabled then
		settingsHub:HideBar()
		settingsHub.Pages.CurrentPage:Hide(1, 1)
	end
end

local function CreateNewSlider(numOfSteps, startStep, minStep)
	-------------------- SETUP ------------------------
	local this = {}

	local spacing = 4
	local initialSpacing = 8
	local steps = tonumber(numOfSteps)
	local currentStep = startStep

	local lastInputDirection = 0
	local timeAtLastInput = nil

	local interactable = true

	local renderStepBindName = HttpService:GenerateGUID(false)

	-- this is done to prevent using these values below (trying to keep the variables consistent)
	numOfSteps = ""
	startStep = ""

	if steps <= 0 then
		error("CreateNewSlider failed because numOfSteps (first arg) is 0 or negative, please supply a positive integer", 2)
		return
	end

	local valueChangedEvent = Instance.new("BindableEvent")
	valueChangedEvent.Name = "ValueChanged"

	----------------- GUI SETUP ------------------------
	this.SliderFrame = Util.Create'ImageButton'
	{
		Name = "Slider",
		Image = "",
		AutoButtonColor = false,
		NextSelectionLeft = this.SliderFrame,
		NextSelectionRight = this.SliderFrame,
		BackgroundTransparency = 1,
		Size = UDim2.new(0.6, 0, 0, 50),
		Position = UDim2.new(1, 0, 0.5, 0),
		AnchorPoint = Vector2.new(1, 0.5),
		SelectionImageObject = noSelectionObject,
		ZIndex = 2
	};

	this.StepsContainer = Util.Create "Frame"
	{
		Name = "StepsContainer",
		Position = UDim2.new(0.5, 0, 0.5, 0),
		Size = UDim2.new(1, -100, 1, 0),
		AnchorPoint = Vector2.new(0.5, 0.5),
		BackgroundTransparency = 1,
		Parent = this.SliderFrame,
	}

	local leftButton = Util.Create'ImageButton'
	{
		Name = "LeftButton",
		BackgroundTransparency = 1,
		AnchorPoint = Vector2.new(0, 0.5),
		Position = UDim2.new(0,0,0.5,0),
		Size =  UDim2.new(0,50,0,50),
		Image =  "",
		ZIndex = 3,
		Selectable = false,
		SelectionImageObject = noSelectionObject,
		Active = true,
		Parent = this.SliderFrame
	};
	local rightButton = Util.Create'ImageButton'
	{
		Name = "RightButton",
		BackgroundTransparency = 1,
		AnchorPoint = Vector2.new(1, 0.5),
		Position = UDim2.new(1,0,0.5,0),
		Size =  UDim2.new(0,50,0,50),
		Image =  "",
		ZIndex = 3,
		Selectable = false,
		SelectionImageObject = noSelectionObject,
		Active = true,
		Parent = this.SliderFrame
	};

	local leftButtonImage = Util.Create'ImageLabel'
	{
		Name = "LeftButton",
		BackgroundTransparency = 1,
		AnchorPoint = Vector2.new(0.5, 0.5),
		Position = UDim2.new(0.5,0,0.5,0),
		Size =  UDim2.new(0,30,0,30),
		Image =  "rbxasset://textures/ui/Settings/Slider/Less.png",
		ZIndex = 4,
		Parent = leftButton,
		ImageColor3 = UserInputService.TouchEnabled and ARROW_COLOR_TOUCH or ARROW_COLOR
	};
	local rightButtonImage = Util.Create'ImageLabel'
	{
		Name = "RightButton",
		BackgroundTransparency = 1,
		AnchorPoint = Vector2.new(0.5, 0.5),
		Position = UDim2.new(0.5,0,0.5,0),
		Size =  UDim2.new(0,30,0,30),
		Image =  "rbxasset://textures/ui/Settings/Slider/More.png",
		ZIndex = 4,
		Parent = rightButton,
		ImageColor3 = UserInputService.TouchEnabled and ARROW_COLOR_TOUCH or ARROW_COLOR
	};
	if not UserInputService.TouchEnabled then
		local onNormalButtonState, onHoverButtonState =
			function(instance) instance.ImageColor3 = ARROW_COLOR end,
			function(instance) instance.ImageColor3 = ARROW_COLOR_HOVER end

		addHoverState(leftButton, leftButtonImage, onNormalButtonState, onHoverButtonState)
		addHoverState(rightButton, rightButtonImage, onNormalButtonState, onHoverButtonState)
	end

	this.Steps = {}
	local stepXSize = 35
	if isSmallTouchScreen() then
		stepXSize = 25
	end

	local stepXScale = 1 / steps
	stepXSize = 0

	for i = 1, steps do
		local nextStep = Util.Create'ImageButton'
		{
			Name = "Step" .. tostring(i),
			BackgroundColor3 = SELECTED_COLOR,
			BackgroundTransparency = 0.36,
			BorderSizePixel = 0,
			AutoButtonColor = false,
			Active = false,
			AnchorPoint = Vector2.new(0, 0.5),
			Position = UDim2.new((i - 1) * stepXScale, spacing / 2, 0.5, 0),
			Size =  UDim2.new(stepXScale,-spacing, 24 / 50, 0),
			Image =  "",
			ZIndex = 3,
			Selectable = false,
			ImageTransparency = 0.36,
			Parent = this.StepsContainer,
			SelectionImageObject = noSelectionObject
		};

		if i > currentStep then
			nextStep.BackgroundColor3 = NON_SELECTED_COLOR
		end

		if i == 1 or i == steps then
			nextStep.BackgroundTransparency = 1
			nextStep.ScaleType = Enum.ScaleType.Slice
			nextStep.SliceCenter = Rect.new(3,3,32,21)

			if i <= currentStep then
				if i == 1 then
					nextStep.Image = SELECTED_LEFT_IMAGE
				else
					nextStep.Image = SELECTED_RIGHT_IMAGE
				end
			else
				if i == 1 then
					nextStep.Image = NON_SELECTED_LEFT_IMAGE
				else
					nextStep.Image = NON_SELECTED_RIGHT_IMAGE
				end
			end
		end

		this.Steps[#this.Steps + 1] = nextStep
	end

	------------------- FUNCTIONS ---------------------
	local function hideSelection()
		for i = 1, steps do
			this.Steps[i].BackgroundColor3 = NON_SELECTED_COLOR
			if i == 1 then
				this.Steps[i].Image = NON_SELECTED_LEFT_IMAGE
			elseif i == steps then
				this.Steps[i].Image = NON_SELECTED_RIGHT_IMAGE
			end
		end
	end
	local function showSelection()
		for i = 1, steps do
			if i > currentStep then break end
			this.Steps[i].BackgroundColor3 = SELECTED_COLOR
			if i == 1 then
				this.Steps[i].Image = SELECTED_LEFT_IMAGE
			elseif i == steps then
				this.Steps[i].Image = SELECTED_RIGHT_IMAGE
			end
		end
	end
	local function modifySelection(alpha)
		for i = 1, steps do
			if i == 1 or i == steps then
				this.Steps[i].ImageTransparency = alpha
			else
				this.Steps[i].BackgroundTransparency = alpha
			end
		end
	end

	local function setCurrentStep(newStepPosition)
		if not minStep then minStep = 0 end

		leftButton.Visible = true
		rightButton.Visible = true

		if newStepPosition <= minStep then
			newStepPosition = minStep
			leftButton.Visible = false
		end
		if newStepPosition >= steps then
			newStepPosition = steps
			rightButton.Visible = false
		end

		if currentStep == newStepPosition then return end

		currentStep = newStepPosition

		hideSelection()
		showSelection()

		timeAtLastInput = tick()
		valueChangedEvent:Fire(currentStep)
	end

	local function isActivateEvent(inputObject)
		if not inputObject then return false end
		return inputObject.UserInputType == Enum.UserInputType.MouseButton1 or inputObject.UserInputType == Enum.UserInputType.Touch or (inputObject.UserInputType == Enum.UserInputType.Gamepad1 and inputObject.KeyCode == Enum.KeyCode.ButtonA)
	end
	local function mouseDownFunc(inputObject, newStepPos, repeatAction)
		if not interactable then return end

		if inputObject == nil then return end

		if not isActivateEvent(inputObject) then return end

		if usesSelectedObject() and not VRService.VREnabled then
			GuiService.SelectedCoreObject = this.SliderFrame
		end

		if not VRService.VREnabled then
			if repeatAction then
				lastInputDirection = newStepPos - currentStep
			else
				lastInputDirection = 0

				local mouseInputMovedCon = nil
				local mouseInputEndedCon = nil

				mouseInputMovedCon = UserInputService.InputChanged:Connect(function(inputObject)
					if inputObject.UserInputType ~= Enum.UserInputType.MouseMovement then return end

					local mousePos = inputObject.Position.X
					for i = 1, steps do
						local stepPosition = this.Steps[i].AbsolutePosition.X
						local stepSize = this.Steps[i].AbsoluteSize.X
						if mousePos >= stepPosition and mousePos <= stepPosition + stepSize then
							setCurrentStep(i)
							break
						elseif i == 1 and mousePos < stepPosition then
							setCurrentStep(0)
							break
						elseif i == steps and mousePos >= stepPosition then
							setCurrentStep(i)
							break
						end
					end
				end)
				mouseInputEndedCon = UserInputService.InputEnded:Connect(function(inputObject)
					if not isActivateEvent(inputObject) then return end

					lastInputDirection = 0
					mouseInputEndedCon:Disconnect()
					mouseInputMovedCon:Disconnect()
				end)
			end
		else
			lastInputDirection = 0
		end

		setCurrentStep(newStepPos)
	end

	local function mouseUpFunc(inputObject)
		if not interactable then return end
		if not isActivateEvent(inputObject) then return end

		lastInputDirection = 0
	end

	local function touchClickFunc(inputObject, newStepPos, repeatAction)
		mouseDownFunc(inputObject, newStepPos, repeatAction)
	end

	--------------------- PUBLIC FACING FUNCTIONS -----------------------
	this.ValueChanged = valueChangedEvent.Event

	function this:SetValue(newValue)
		setCurrentStep(newValue)
	end

	function this:GetValue()
		return currentStep
	end

	function this:SetInteractable(value)
		lastInputDirection = 0
		interactable = value
		this.SliderFrame.Selectable = value
		if not interactable then
			hideSelection()
		else
			showSelection()
		end
	end

	function this:SetZIndex(newZIndex)
		leftButton.ZIndex = newZIndex
		rightButton.ZIndex = newZIndex
		leftButtonImage.ZIndex = newZIndex
		rightButtonImage.ZIndex = newZIndex

		for i = 1, #this.Steps do
			this.Steps[i].ZIndex = newZIndex
		end
	end

	function this:SetMinStep(newMinStep)
		if newMinStep >= 0 and newMinStep <= steps then
			minStep = newMinStep
		end

		if currentStep <= minStep then
			currentStep = minStep
			leftButton.Visible = false
		end
		if currentStep >= steps then
			currentStep = steps
			rightButton.Visible = false
		end
	end

	--------------------- SETUP -----------------------

	leftButton.InputBegan:Connect(function(inputObject) mouseDownFunc(inputObject, currentStep - 1, true) end)
	leftButton.InputEnded:Connect(function(inputObject) mouseUpFunc(inputObject) end)
	rightButton.InputBegan:Connect(function(inputObject) mouseDownFunc(inputObject, currentStep + 1, true) end)
	rightButton.InputEnded:Connect(function(inputObject) mouseUpFunc(inputObject) end)

	local function onVREnabled(prop)
		if prop ~= "VREnabled" then
			return
		end
		if VRService.VREnabled then
			leftButton.Selectable = interactable
			rightButton.Selectable = interactable
			this.SliderFrame.Selectable = interactable

			for i = 1, steps do
				this.Steps[i].Selectable = interactable
				this.Steps[i].Active = interactable
			end
		else
			leftButton.Selectable = false
			rightButton.Selectable = false
			this.SliderFrame.Selectable = interactable
			for i = 1, steps do
				this.Steps[i].Selectable = false
				this.Steps[i].Active = false
			end
		end
	end
	VRService.Changed:Connect(onVREnabled)
	onVREnabled("VREnabled")

	for i = 1, steps do
		this.Steps[i].InputBegan:Connect(function(inputObject)
			mouseDownFunc(inputObject, i)
		end)
		this.Steps[i].InputEnded:Connect(function(inputObject)
		 mouseUpFunc(inputObject) end)
	end

	this.SliderFrame.InputBegan:Connect(function(inputObject)
		if VRService.VREnabled then
			local selected = GuiService.SelectedCoreObject
			if not selected or not selected:IsDescendantOf(this.SliderFrame.Parent) then return end
		end
		mouseDownFunc(inputObject, currentStep)
	end)
	this.SliderFrame.InputEnded:Connect(function(inputObject)
		if VRService.VREnabled then
			local selected = GuiService.SelectedCoreObject
			if not selected or not selected:IsDescendantOf(this.SliderFrame.Parent) then return end
		end
		mouseUpFunc(inputObject)
	end)

	local stepSliderFunc = function()
		if timeAtLastInput == nil then return end

		local currentTime = tick()
		local timeSinceLastInput = currentTime - timeAtLastInput
		if timeSinceLastInput >= CONTROLLER_SCROLL_DELTA then
			setCurrentStep(currentStep + lastInputDirection)
		end
	end

	local isInTree = true

	local navigateLeft = -1 --these are just for differentiation, the actual value isn't important as long as they coerce to boolean true (all numbers do in Lua)
	local navigateRight = 1
	local navigationKeyCodes = {
		[Enum.KeyCode.Thumbstick1] = true, --thumbstick can be either direction
		[Enum.KeyCode.DPadLeft] = navigateLeft,
		[Enum.KeyCode.DPadRight] = navigateRight,
		[Enum.KeyCode.Left] = navigateLeft,
		[Enum.KeyCode.Right] = navigateRight,
		[Enum.KeyCode.A] = navigateLeft,
		[Enum.KeyCode.D] = navigateRight,
		[Enum.KeyCode.ButtonA] = true --buttonA can be either direction
	}
	UserInputService.InputBegan:Connect(function(inputObject)
		if not interactable then return end
		if not isInTree then return end

		if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 and inputObject.UserInputType ~= Enum.UserInputType.Keyboard then return end
		local selected = GuiService.SelectedCoreObject
		if not selected or not selected:IsDescendantOf(this.SliderFrame.Parent) then return end

		if navigationKeyCodes[inputObject.KeyCode] == navigateLeft then
			lastInputDirection = -1
			setCurrentStep(currentStep - 1)
		elseif navigationKeyCodes[inputObject.KeyCode] == navigateRight then
			lastInputDirection = 1
			setCurrentStep(currentStep + 1)
		end
	end)

	UserInputService.InputEnded:Connect(function(inputObject)
		if not interactable then return end

		if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 and inputObject.UserInputType ~= Enum.UserInputType.Keyboard then return end
		local selected = GuiService.SelectedCoreObject
		if not selected or not selected:IsDescendantOf(this.SliderFrame.Parent) then return end

		if navigationKeyCodes[inputObject.KeyCode] then --detect any keycode considered a navigation key
			lastInputDirection = 0
		end
	end)

	UserInputService.InputChanged:Connect(function(inputObject)
		if not interactable then
			lastInputDirection = 0
			return
		end
		if not isInTree then
			lastInputDirection = 0
			return
		end

		if inputObject.UserInputType ~= Enum.UserInputType.Gamepad1 then return end
		local selected = GuiService.SelectedCoreObject
		if not selected or not selected:IsDescendantOf(this.SliderFrame.Parent) then return end
		if inputObject.KeyCode ~= Enum.KeyCode.Thumbstick1 then return end

		if inputObject.Position.X > CONTROLLER_THUMBSTICK_DEADZONE and inputObject.Delta.X > 0 and lastInputDirection ~= 1 then
			lastInputDirection = 1
			setCurrentStep(currentStep + 1)
		elseif inputObject.Position.X < -CONTROLLER_THUMBSTICK_DEADZONE and inputObject.Delta.X < 0 and lastInputDirection ~= -1 then
			lastInputDirection = -1
			setCurrentStep(currentStep - 1)
		elseif math.abs(inputObject.Position.X) < CONTROLLER_THUMBSTICK_DEADZONE then
			lastInputDirection = 0
		end
	end)

	local isBound = false
	GuiService.Changed:Connect(function(prop)
		if prop ~= "SelectedCoreObject" then return end

		local selected = GuiService.SelectedCoreObject
		local isThisSelected = selected and selected:IsDescendantOf(this.SliderFrame.Parent)
		if isThisSelected then
			modifySelection(0)
			if not isBound then
				isBound = true
				timeAtLastInput = tick()
				RunService:BindToRenderStep(renderStepBindName, Enum.RenderPriority.Input.Value + 1, stepSliderFunc)
			end
		else
			modifySelection(0.36)
			if isBound then
				isBound = false
				RunService:UnbindFromRenderStep(renderStepBindName)
			end
		end
	end)

	this.SliderFrame.AncestryChanged:Connect(function(child, parent)
		isInTree = parent
	end)

	setCurrentStep(currentStep)

	return this
end

local ROW_HEIGHT = 50
if isTenFootInterface() then ROW_HEIGHT = 90 end

local nextPosTable = {}
local function AddNewRow(pageToAddTo, rowDisplayName, selectionType, rowValues, rowDefault, extraSpacing)
	local nextRowPositionY = 0
	local isARealRow = selectionType ~= 'TextBox' -- Textboxes are constructed in this function - they don't have an associated class.

	if nextPosTable[pageToAddTo] then
		nextRowPositionY = nextPosTable[pageToAddTo]
	end

	local RowFrame = nil
	RowFrame = Util.Create'ImageButton'
	{
		Name = rowDisplayName .. "Frame",
		BackgroundTransparency = 1,
		BorderSizePixel = 0,
		Image = "rbxasset://textures/ui/VR/rectBackgroundWhite.png",
		ScaleType = Enum.ScaleType.Slice,
		SliceCenter = Rect.new(2, 2, 18, 18),
		ImageTransparency = 1,
		Active = false,
		AutoButtonColor = false,
		Size = UDim2.new(1,0,0,ROW_HEIGHT),
		Position = UDim2.new(0,0,0,nextRowPositionY),
		ZIndex = 2,
		Selectable = false,
		SelectionImageObject = noSelectionObject,
		Parent = pageToAddTo.Page
	};
	RowFrame.ImageColor3 = RowFrame.BackgroundColor3

	if RowFrame and extraSpacing then
		RowFrame.Position = UDim2.new(RowFrame.Position.X.Scale,RowFrame.Position.X.Offset,
			RowFrame.Position.Y.Scale,RowFrame.Position.Y.Offset + extraSpacing)
	end

	local RowLabel = nil
	RowLabel = Util.Create'TextLabel'
	{
		Name = rowDisplayName .. "Label",
		Text = rowDisplayName,
		Font = Enum.Font.SourceSansBold,
		TextSize = 16,
		TextColor3 = Color3.fromRGB(255,255,255),
		TextXAlignment = Enum.TextXAlignment.Left,
		BackgroundTransparency = 1,
		Size = UDim2.new(0,200,1,0),
		Position = UDim2.new(0,10,0,0),
		ZIndex = 2,
		Parent = RowFrame
	};

	local RowLabelTextSizeConstraint = Instance.new("UITextSizeConstraint")
	if FFlagUseNotificationsLocalization then
		RowLabel.Size = UDim2.new(0.35,0,1,0)
		RowLabel.TextScaled = true
		RowLabel.TextWrapped = true
		RowLabelTextSizeConstraint.Parent = RowLabel
		RowLabelTextSizeConstraint.MaxTextSize = 16
	end

	if not isARealRow then
		RowLabel.Text = ''
	end

	local function onResized(viewportSize, portrait)
		if portrait then
			RowLabel.TextSize = 16
		else
			RowLabel.TextSize = isTenFootInterface() and 36 or 24
		end
		RowLabelTextSizeConstraint.MaxTextSize = RowLabel.TextSize
	end
	onResized(getViewportSize(), isPortrait())
	addOnResizedCallback(RowFrame, onResized)

	local ValueChangerSelection = nil
	local ValueChangerInstance = nil
	if selectionType == "Slider" then
		ValueChangerInstance = CreateNewSlider(rowValues, rowDefault)
		ValueChangerInstance.SliderFrame.Parent = RowFrame
		ValueChangerSelection = ValueChangerInstance.SliderFrame
	elseif selectionType == "Selector" then
		ValueChangerInstance = CreateSelector(rowValues, rowDefault)
		ValueChangerInstance.SelectorFrame.Parent = RowFrame
		ValueChangerSelection = ValueChangerInstance.SelectorFrame
	elseif selectionType == "DropDown" then
		ValueChangerInstance = CreateDropDown(rowValues, rowDefault, pageToAddTo.HubRef)
		ValueChangerInstance.DropDownFrame.Parent = RowFrame
		ValueChangerSelection = ValueChangerInstance.DropDownFrame
	elseif selectionType == "TextBox" then
		local isMouseOverRow = false
		local forceReturnSelectionOnFocusLost = false
		local SelectionOverrideObject = Util.Create'ImageLabel'
		{
			Image = "",
			BackgroundTransparency = 1,
		};

		ValueChangerInstance = {}
		ValueChangerInstance.HubRef = nil

		local box = Util.Create'TextBox'
		{
			AnchorPoint = Vector2.new(1, 0.5),
			Size = UDim2.new(0.6,0,1,0),
			Position = UDim2.new(1,0,0.5,0),
			Text = rowDisplayName,
			TextColor3 = Color3.fromRGB(49, 49, 49),
			BackgroundTransparency = 0.5,
			BorderSizePixel = 0,
			TextYAlignment = Enum.TextYAlignment.Top,
			TextXAlignment = Enum.TextXAlignment.Left,
			TextWrapped = true,
			Font = Enum.Font.SourceSans,
			TextSize = 24,
			ZIndex = 2,
			SelectionImageObject = SelectionOverrideObject,
			ClearTextOnFocus = false,
			Parent = RowFrame
		};
		ValueChangerSelection = box

		box.Focused:Connect(function()
			if usesSelectedObject() then
				GuiService.SelectedCoreObject = box
			end

			if box.Text == rowDisplayName then
				box.Text = ""
			end
		end)
		box.FocusLost:Connect(function(enterPressed, inputObject)
			forceReturnSelectionOnFocusLost = false
		end)
		if extraSpacing then
			box.Position = UDim2.new(box.Position.X.Scale,box.Position.X.Offset,
				box.Position.Y.Scale,box.Position.Y.Offset + extraSpacing)
		end

		ValueChangerSelection.SelectionGained:Connect(function()
			if usesSelectedObject() then
				box.BackgroundTransparency = 0.1

				if ValueChangerInstance.HubRef then
					ValueChangerInstance.HubRef:ScrollToFrame(ValueChangerSelection)
				end
			end
		end)
		ValueChangerSelection.SelectionLost:Connect(function()
			if usesSelectedObject() then
				box.BackgroundTransparency = 0.5
			end
		end)

		local setRowSelection = function()
			local fullscreenDropDown = CoreGui.RobloxGui:FindFirstChild("DropDownFullscreenFrame")
			if fullscreenDropDown and fullscreenDropDown.Visible then return end

			local valueFrame = ValueChangerSelection

			if valueFrame and valueFrame.Visible and valueFrame.ZIndex > 1 and usesSelectedObject() and pageToAddTo.Active then
				GuiService.SelectedCoreObject = valueFrame
				isMouseOverRow = true
			end
		end
		local function processInput(input)
			if input.UserInputState == Enum.UserInputState.Begin then
				if input.KeyCode == Enum.KeyCode.Return then
					if GuiService.SelectedCoreObject == ValueChangerSelection then
						forceReturnSelectionOnFocusLost = true
						box:CaptureFocus()
					end
				end
			end
		end
		box.MouseEnter:Connect(setRowSelection)

		UserInputService.InputBegan:Connect(processInput)

	elseif selectionType == "TextEntry" then
		local isMouseOverRow = false
		local forceReturnSelectionOnFocusLost = false
		local SelectionOverrideObject = Util.Create'ImageLabel'
		{
			Image = "",
			BackgroundTransparency = 1,
		};

		ValueChangerInstance = {}
		ValueChangerInstance.HubRef = nil

		local box = Util.Create'TextBox'
		{
			AnchorPoint = Vector2.new(1, 0.5),
			Size = UDim2.new(0.4,-10,0,40),
			Position = UDim2.new(1,0,0.5,0),
			Text = rowDisplayName,
			TextColor3 = Color3.fromRGB(178, 178, 178),
			BackgroundTransparency = 1.0,
			BorderSizePixel = 0,
			TextYAlignment = Enum.TextYAlignment.Center,
			TextXAlignment = Enum.TextXAlignment.Center,
			TextWrapped = false,
			Font = Enum.Font.SourceSans,
			TextSize = 24,
			ZIndex = 2,
			SelectionImageObject = SelectionOverrideObject,
			ClearTextOnFocus = false,
			Parent = RowFrame
		};
		ValueChangerSelection = box

		box.Focused:Connect(function()
			if usesSelectedObject() then
				GuiService.SelectedCoreObject = box
			end

			if box.Text == rowDisplayName then
				box.Text = ""
			end
		end)
		box.FocusLost:Connect(function(enterPressed, inputObject)
			forceReturnSelectionOnFocusLost = false
		end)
		if extraSpacing then
			box.Position = UDim2.new(box.Position.X.Scale,box.Position.X.Offset,
										box.Position.Y.Scale,box.Position.Y.Offset + extraSpacing)
		end

		ValueChangerSelection.SelectionGained:Connect(function()
			if usesSelectedObject() then
				box.BackgroundTransparency = 0.8

				if ValueChangerInstance.HubRef then
					ValueChangerInstance.HubRef:ScrollToFrame(ValueChangerSelection)
				end
			end
		end)
		ValueChangerSelection.SelectionLost:Connect(function()
			if usesSelectedObject() then
				box.BackgroundTransparency = 1.0
			end
		end)

		local setRowSelection = function()
			local fullscreenDropDown = CoreGui.RobloxGui:FindFirstChild("DropDownFullscreenFrame")
			if fullscreenDropDown and fullscreenDropDown.Visible then return end

			local valueFrame = ValueChangerSelection

			if valueFrame and valueFrame.Visible and valueFrame.ZIndex > 1 and usesSelectedObject() and pageToAddTo.Active then
				GuiService.SelectedCoreObject = valueFrame
				isMouseOverRow = true
			end
		end
		local function processInput(input)
			if input.UserInputState == Enum.UserInputState.Begin then
				if input.KeyCode == Enum.KeyCode.Return then
					if GuiService.SelectedCoreObject == ValueChangerSelection then
						forceReturnSelectionOnFocusLost = true
						box:CaptureFocus()
					end
				end
			end
		end
		RowFrame.MouseEnter:Connect(setRowSelection)

		function ValueChangerInstance:SetZIndex(newZIndex)
			box.ZIndex = newZIndex
		end

		function ValueChangerInstance:SetInteractable(interactable)
			box.Selectable = interactable
			if not interactable then
				box.TextColor3 = Color3.fromRGB(49,49,49)
				box.ZIndex = 1
			else
				box.TextColor3 = Color3.fromRGB(178,178,178)
				box.ZIndex = 2
			end
		end

		function ValueChangerInstance:SetValue(value) -- should this do more?
			box.Text = value
		end

		local valueChangedEvent = Instance.new("BindableEvent")
		valueChangedEvent.Name = "ValueChanged"

		box.FocusLost:Connect(function()
			valueChangedEvent:Fire(box.Text)
		end)

		ValueChangerInstance.ValueChanged = valueChangedEvent.Event

		UserInputService.InputBegan:Connect(processInput)
	end

	ValueChangerInstance.Name = rowDisplayName .. "ValueChanger"

	nextRowPositionY = nextRowPositionY + ROW_HEIGHT
	if extraSpacing then
		nextRowPositionY = nextRowPositionY + extraSpacing
	end

	nextPosTable[pageToAddTo] = nextRowPositionY

	if isARealRow then
		local setRowSelection = function()
			local fullscreenDropDown = CoreGui.RobloxGui:FindFirstChild("DropDownFullscreenFrame")
			if fullscreenDropDown and fullscreenDropDown.Visible then return end

			local valueFrame = ValueChangerInstance.SliderFrame
			if not valueFrame then
				valueFrame = ValueChangerInstance.SliderFrame
			end
			if not valueFrame then
				valueFrame = ValueChangerInstance.DropDownFrame
			end
			if not valueFrame then
				valueFrame = ValueChangerInstance.SelectorFrame
			end

			if valueFrame and valueFrame.Visible and valueFrame.ZIndex > 1 and usesSelectedObject() and pageToAddTo.Active then
				GuiService.SelectedCoreObject = valueFrame
			end
		end
		RowFrame.MouseEnter:Connect(setRowSelection)

		--Could this be cleaned up even more?
		local function onVREnabled(prop)
			if prop == "VREnabled" then
				if VRService.VREnabled then
					RowFrame.Selectable = true
					RowFrame.Active = true
					ValueChangerSelection.Active = true
					GuiService.Changed:Connect(function(prop)
						if prop == "SelectedCoreObject" then
							local selected = GuiService.SelectedCoreObject
							if selected and (selected == RowFrame or selected:IsDescendantOf(RowFrame)) then
								RowFrame.ImageTransparency = 0.5
								RowFrame.BackgroundTransparency = 1
							else
								RowFrame.ImageTransparency = 1
								RowFrame.BackgroundTransparency = 1
							end
						end
					end)
				else
					RowFrame.Selectable = false
					RowFrame.Active = false
				end
			end
		end
		VRService.Changed:Connect(onVREnabled)
		onVREnabled("VREnabled")

		ValueChangerSelection.SelectionGained:Connect(function()
			if usesSelectedObject() then
				if VRService.VREnabled then
					RowFrame.ImageTransparency = 0.5
					RowFrame.BackgroundTransparency = 1
				else
					RowFrame.ImageTransparency = 1
					RowFrame.BackgroundTransparency = 0.5
				end

				if ValueChangerInstance.HubRef then
					ValueChangerInstance.HubRef:ScrollToFrame(RowFrame)
				end
			end
		end)
		ValueChangerSelection.SelectionLost:Connect(function()
			if usesSelectedObject() then
				RowFrame.ImageTransparency = 1
				RowFrame.BackgroundTransparency = 1
			end
		end)
	end

	pageToAddTo:AddRow(RowFrame, RowLabel, ValueChangerInstance, extraSpacing, false)

	ValueChangerInstance.Selection = ValueChangerSelection

	return RowFrame, RowLabel, ValueChangerInstance
end

local function AddNewRowObject(pageToAddTo, rowDisplayName, rowObject, extraSpacing)
	local nextRowPositionY = 0

	if nextPosTable[pageToAddTo] then
		nextRowPositionY = nextPosTable[pageToAddTo]
	end

	local RowFrame = Util.Create'ImageButton'
	{
		Name = rowDisplayName .. "Frame",
		BackgroundTransparency = 1,
		BorderSizePixel = 0,
		Image = "rbxasset://textures/ui/VR/rectBackgroundWhite.png",
		ScaleType = Enum.ScaleType.Slice,
		SliceCenter = Rect.new(10,10,10,10),
		ImageTransparency = 1,
		Active = false,
		AutoButtonColor = false,
		Size = UDim2.new(1,0,0,ROW_HEIGHT),
		Position = UDim2.new(0,0,0,nextRowPositionY),
		ZIndex = 2,
		Selectable = false,
		SelectionImageObject = noSelectionObject,
		Parent = pageToAddTo.Page
	};
	RowFrame.ImageColor3 = RowFrame.BackgroundColor3
	RowFrame.SelectionGained:Connect(function()
		RowFrame.BackgroundTransparency = 0.5
	end)
	RowFrame.SelectionLost:Connect(function()
		RowFrame.BackgroundTransparency = 1
	end)

	local RowLabel = Util.Create'TextLabel'
	{
		Name = rowDisplayName .. "Label",
		Text = rowDisplayName,
		Font = Enum.Font.SourceSansBold,
		TextSize = 16,
		TextColor3 = Color3.fromRGB(255,255,255),
		TextXAlignment = Enum.TextXAlignment.Left,
		BackgroundTransparency = 1,
		Size = UDim2.new(0,200,1,0),
		Position = UDim2.new(0,10,0,0),
		ZIndex = 2,
		Parent = RowFrame
	};
	local function onResized(viewportSize, portrait)
		if portrait then
			RowLabel.TextSize = 16
		else
			RowLabel.TextSize = isTenFootInterface() and 36 or 24
		end
	end
	addOnResizedCallback(RowFrame, onResized)

	if extraSpacing then
		RowFrame.Position = UDim2.new(RowFrame.Position.X.Scale,RowFrame.Position.X.Offset,
			RowFrame.Position.Y.Scale,RowFrame.Position.Y.Offset + extraSpacing)
	end

	nextRowPositionY = nextRowPositionY + ROW_HEIGHT
	if extraSpacing then
		nextRowPositionY = nextRowPositionY + extraSpacing
	end

	nextPosTable[pageToAddTo] = nextRowPositionY

	local setRowSelection = function()
		if RowFrame.Visible then
			GuiService.SelectedCoreObject = RowFrame
		end
	end
	RowFrame.MouseEnter:Connect(setRowSelection)

	rowObject.SelectionImageObject = noSelectionObject

	rowObject.SelectionGained:Connect(function()
		if VRService.VREnabled then
			RowFrame.ImageTransparency = 0.5
			RowFrame.BackgroundTransparency = 1
		else
			RowFrame.ImageTransparency = 1
			RowFrame.BackgroundTransparency = 0.5
		end
	end)
	rowObject.SelectionLost:Connect(function()
		RowFrame.ImageTransparency = 1
		RowFrame.BackgroundTransparency = 1
	end)

	rowObject.Parent = RowFrame

	pageToAddTo:AddRow(RowFrame, RowLabel, rowObject, extraSpacing, true)
	return RowFrame
end


Prompt: --------RIGHT DOOR 5--------

Response:
game.Workspace.doorright.l73.BrickColor = BrickColor.new(135)
game.Workspace.doorright.l72.BrickColor = BrickColor.new(135)
game.Workspace.doorright.l71.BrickColor = BrickColor.new(135)
game.Workspace.doorright.l63.BrickColor = BrickColor.new(135)
game.Workspace.doorright.l62.BrickColor = BrickColor.new(135)
game.Workspace.doorright.l61.BrickColor = BrickColor.new(135)
game.Workspace.doorright.l53.BrickColor = BrickColor.new(135)
game.Workspace.doorright.l52.BrickColor = BrickColor.new(135)
game.Workspace.doorright.l51.BrickColor = BrickColor.new(135)
game.Workspace.doorright.l42.BrickColor = BrickColor.new(135)
game.Workspace.doorright.l41.BrickColor = BrickColor.new(135)
game.Workspace.doorright.l31.BrickColor = BrickColor.new(135)

game.Workspace.doorright.l11.BrickColor = BrickColor.new(102)
game.Workspace.doorright.l12.BrickColor = BrickColor.new(102)
game.Workspace.doorright.l13.BrickColor = BrickColor.new(102)
game.Workspace.doorright.l43.BrickColor = BrickColor.new(102)
game.Workspace.doorright.l21.BrickColor = BrickColor.new(102)
game.Workspace.doorright.l22.BrickColor = BrickColor.new(102)
game.Workspace.doorright.l23.BrickColor = BrickColor.new(102)
game.Workspace.doorright.l32.BrickColor = BrickColor.new(102)
game.Workspace.doorright.l33.BrickColor = BrickColor.new(102)


Prompt:
--[[

	Knit.CreateService(service): Service
	Knit.AddServices(folder): Service[]
	Knit.AddServicesDeep(folder): Service[]
	Knit.Start(): Promise<void>
	Knit.OnStart(): Promise<void>

--]]

Response:
type ServiceDef = {
	Name: string,
	Client: {[any]: any}?,
	[any]: any,
}

type Service = {
	Name: string,
	Client: ServiceClient,
	_knit_is_service: boolean,
	_knit_rf: {},
	_knit_re: {},
	_knit_rp: {},
	_knit_rep_folder: Instance,
	[any]: any,
}

type ServiceClient = {
	Server: Service,
	[any]: any,
}

local KnitServer = {}

KnitServer.Version = script.Parent.Version.Value
KnitServer.Services = {} :: {[string]: Service}
KnitServer.Util = script.Parent.Util

local knitRepServiceFolder = Instance.new("Folder")
knitRepServiceFolder.Name = "Services"

local Promise = require(KnitServer.Util.Promise)
local Signal = require(KnitServer.Util.Signal)
local Loader = require(KnitServer.Util.Loader)
local Ser = require(KnitServer.Util.Ser)
local RemoteSignal = require(KnitServer.Util.Remote.RemoteSignal)
local RemoteProperty = require(KnitServer.Util.Remote.RemoteProperty)
local TableUtil = require(KnitServer.Util.TableUtil)

local started = false
local startedComplete = false
local onStartedComplete = Instance.new("BindableEvent")

local function CreateRepFolder(serviceName: string): Instance
	local folder = Instance.new("Folder")
	folder.Name = serviceName
	return folder
end

local function GetFolderOrCreate(parent: Instance, name: string): Instance
	local f = parent:FindFirstChild(name)
	if not f then
		f = Instance.new("Folder")
		f.Name = name
		f.Parent = parent
	end
	return f
end

local function AddToRepFolder(service: Service, remoteObj: Instance, folderOverride: string?)
	if folderOverride then
		remoteObj.Parent = GetFolderOrCreate(service._knit_rep_folder, folderOverride)
	elseif remoteObj:IsA("RemoteFunction") then
		remoteObj.Parent = GetFolderOrCreate(service._knit_rep_folder, "RF")
	elseif remoteObj:IsA("RemoteEvent") then
		remoteObj.Parent = GetFolderOrCreate(service._knit_rep_folder, "RE")
	elseif remoteObj:IsA("ValueBase") then
		remoteObj.Parent = GetFolderOrCreate(service._knit_rep_folder, "RP")
	else
		error("Invalid rep object: " .. remoteObj.ClassName)
	end
	if not service._knit_rep_folder.Parent then
		service._knit_rep_folder.Parent = knitRepServiceFolder
	end
end

local function DoesServiceExist(serviceName: string): boolean
	local service: Service? = KnitServer.Services[serviceName]
	return service ~= nil
end

function KnitServer.IsService(object: any): boolean
	return type(object) == "table" and object._knit_is_service == true
end

function KnitServer.CreateService(serviceDef: ServiceDef): Service
	assert(type(serviceDef) == "table", "Service must be a table; got " .. type(serviceDef))
	assert(type(serviceDef.Name) == "string", "Service.Name must be a string; got " .. type(serviceDef.Name))
	assert(#serviceDef.Name > 0, "Service.Name must be a non-empty string")
	assert(not DoesServiceExist(serviceDef.Name), "Service \"" .. serviceDef.Name .. "\" already exists")
	local service: Service = TableUtil.Assign(serviceDef, {
		_knit_is_service = true;
		_knit_rf = {};
		_knit_re = {};
		_knit_rp = {};
		_knit_rep_folder = CreateRepFolder(serviceDef.Name);
	})
	if type(service.Client) ~= "table" then
		service.Client = {Server = service}
	else
		if service.Client.Server ~= service then
			service.Client.Server = service
		end
	end
	KnitServer.Services[service.Name] = service
	return service
end

function KnitServer.AddServices(folder: Instance): {any}
	return Loader.LoadChildren(folder)
end

function KnitServer.AddServicesDeep(folder: Instance): {any}
	return Loader.LoadDescendants(folder)
end

function KnitServer.GetService(serviceName: string): Service
	assert(type(serviceName) == "string", "ServiceName must be a string; got " .. type(serviceName))
	return assert(KnitServer.Services[serviceName], "Could not find service \"" .. serviceName .. "\"") :: Service
end

function KnitServer.BindRemoteEvent(service: Service, eventName: string, remoteEvent)
	assert(service._knit_re[eventName] == nil, "RemoteEvent \"" .. eventName .. "\" already exists")
	local re = remoteEvent._remote
	re.Name = eventName
	service._knit_re[eventName] = re
	AddToRepFolder(service, re)
end

function KnitServer.BindRemoteFunction(service: Service, funcName: string, func: (ServiceClient, ...any) -> ...any)
	assert(service._knit_rf[funcName] == nil, "RemoteFunction \"" .. funcName .. "\" already exists")
	local rf = Instance.new("RemoteFunction")
	rf.Name = funcName
	service._knit_rf[funcName] = rf
	AddToRepFolder(service, rf)
	rf.OnServerInvoke = function(...)
		return Ser.SerializeArgsAndUnpack(func(service.Client, Ser.DeserializeArgsAndUnpack(...)))
	end
end

function KnitServer.BindRemoteProperty(service: Service, propName: string, prop)
	assert(service._knit_rp[propName] == nil, "RemoteProperty \"" .. propName .. "\" already exists")
	prop._object.Name = propName
	service._knit_rp[propName] = prop
	AddToRepFolder(service, prop._object, "RP")
end

function KnitServer.Start()

	if started then
		return Promise.Reject("Knit already started")
	end

	started = true

	local services = KnitServer.Services

	return Promise.new(function(resolve)

		-- Bind remotes:
		for _,service in pairs(services) do
			for k,v in pairs(service.Client) do
				if type(v) == "function" then
					KnitServer.BindRemoteFunction(service, k, v)
				elseif RemoteSignal.Is(v) then
					KnitServer.BindRemoteEvent(service, k, v)
				elseif RemoteProperty.Is(v) then
					KnitServer.BindRemoteProperty(service, k, v)
				elseif Signal.Is(v) then
					warn("Found Signal instead of RemoteSignal (Knit.Util.RemoteSignal). Please change to RemoteSignal. [" .. service.Name .. ".Client." .. k .. "]")
				end
			end
		end

		-- Init:
		local promisesInitServices = {}
		for _,service in pairs(services) do
			if type(service.KnitInit) == "function" then
				table.insert(promisesInitServices, Promise.new(function(r)
					service:KnitInit()
					r()
				end))
			end
		end

		resolve(Promise.All(promisesInitServices))

	end):Then(function()

		-- Start:
		for _,service in pairs(services) do
			if type(service.KnitStart) == "function" then
				task.spawn(service.KnitStart, service)
			end
		end

		startedComplete = true
		onStartedComplete:Fire()

		task.defer(function()
			onStartedComplete:Destroy()
		end)

		-- Expose service remotes to everyone:
		knitRepServiceFolder.Parent = script.Parent

	end)

end

function KnitServer.OnStart()
	if startedComplete then
		return Promise.Resolve()
	else
		return Promise.FromEvent(onStartedComplete.Event)
	end
end

return KnitServer


Prompt: -- Set up the event handler for the button

Response: btn.MouseButton1Click:Connect(toggleWindows)


Prompt: --[[Susupension]]

Response:
	Tune.SusEnabled		= false		-- works only in with PGSPhysicsSolverEnabled, defaults to false when PGS is disabled

	--Front Suspension
	Tune.FSusDamping	= 500		-- Spring Dampening
	Tune.FSusStiffness	= 9000		-- Spring Force
	Tune.FAntiRoll 		= 50		-- Anti-Roll (Gyro Dampening)

	Tune.FSusLength		= 2			-- Suspension length (in studs)
	Tune.FPreCompress	= .3		-- Pre-compression adds resting length force
	Tune.FExtensionLim	= .3		-- Max Extension Travel (in studs)
	Tune.FCompressLim	= .1		-- Max Compression Travel (in studs)
	Tune.FSusAngle		= 80		-- Suspension Angle (degrees from horizontal)

	Tune.FWsBoneLen		= 5			-- Wishbone Length
	Tune.FWsBoneAngle	= 0			-- Wishbone angle (degrees from horizontal)
	Tune.FAnchorOffset	= {			-- Suspension anchor point offset (relative to center of wheel)
	 --[[Lateral]]		-.4		,	-- positive = outward
	 --[[Vertical]]		-.5		,	-- positive = upward
	 --[[Forward]]		0		}	-- positive = forward

	--Rear Suspension
	Tune.RSusDamping	= 500		-- Spring Dampening
	Tune.RSusStiffness	= 9000		-- Spring Force
	Tune.FAntiRoll 		= 50		-- Anti-Roll (Gyro Dampening)

	Tune.RSusLength		= 2			-- Suspension length (in studs)
	Tune.RPreCompress	= .3		-- Pre-compression adds resting length force
	Tune.RExtensionLim	= .3		-- Max Extension Travel (in studs)
	Tune.RCompressLim	= .1		-- Max Compression Travel (in studs)
	Tune.RSusAngle		= 80		-- Suspension Angle (degrees from horizontal)

	Tune.RWsBoneLen		= 5			-- Wishbone Length
	Tune.RWsBoneAngle	= 0			-- Wishbone angle (degrees from horizontal)
	Tune.RAnchorOffset	= {			-- Suspension anchor point offset (relative to center of wheel)
	 --[[Lateral]]		-.4		,	-- positive = outward
	 --[[Vertical]]		-.5		,	-- positive = upward
	 --[[Forward]]		0		}	-- positive = forward

	--Aesthetics
	Tune.SusVisible		= false			-- Spring Visible
	Tune.WsBVisible		= false			-- Wishbone Visible
	Tune.SusRadius		= .2			-- Suspension Coil Radius
	Tune.SusThickness	= .1			-- Suspension Coil Thickness
	Tune.SusColor		= "Bright red"	-- Suspension Color [BrickColor]
	Tune.SusCoilCount	= 6				-- Suspension Coil Count
	Tune.WsColor		= "Black"		-- Wishbone Color [BrickColor]
	Tune.WsThickness	= .1			-- Wishbone Rod Thickness


Prompt:
-----------------
--| Variables |--
-----------------

Response:
local GamePassService = game:GetService('MarketplaceService')
local PlayersService = game:GetService('Players')

local VipDoor = script.Parent

local GamePassIdObject = WaitForChild(script, 'GamePassId')

local JustTouched = {}


Prompt: -- Confetti Defaults.

Response:
local shapes = {script:WaitForChild("CircularConfetti"), script:WaitForChild("SquareConfetti")};
local colors = {Color3.fromRGB(168,100,253), Color3.fromRGB(41,205,255), Color3.fromRGB(120,255,68), Color3.fromRGB(255,113,141), Color3.fromRGB(253,255,106)};


Prompt: --[[Transmission]]

Response:
	Tune.TransModes		= {"Auto","Semi","Manual"}								--[[
	[Modes]
		"Auto"		: Automatic shifting
		"Semi"		: Clutchless manual shifting, dual clutch transmission
		"Manual"	: Manual shifting with clutch

		>Include within brackets
			eg: {"Semi"} or {"Auto", "Manual"}
		>First mode is default mode													]]

	--Automatic Settings
	Tune.AutoShiftMode	= "Speed"												--[[
	[Modes]
		"Speed"		: Shifts based on wheel speed
		"RPM"		: Shifts based on RPM											]]
	Tune.AutoUpThresh	= -200		--Automatic upshift point 	(relative to peak RPM, positive = Over-rev)
	Tune.AutoDownThresh = 1400		--Automatic downshift point (relative to peak RPM, positive = Under-rev)

	--Gear Ratios
	Tune.FinalDrive		= 13.5			-- Gearing determines top speed and wheel torque
	Tune.Ratios			= {				-- Higher ratio = more torque, Lower ratio = higher top speed
		--[[Reverse]]	1.5		,	-- Copy and paste a ratio to add a gear
		--[[Neutral]]	0			,	-- Ratios can also be deleted
		--[[ 1 ]]		1.89		,	-- Reverse, Neutral, and 1st gear are required
		--[[ 2 ]]		0.76		,
		--[[ 3 ]]		0.63        ,
		--[[ 4 ]]       0.49        ,
		--[[ 5 ]]       0.33        ,
	}
	Tune.FDMult			= 1.5			-- Ratio multiplier (Change this value instead of FinalDrive if car is struggling with torque ; Default = 1)


Prompt: -- Below is the script to make the moving platform work. It won't work if something is wrong with the destination blocks.

Response:
local mainFolder = script.Parent
local platform = mainFolder.Platform
local alignPosition = platform.AlignPosition


Prompt: -- Bind Events

Response:
CaptureFlag.Event:connect(OnCaptureFlag)
ReturnFlag.Event:connect(OnReturnFlag)

return GameManager


Prompt: -- Loop through all players when model added

Response:
for _, player in pairs(game.Players:GetPlayers()) do
	addMyLocalScript(player)
end


Prompt:
--[=[
	Yields the current thread until the given Promise completes. Returns the the values that the promise resolved with.

	```lua
	local worked = pcall(function()
		print("got", getTheValue():expect())
	end)

	if not worked then
		warn("it failed")
	end
	```

	This is essentially sugar for:

	```lua
	select(2, assert(promise:await()))
	```

	**Errors** if the Promise rejects or gets cancelled.

	@error any -- Errors with the rejection value if this Promise rejects or gets cancelled.
	@yields
	@return ...any -- The values the Promise resolved with.
]=]

Response:
function Promise.prototype:expect()
	return expectHelper(self:awaitStatus())
end


Prompt: --[[ Reference extension ]]

Response:
--

do
	local ReferenceTypes = {
		Character = {},
		CharacterPart = {}
	}

	local References = {}
	local Objects = {}

	for i,v in pairs(ReferenceTypes) do
		References[i] = {}
		Objects[i] = {}
	end

	function Network:AddReference(key, refType, ...)
		local refInfo = ReferenceTypes[refType]
		assert(refInfo, "Invalid Reference Type")

		local refData = {
			Type = refType,
			Reference = key,
			Objects = {...},
			Aliases = {}
		}

		References[refType][refData.Reference] = refData

		local last = Objects[refType]
		for _,obj in ipairs(refData.Objects) do
			local list = last[obj] or {}
			last[obj] = list
			last = list
		end

		last.__Data = refData
	end

	function Network:AddReferenceAlias(key, refType, ...)
		local refInfo = ReferenceTypes[refType]
		assert(refInfo, "Invalid Reference Type")

		local refData = References[refType][key]
		if not refData then
			warn("Tried to add an alias to a non-existing reference")
			return
		end

		local objects = {...}
		refData.Aliases[#refData.Aliases + 1] = objects

		local last = Objects[refType]
		for _,obj in ipairs(objects) do
			local list = last[obj] or {}
			last[obj] = list
			last = list
		end

		last.__Data = refData
	end

	function Network:RemoveReference(key, refType)
		local refInfo = ReferenceTypes[refType]
		assert(refInfo, "Invalid Reference Type")

		local refData = References[refType][key]
		if not refData then
			warn("Tried to remove a non-existing reference")
			return
		end

		References[refType][refData.Reference] = nil

		local function rem(parent, objects, index)
			if index <= #objects then
				local key = objects[index]
				local child = parent[key]

				rem(child, objects, index + 1)

				if next(child) == nil then
					parent[key] = nil
				end
			elseif parent.__Data == refData then
				parent.__Data = nil
			end
		end

		local objects = Objects[refData.Type]
		rem(objects, refData.Objects, 1)

		for i,alias in ipairs(refData.Aliases) do
			rem(objects, alias, 1)
		end
	end

	function Network:GetObject(ref, refType)
		assert(ReferenceTypes[refType], "Invalid Reference Type")

		local refData = References[refType][ref]
		if not refData then
			return nil
		end

		return unpack(refData.Objects)
	end

	function Network:GetReference(...)
		local objects = {...}

		local refType = table.remove(objects)
		assert(ReferenceTypes[refType], "Invalid Reference Type")

		local last = Objects[refType]
		for i,v in ipairs(objects) do
			last = last[v]

			if not last then
				break
			end
		end

		local refData = last and last.__Data
		return refData and refData.Reference or nil
	end
end


Prompt: -- KEY IS DOWN --

Response:
UIS.InputBegan:Connect(function(Input, isTyping)
	if isTyping then return end

	if Input.KeyCode == Enum.KeyCode.R then
		if Equipped.Value and Holding.Value == "None" and not Using.Value then
			SkillsHandler:FireServer("Hold", "R")
		end
	end
end)


Prompt: -- ROBLOX deviation: omitting imports for file system interaction

Response:
local CurrentModule = script
local Packages = CurrentModule.Parent


Prompt:
-- Explicit dependencies are dependencies that are are explicitly listed.
-- These dependencies are available to this package and ANY dependent packages below

Response:
function PackageInfoUtils.fillExplicitPackageDependencySet(explicitDependencySet, packageFolder, packageInfoMap)
	assert(type(explicitDependencySet) == "table", "Bad explicitDependencySet")
	assert(typeof(packageFolder) == "Instance", "Bad packageFolder")
	assert(type(packageInfoMap) == "table", "Bad packageInfoMap")

	for _, item in pairs(packageFolder:GetChildren()) do
		if item:IsA("Folder") and item.Name == ScriptInfoUtils.DEPENDENCY_FOLDER_NAME then
			for _, packageInfo in pairs(PackageInfoUtils.getPackageInfoListFromDependencyFolder(item, packageInfoMap)) do
				explicitDependencySet[packageInfo] = true
			end
		end
	end
end

return PackageInfoUtils


Prompt: -- Container for temporary connections (disconnected automatically)

Response:
local Connections = {};

function LightingTool.Equip()
	-- Enables the tool's equipped functionality

	-- Start up our interface
	ShowUI();
	EnableSurfaceClickSelection();

end;

function LightingTool.Unequip()
	-- Disables the tool's equipped functionality

	-- Clear unnecessary resources
	HideUI();
	ClearConnections();

end;

function ClearConnections()
	-- Clears out temporary connections

	for ConnectionKey, Connection in pairs(Connections) do
		Connection:Disconnect();
		Connections[ConnectionKey] = nil;
	end;

end;

function ShowUI()
	-- Creates and reveals the UI

	-- Reveal UI if already created
	if LightingTool.UI then

		-- Reveal the UI
		LightingTool.UI.Visible = true;

		-- Update the UI every 0.1 seconds
		UIUpdater = Support.ScheduleRecurringTask(UpdateUI, 0.1);

		-- Skip UI creation
		return;

	end;

	-- Create the UI
	LightingTool.UI = Core.Tool.Interfaces.BTLightingToolGUI:Clone();
	LightingTool.UI.Parent = Core.UI;
	LightingTool.UI.Visible = true;

	-- Enable each light type UI
	EnableLightSettingsUI(LightingTool.UI.PointLight);
	EnableLightSettingsUI(LightingTool.UI.SpotLight);
	EnableLightSettingsUI(LightingTool.UI.SurfaceLight);

	-- Update the UI every 0.1 seconds
	UIUpdater = Support.ScheduleRecurringTask(UpdateUI, 0.1);

end;

function EnableSurfaceClickSelection(LightType)
	-- Allows for the setting of the face for the given light type by clicking

	-- Clear out any existing connection
	if Connections.SurfaceClickSelection then
		Connections.SurfaceClickSelection:Disconnect();
		Connections.SurfaceClickSelection = nil;
	end;

	-- Add the new click connection
	Connections.SurfaceClickSelection = Core.Mouse.Button1Down:Connect(function ()
		local _, ScopeTarget = Core.Targeting:UpdateTarget()
		if Selection.IsSelected(ScopeTarget) then
			SetSurface(LightType, Core.Mouse.TargetSurface)
		end
	end)

end;

function EnableLightSettingsUI(LightSettingsUI)
	-- Sets up the UI for the given light type settings UI

	-- Get the type of light this settings UI is for
	local LightType = LightSettingsUI.Name;

	-- Option input references
	local Options = LightSettingsUI.Options;
	local RangeInput = Options.RangeOption.Input.TextBox;
	local BrightnessInput = Options.BrightnessOption.Input.TextBox;
	local ColorPicker = Options.ColorOption.HSVPicker;
	local ShadowsCheckbox = Options.ShadowsOption.Checkbox;

	-- Add/remove/show button references
	local AddButton = LightSettingsUI.AddButton;
	local RemoveButton = LightSettingsUI.RemoveButton;
	local ShowButton = LightSettingsUI.ArrowButton;

	-- Enable range input
	RangeInput.FocusLost:Connect(function ()
		SetRange(LightType, tonumber(RangeInput.Text));
	end);

	-- Enable brightness input
	BrightnessInput.FocusLost:Connect(function ()
		SetBrightness(LightType, tonumber(BrightnessInput.Text));
	end);

	-- Enable color input
	ColorPicker.MouseButton1Click:Connect(function ()
		Core.Cheer(Core.Tool.Interfaces.BTHSVColorPicker, Core.UI).Start(
			Support.IdentifyCommonProperty(GetLights(LightType), 'Color') or Color3.new(1, 1, 1),
			function (Color) SetColor(LightType, Color) end,
			Core.Targeting.CancelSelecting
		);
	end);

	-- Enable shadows input
	ShadowsCheckbox.MouseButton1Click:Connect(function ()
		ToggleShadows(LightType);
	end);

	-- Enable light addition button
	AddButton.MouseButton1Click:Connect(function ()
		AddLights(LightType);
	end);

	-- Enable light removal button
	RemoveButton.MouseButton1Click:Connect(function ()
		RemoveLights(LightType);
	end);

	-- Enable light options UI show button
	ShowButton.MouseButton1Click:Connect(function ()
		OpenLightOptions(LightType);
	end);

	-- Enable light type-specific features
	if LightType == 'SpotLight' or LightType == 'SurfaceLight' then

		-- Create a surface selection dropdown
		Surfaces = { 'Top', 'Bottom', 'Front', 'Back', 'Left', 'Right' };
		local SurfaceDropdown = Core.Cheer(Options.SideOption.Dropdown).Start(Surfaces, '', function (Surface)
			SetSurface(LightType, Enum.NormalId[Surface]);
		end);

		-- Enable angle input
		local AngleInput = Options.AngleOption.Input.TextBox;
		AngleInput.FocusLost:Connect(function ()
			SetAngle(LightType, tonumber(AngleInput.Text));
		end);

	end;

end;

function HideUI()
	-- Hides the tool UI

	-- Make sure there's a UI
	if not LightingTool.UI then
		return;
	end;

	-- Hide the UI
	LightingTool.UI.Visible = false;

	-- Stop updating the UI
	UIUpdater:Stop();

end;

function GetLights(LightType)
	-- Returns all the lights of the given type in the selection

	local Lights = {};

	-- Get any lights from any selected parts
	for _, Part in pairs(Selection.Parts) do
		table.insert(Lights, Support.GetChildOfClass(Part, LightType));
	end;

	-- Return the lights
	return Lights;

end;


Prompt: -- Private Functions --

Response:
function getMotorVelocity( motor )
	return motor.Attachment1.WorldAxis:Dot( motor.Attachment1.Parent.RotVelocity )
end


Prompt: --------LEFT DOOR --------

Response:
game.Workspace.doorleft.l12.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)

game.Workspace.doorleft.l23.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l61.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l42.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l72.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l53.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l71.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l31.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)

game.Workspace.doorleft.l11.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l21.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l22.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l32.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l33.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l43.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l51.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l41.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l73.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l52.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l63.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l62.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)
game.Workspace.doorleft.l13.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)

game.Workspace.doorleft.pillar.BrickColor = BrickColor.new(game.Workspace.Lighting.defaultlights.Value)


Prompt:
-- How to install
-- Put the "[FE+] Pedals" script into the Plugins folder
-- Move the "BP","CP" and "GP" groups to fit the interior, and put them in the Misc group
-- Copy and paste the following into MiscWeld under initialize.

Response:
MakeWeld(misc.BP.SS,car.DriveSeat,"Motor",.1)
ModelWeld(misc.BP.Parts,misc.BP.SS)
MakeWeld(misc.GP.SS,car.DriveSeat,"Motor",.1)
ModelWeld(misc.GP.Parts,misc.GP.SS)
MakeWeld(misc.CP.SS,car.DriveSeat,"Motor",.1)
ModelWeld(misc.CP.Parts,misc.CP.SS)


Prompt:
--[[
	Player state. No logic, as server dictates entry and exit in this state.
]]

Response: local PlayerSpectating = {}


Prompt: --[[Weight and CG]]

Response:
	Tune.Weight			= 2200		-- Total weight (in pounds)
	Tune.WeightBSize	= {			-- Size of weight brick (dimmensions in studs ; larger = more stable)
	 --[[Width]]		8		,
	 --[[Height]]		4.5		,
	 --[[Length]]		16		}
	Tune.WeightDist		= 50		-- Weight distribution (0 - on rear wheels, 100 - on front wheels, can be <0 or >100)
	Tune.CGHeight		= .8		-- Center of gravity height (studs relative to median of all wheels)
	Tune.WBVisible		= false		-- Makes the weight brick visible

	--Unsprung Weight
	Tune.FWheelDensity	= .1		-- Front Wheel Density
	Tune.RWheelDensity	= .1		-- Rear Wheel Density
	Tune.FWLgcyDensity	= 1			-- Front Wheel Density [PGS OFF]
	Tune.RWLgcyDensity	= 1			-- Rear Wheel Density [PGS OFF]

	Tune.AxleSize		= 2			-- Size of structural members (larger = more stable/carry more weight)
	Tune.AxleDensity	= .1		-- Density of structural members


Prompt: -- note: maybe use playfab to capture errors

Response:
ClientOrchestration.registerClientComponents = function(config)
	if config.orchestrationTime < ClientOrchestration.lastCalledOrchestrationTime then
		ClientOrchestration._warn("Attempted to orchestrate an older scene on the client: " .. config.name)
		return
	end

	if config.orchestrationTime == ClientOrchestration.lastCalledOrchestrationTime then
		ClientOrchestration._warn(
			"Attempted to orchestrate a scene with same tick time. Double check that you're not loading a scene 2x"
		)
		ClientOrchestration._warn(config.name)
		return
	end

	if config.schema.Client == nil then
		ClientOrchestration._warn(
			"No schema Client file provided on the client for scene: " .. config.name .. ". Is this intended?"
		)
		return
	end

	ClientOrchestration.isSeekable = false

	ClientOrchestration.lastCalledOrchestrationTime = config.orchestrationTime
	ClientOrchestration.cleanUp()

	local schema = ClientOrchestration._require(config.schema.Client)
	local SchemaProcessor = ClientOrchestration._require(config.schemaProcessor)
	ClientOrchestration.SchemaProcessorInstance = SchemaProcessor.new(schema, config.timePosition)

	-- Run setup before processing
	local setupSuccess = ClientOrchestration.setupSchema()

	if config.orchestrationTime < ClientOrchestration.lastCalledOrchestrationTime then
		ClientOrchestration._warn("No longer processing outdated scene: " .. config.name)
		return
	end

	if setupSuccess then
		ClientOrchestration.processSchema()
	end

	if config.orchestrationTime < ClientOrchestration.lastCalledOrchestrationTime then
		ClientOrchestration._warn("No longer processing outdated scene: " .. config.name)
		return
	end

	local name = config.name or "Default"
	-- If the player has seek permissions, then update the seek UI
	ClientOrchestration.ClientSceneMetadataEvent:Fire(
		"Pass",
		name,
		ClientOrchestration.SchemaProcessorInstance.timePosition,
		config.timeLength
	)

	if ClientOrchestration.ClientSceneMetadataRequestConnection then
		ClientOrchestration.ClientSceneMetadataRequestConnection:Disconnect()
	end

	ClientOrchestration.ClientSceneMetadataRequestConnection =
		ClientOrchestration.ClientSceneMetadataEvent.Event:Connect(
			function(Type)
				if Type == "Request" then
					ClientOrchestration.ClientSceneMetadataEvent:Fire(
						"Pass",
						name,
						ClientOrchestration.SchemaProcessorInstance.timePosition,
						config.timeLength
					)
				end
			end
		)
end

ClientOrchestration.seek = function(timeToPlay)
	local lastCalledOrchestrationTime = ClientOrchestration.lastCalledOrchestrationTime

	while not ClientOrchestration.isSeekable do
		local wasNewSceneCalled = lastCalledOrchestrationTime ~= ClientOrchestration.lastCalledOrchestrationTime
		if wasNewSceneCalled then
			ClientOrchestration._warn("New scene orchestrating, cancelling seek")
			return
		end
		ClientOrchestration.taskLib.wait()
	end

	if ClientOrchestration.SchemaProcessorInstance == nil then
		ClientOrchestration._warn("Schema Processor Instance hasn't been created on client")
		return
	end

	ClientOrchestration.cleanUp()

	-- This is in Process fires faster than setTime has replicated for the client
	ClientOrchestration.SchemaProcessorInstance.timePosition.Value = timeToPlay
	ClientOrchestration.processSchema()
end

local hasBeenCalled = false
return function(stubs)
	if hasBeenCalled then
		error("Client Orchestration has already been called")
		return
	end

	-- Used for testing only
	if stubs then
		for i, v in pairs(stubs) do
			ClientOrchestration[i] = v
		end
	end

	ClientOrchestration.SendMediaControllerConfig.OnClientEvent:Connect(ClientOrchestration.registerClientComponents)
	ClientOrchestration.SeekPermissionsEvent.OnClientEvent:Connect(ClientOrchestration.handleSeekPermissionsEvent)
	ClientOrchestration.Seek.OnClientEvent:Connect(ClientOrchestration.seek)
	ClientOrchestration.SceneEnded.OnClientEvent:Connect(ClientOrchestration.handleSceneEnded)

	hasBeenCalled = true

	return ClientOrchestration
end


Prompt: --Change the value \/

Response:
local flinginess = 50 --CHANGE THIS VALUE TO AFFECT FLING

local flng = flinginess
local negflng = flinginess * -1


Prompt:
--[[
	Create a promise that represents the immediately rejected value.
]]

Response:
function Promise.reject(...)
	local length, values = pack(...)
	return Promise._new(debug.traceback(nil, 2), function(_, reject)
		reject(unpack(values, 1, length))
	end)
end
Promise.Reject = Promise.reject


Prompt: --// Module LoadOrder List; Core modules need to be loaded in a specific order; If you create new "Core" modules make sure you add them here or they won't load

Response:
local LoadingOrder = {
	--// Nearly all modules rely on these to function
	"Logs";
	"Variables";
	"Functions";
a
	--// Core functionality
	"Core";
	"Remote";
	"Process";

	--// Misc
	"Admin";
	"HTTP";
	"Anti";
	"Commands";
}