SupportLibrary={}function SupportLibrary.FindTableOccurrences(g,w)local v={}for g,A in pairs(g)do if A==w then table.insert(v,g)end end return v end function SupportLibrary.FindTableOccurrence(g,w)for g,v in pairs(g)do if v==w then return g end end return nil end function SupportLibrary.IsInTable(g,w)for g,v in pairs(g)do if v==w then return true end end return false end function SupportLibrary.DoTablesMatch(g,w)for v in pairs(g)do if g[v]~=w[v]then return false end end for v in pairs(w)do if w[v]~=g[v]then return false end end return true end function SupportLibrary.Round(g,w)if type(g)~="\110\117\109\098\101\114"then return end local v=10^(w or 0)local A=math.floor(g*v+.5)/v return A end function SupportLibrary.CloneTable(g)local w={}for g,v in pairs(g)do w[g]=v end return w end function SupportLibrary.Merge(g,...)local w={...}for w,v in ipairs(w)do for w,v in pairs(v)do g[w]=v end end return g end local g=newproxy(true)SupportLibrary.Blank=g;(getmetatable(g)).__tostring=function()return"\083\121\109\098\111\108\040\066\108\097\110\107\041"end function SupportLibrary.MergeWithBlanks(w,...)local v={...}for v,A in ipairs(v)do for v,A in pairs(A)do if A==g then w[v]=nil else w[v]=A end end end return w end function SupportLibrary.GetAllDescendants(g)local w={}for g,v in pairs(g:GetChildren())do table.insert(w,v)for g,v in pairs(SupportLibrary.GetAllDescendants(v))do table.insert(w,v)end end return w end function SupportLibrary.GetDescendantsWhichAreA(g,w)local v={}for g,A in pairs(g:GetDescendants())do if A:IsA(w)then v[#v+1]=A end end return v end function SupportLibrary.FilterArray(g,w)local v={}for g,A in ipairs(g)do if w(A,g)then table.insert(v,A)end end return v end function SupportLibrary.FilterMap(g,w)local v={}for g,A in ipairs(g)do if w(A,g)then v[g]=A end end return v end function SupportLibrary.GetDescendantCount(g)local w=0 for g,v in pairs(g:GetChildren())do w=w+1 w=w+SupportLibrary.GetDescendantCount(v)end return w end function SupportLibrary.CloneParts(g)local w={}for g,v in pairs(g)do w[g]=v:Clone()end return w end function SupportLibrary.SplitString(g,w)local v={}local A=("\040\091\094\037\115\093\043\041"):format(w)g:gsub(A,function(g)table.insert(v,g)end)return v end function SupportLibrary.GetChildOfClass(g,w,v)if not v then for g,v in pairs(g:GetChildren())do if v.ClassName==w then return v end end else for g,v in pairs(g:GetChildren())do if v:IsA(w)then return v end end end return nil end function SupportLibrary.GetChildrenOfClass(g,w,v)local A={}if not v then for g,v in pairs(g:GetChildren())do if v.ClassName==w then table.insert(A,v)end end else for g,v in pairs(g:GetChildren())do if v:IsA(w)then table.insert(A,v)end end end return A end function SupportLibrary.HSVToRGB(g,w,v)if w==0 then return v end local A=math.floor(g/60)local C=g/60-A local Q=v*(1-w)local t=v*(1-w*C)local c=v*(1-w*(1-C))if A==0 then return v,c,Q elseif A==1 then return t,v,Q elseif A==2 then return Q,v,c elseif A==3 then return Q,t,v elseif A==4 then return c,Q,v elseif A==5 then return v,Q,t end end function SupportLibrary.RGBToHSV(g,w,v)local A,C,Q local t=math.min(g,w,v)local c=math.max(g,w,v)Q=c local U=c-t if c~=0 then C=U/c else C=0 A=-1 return A,C,Q end if g==c then A=(w-v)/U elseif w==c then A=2+(v-g)/U else A=4+(g-w)/U end A=A*60 if A<0 then A=A+360 end return A,C,Q end function SupportLibrary.IdentifyCommonItem(g)local w=nil for g,v in pairs(g)do if g==1 then w=v else if v~=w then return nil end end end return w end function SupportLibrary.IdentifyCommonProperty(g,w)local v={}for g,A in pairs(g)do table.insert(v,A[w])end return SupportLibrary.IdentifyCommonItem(v)end function SupportLibrary.GetPartCorners(g)local w=table.insert local v=(CFrame.new()).toWorldSpace local A=CFrame.new local C=g.CFrame local Q,t,c=g.Size.x/2,g.Size.y/2,g.Size.z/2 local U={}w(U,v(C,A(Q,t,c)))w(U,v(C,A(-Q,t,c)))w(U,v(C,A(Q,-t,c)))w(U,v(C,A(Q,t,-c)))w(U,v(C,A(-Q,t,-c)))w(U,v(C,A(-Q,-t,c)))w(U,v(C,A(Q,-t,-c)))w(U,v(C,A(-Q,-t,-c)))return U end function SupportLibrary.GetListMembers(g,w)local v={}for g,A in ipairs(g)do v[g]=A[w]end return v end function SupportLibrary.GetMemberMap(g,w)local v={}for g,A in ipairs(g)do v[A]=A[w]end return v end function SupportLibrary.AddUserInputListener(g,w,v,A)local C={}if type(w)=="\115\116\114\105\110\103"then C[w]=true elseif type(w)=="\116\097\098\108\101"then C=SupportLibrary.FlipTable(w)end return(Game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101"))["\073\110\112\117\116"..g]:Connect(function(g,w)if w and not v then return end if not C[g.UserInputType.Name]then return end if InputType==Enum.UserInputType.Keyboard and(Game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101")):GetFocusedTextBox()then return end A(g)end)end function SupportLibrary.AddGuiInputListener(g,w,v,A,C)local Q={}if type(v)=="\115\116\114\105\110\103"then Q[v]=true elseif type(v)=="\116\097\098\108\101"then Q=SupportLibrary.FlipTable(v)end return g["\073\110\112\117\116"..w]:Connect(function(g,w)if w and not A then return end if not Q[g.UserInputType.Name]then return end C(g)end)end function SupportLibrary.AreKeysPressed(...)local g=0 local w=SupportLibrary.GetListMembers((Game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101")):GetKeysPressed(),"\075\101\121\067\111\100\101")for v,A in pairs({...})do if SupportLibrary.IsInTable(w,A)then g=g+1 end end return g==#{...}end function SupportLibrary.ConcatTable(g,...)local w={...}for w,v in ipairs(w)do for w,v in ipairs(v)do table.insert(g,v)end end return g end function SupportLibrary.ClearTable(g)for w in pairs(g)do g[w]=nil end return g end function SupportLibrary.Values(g)local w={}for g,v in pairs(g)do table.insert(w,v)end return w end function SupportLibrary.Keys(g)local w={}for g in pairs(g)do table.insert(w,g)end return w end function SupportLibrary.Call(g,...)local w={...}return function(...)return g(unpack(SupportLibrary.ConcatTable({},w,{...})))end end function SupportLibrary.Trim(g)return g:gsub("\094\037\115\042\040\046-\041\037\115\042\036","\037\049")end function SupportLibrary.ChainCall(...)local g={...}return function(...)local w={...}for g,v in ipairs(g)do w={v(unpack(w))}end return unpack(w)end end function SupportLibrary.CountKeys(g)local w=0 for g in pairs(g)do w=w+1 end return w end function SupportLibrary.Slice(g,w,v)local A={}for w=w,v,1 do table.insert(A,g[w])end return A end function SupportLibrary.FlipTable(g)local w={}for g,v in pairs(g)do w[v]=g end return w end function SupportLibrary.ScheduleRecurringTask(g,w)local v={Running=true;Stop=function(g)g.Running=false end,TaskFunction=g;Interval=w};(coroutine.wrap(function(g)while wait(g.Interval)and g.Running do g.TaskFunction()end end))(v)return v end function SupportLibrary.Loop(g,w,...)local v={...}local A=true local C=function()A=nil end;(coroutine.wrap(function()while wait(g)and A do w(unpack(v))end end))()return C end function SupportLibrary.Clamp(g,w,v)if w and g<w then g=w elseif v and g>v then g=v end return g end function SupportLibrary.ReverseTable(g)local w={}for v,A in ipairs(g)do w[(#g-v)+1]=A end return w end function SupportLibrary.CreateConsecutiveCallDeferrer(g)local w local function v()local v=os.time()w=v wait(g)return w==v end return v end return SupportLibrary
SupportLibrary = {}
-- TODO: needs cleanup
function SupportLibrary.FindTableOccurrences(Haystack, Needle)
	-- Returns the positions of instances of `needle` in table `haystack`

	local Positions = {}

	-- Add any indexes from `Haystack` that are `Needle`
	for Index, Value in pairs(Haystack) do
		if Value == Needle then
			table.insert(Positions, Index)
		end
	end

	return Positions
end

function SupportLibrary.FindTableOccurrence(Haystack, Needle)
	-- Returns one occurrence of `Needle` in `Haystack`

	-- Search for the first instance of `Needle` found and return it
	for Index, Value in pairs(Haystack) do
		if Value == Needle then
			return Index
		end
	end

	-- If no occurrences exist, return `nil`
	return nil
end

function SupportLibrary.IsInTable(Haystack, Needle)
	-- Returns whether the given `Needle` can be found within table `Haystack`

	-- Go through every value in `Haystack` and return whether `Needle` is found
	for _, Value in pairs(Haystack) do
		if Value == Needle then
			return true
		end
	end

	-- If no instances were found, return false
	return false
end

function SupportLibrary.DoTablesMatch(A, B)
	-- Returns whether the values of tables A and B are the same

	-- Check B table differences
	for Index in pairs(A) do
		if A[Index] ~= B[Index] then
			return false
		end
	end

	-- Check A table differences
	for Index in pairs(B) do
		if B[Index] ~= A[Index] then
			return false
		end
	end

	-- Return true if no differences
	return true
end

function SupportLibrary.Round(Number, Places)
	-- Returns `Number` rounded to the given number of decimal places (from lua-users)

	-- Ensure that `Number` is a number
	if type(Number) ~= 'number' then return end

	-- Round the number
	local Multiplier = 10 ^ (Places or 0)
	local RoundedNumber = math.floor(Number * Multiplier + 0.5) / Multiplier

	-- Return the rounded number
	return RoundedNumber
end

function SupportLibrary.CloneTable(Table)
	-- Returns a copy of `Table`

	local ClonedTable = {}

	-- Copy all values into `ClonedTable`
	for Key, Value in pairs(Table) do
		ClonedTable[Key] = Value
	end

	-- Return the clone
	return ClonedTable
end

function SupportLibrary.Merge(Target, ...)
	-- Copies members of the given tables into the specified target table

	local Tables = { ... }

	-- Copy members from each table into target
	for TableOrder, Table in ipairs(Tables) do
		for Key, Value in pairs(Table) do
			Target[Key] = Value
		end
	end

	-- Return target
	return Target
end

-- Create symbol representing a blank value
local Blank = newproxy(true)
SupportLibrary.Blank = Blank
getmetatable(Blank).__tostring = function()
	return 'Symbol(Blank)'
end

function SupportLibrary.MergeWithBlanks(Target, ...)
	-- Copies members of the given tables into the specified target table, including blank values

	local Tables = { ... }

	-- Copy members from each table into target
	for TableOrder, Table in ipairs(Tables) do
		for Key, Value in pairs(Table) do
			if Value == Blank then
				Target[Key] = nil
			else
				Target[Key] = Value
			end
		end
	end

	-- Return target
	return Target
end

function SupportLibrary.GetAllDescendants(Parent)
	-- Recursively gets all the descendants of `Parent` and returns them

	local Descendants = {}

	for _, Child in pairs(Parent:GetChildren()) do
		-- Add the direct descendants of `Parent`
		table.insert(Descendants, Child)

		-- Add the descendants of each child
		for _, Subchild in pairs(SupportLibrary.GetAllDescendants(Child)) do
			table.insert(Descendants, Subchild)
		end
	end

	return Descendants
end

function SupportLibrary.GetDescendantsWhichAreA(Object, Class)
	-- Returns descendants of `Object` which match `Class`

	local Matches = {}

	-- Check each descendant
	for _, Descendant in pairs(Object:GetDescendants()) do
		if Descendant:IsA(Class) then
			Matches[#Matches + 1] = Descendant
		end
	end

	-- Return matches
	return Matches
end

function SupportLibrary.FilterArray(Array, Callback)
	-- Returns a filtered copy of `Array` based on the filter `Callback`

	local FilteredArray = {}

	-- Add items from `Array` that `Callback` returns `true` on
	for Key, Value in ipairs(Array) do
		if Callback(Value, Key) then
			table.insert(FilteredArray, Value)
		end
	end

	return FilteredArray
end

function SupportLibrary.FilterMap(Map, Callback)
	-- Returns a filtered copy of `Map` based on the filter `Callback`

	local FilteredMap = {}

	-- Add items from `Map` that `Callback` returns `true` on
	for Key, Value in ipairs(Map) do
		if Callback(Value, Key) then
			FilteredMap[Key] = Value
		end
	end

	return FilteredMap
end

function SupportLibrary.GetDescendantCount(Parent)
	-- Recursively gets a count of all the descendants of `Parent` and returns them

	local Count = 0

	for _, Child in pairs(Parent:GetChildren()) do
		-- Count the direct descendants of `Parent`
		Count = Count + 1

		-- Count and add the descendants of each child
		Count = Count + SupportLibrary.GetDescendantCount(Child)
	end

	return Count
end

function SupportLibrary.CloneParts(Parts)
	-- Returns a table of cloned `Parts`

	local Clones = {}

	-- Copy the parts into `Clones`
	for Index, Part in pairs(Parts) do
		Clones[Index] = Part:Clone()
	end

	return Clones
end

function SupportLibrary.SplitString(String, Delimiter)
	-- Returns a table of string `String` split by pattern `Delimiter`

	local StringParts = {}
	local Pattern = ('([^%s]+)'):format(Delimiter)

	-- Capture each separated part
	String:gsub(Pattern, function(Part)
		table.insert(StringParts, Part)
	end)

	return StringParts
end

function SupportLibrary.GetChildOfClass(Parent, ClassName, Inherit)
	-- Returns the first child of `Parent` that is of class `ClassName`
	-- or nil if it couldn't find any

	-- Look for a child of `Parent` of class `ClassName` and return it
	if not Inherit then
		for _, Child in pairs(Parent:GetChildren()) do
			if Child.ClassName == ClassName then
				return Child
			end
		end
	else
		for _, Child in pairs(Parent:GetChildren()) do
			if Child:IsA(ClassName) then
				return Child
			end
		end
	end

	return nil
end

function SupportLibrary.GetChildrenOfClass(Parent, ClassName, Inherit)
	-- Returns a table containing the children of `Parent` that are
	-- of class `ClassName`

	local Matches = {}

	if not Inherit then
		for _, Child in pairs(Parent:GetChildren()) do
			if Child.ClassName == ClassName then
				table.insert(Matches, Child)
			end
		end
	else
		for _, Child in pairs(Parent:GetChildren()) do
			if Child:IsA(ClassName) then
				table.insert(Matches, Child)
			end
		end
	end

	return Matches
end

function SupportLibrary.HSVToRGB(Hue, Saturation, Value)
	-- Returns the RGB equivalent of the given HSV-defined color
	-- (adapted from some code found around the web)

	-- If it's achromatic, just return the value
	if Saturation == 0 then
		return Value
	end

	-- Get the hue sector
	local HueSector = math.floor(Hue / 60)
	local HueSectorOffset = (Hue / 60) - HueSector

	local P = Value * (1 - Saturation)
	local Q = Value * (1 - Saturation * HueSectorOffset)
	local T = Value * (1 - Saturation * (1 - HueSectorOffset))

	if HueSector == 0 then
		return Value, T, P
	elseif HueSector == 1 then
		return Q, Value, P
	elseif HueSector == 2 then
		return P, Value, T
	elseif HueSector == 3 then
		return P, Q, Value
	elseif HueSector == 4 then
		return T, P, Value
	elseif HueSector == 5 then
		return Value, P, Q
	end
end

function SupportLibrary.RGBToHSV(Red, Green, Blue)
	-- Returns the HSV equivalent of the given RGB-defined color
	-- (adapted from some code found around the web)

	local Hue, Saturation, Value

	local MinValue = math.min(Red, Green, Blue)
	local MaxValue = math.max(Red, Green, Blue)

	Value = MaxValue

	local ValueDelta = MaxValue - MinValue

	-- If the color is not black
	if MaxValue ~= 0 then
		Saturation = ValueDelta / MaxValue

		-- If the color is purely black
	else
		Saturation = 0
		Hue = -1
		return Hue, Saturation, Value
	end

	if Red == MaxValue then
		Hue = (Green - Blue) / ValueDelta
	elseif Green == MaxValue then
		Hue = 2 + (Blue - Red) / ValueDelta
	else
		Hue = 4 + (Red - Green) / ValueDelta
	end

	Hue = Hue * 60
	if Hue < 0 then
		Hue = Hue + 360
	end

	return Hue, Saturation, Value
end

function SupportLibrary.IdentifyCommonItem(Items)
	-- Returns the common item in table `Items`, or `nil` if
	-- they vary

	local CommonItem = nil

	for ItemIndex, Item in pairs(Items) do
		-- Set the initial item to compare against
		if ItemIndex == 1 then
			CommonItem = Item

			-- Check if this item is the same as the rest
			-- If it isn't the same, there is no common item, so just stop right here
		else
			if Item ~= CommonItem then
				return nil
			end
		end
	end

	-- Return the common item
	return CommonItem
end

function SupportLibrary.IdentifyCommonProperty(Items, Property)
	-- Returns the common `Property` value in the instances given in `Items`

	local PropertyVariations = {}

	-- Capture all the variations of the property value
	for _, Item in pairs(Items) do
		table.insert(PropertyVariations, Item[Property])
	end

	-- Return the common property value
	return SupportLibrary.IdentifyCommonItem(PropertyVariations)
end

function SupportLibrary.GetPartCorners(Part)
	-- Returns a table of the given part's corners' CFrames

	-- Make references to functions called a lot for efficiency
	local Insert = table.insert
	local ToWorldSpace = CFrame.new().toWorldSpace
	local NewCFrame = CFrame.new

	-- Get info about the part
	local PartCFrame = Part.CFrame
	local SizeX, SizeY, SizeZ = Part.Size.x / 2, Part.Size.y / 2, Part.Size.z / 2

	-- Get each corner
	local Corners = {}
	Insert(Corners, ToWorldSpace(PartCFrame, NewCFrame(SizeX, SizeY, SizeZ)))
	Insert(Corners, ToWorldSpace(PartCFrame, NewCFrame(-SizeX, SizeY, SizeZ)))
	Insert(Corners, ToWorldSpace(PartCFrame, NewCFrame(SizeX, -SizeY, SizeZ)))
	Insert(Corners, ToWorldSpace(PartCFrame, NewCFrame(SizeX, SizeY, -SizeZ)))
	Insert(Corners, ToWorldSpace(PartCFrame, NewCFrame(-SizeX, SizeY, -SizeZ)))
	Insert(Corners, ToWorldSpace(PartCFrame, NewCFrame(-SizeX, -SizeY, SizeZ)))
	Insert(Corners, ToWorldSpace(PartCFrame, NewCFrame(SizeX, -SizeY, -SizeZ)))
	Insert(Corners, ToWorldSpace(PartCFrame, NewCFrame(-SizeX, -SizeY, -SizeZ)))

	return Corners
end

function SupportLibrary.GetListMembers(List, MemberName)
	-- Gets the given member for each object in the given list table

	local Members = {}

	-- Collect the member values for each item in the list
	for Key, Item in ipairs(List) do
		Members[Key] = Item[MemberName]
	end

	-- Return the members
	return Members
end

function SupportLibrary.GetMemberMap(List, MemberName)
	-- Maps the given items' specified members to each item

	local Map = {}

	-- Collect member values
	for Key, Item in ipairs(List) do
		Map[Item] = Item[MemberName]
	end

	-- Return map
	return Map
end

function SupportLibrary.AddUserInputListener(InputState, InputTypeFilter, CatchAll, Callback)
	-- Connects to the given user input event and takes care of standard boilerplate code

	-- Create input type whitelist
	local InputTypes = {}
	if type(InputTypeFilter) == 'string' then
		InputTypes[InputTypeFilter] = true
	elseif type(InputTypeFilter) == 'table' then
		InputTypes = SupportLibrary.FlipTable(InputTypeFilter)
	end

	-- Create a UserInputService listener based on the given `InputState`
	return Game:GetService('UserInputService')['Input' .. InputState]:Connect(function(

	-- Make sure this input was not captured by the client (unless `CatchAll` is enabled)

	-- Make sure this is the right input type

	-- Make sure any key input did not occur while typing into a UI

	-- Call back upon passing all conditions
	Input,
		GameProcessedEvent
	)
		if GameProcessedEvent and not CatchAll then return end

		if not InputTypes[Input.UserInputType.Name] then return end

		if InputType == Enum.UserInputType.Keyboard and Game:GetService(
			'UserInputService'
		):GetFocusedTextBox() then return end

		Callback(Input)
	end)
end

function SupportLibrary.AddGuiInputListener(Gui, InputState, InputTypeFilter, CatchAll, Callback)
	-- Connects to the given GUI user input event and takes care of standard boilerplate code

	-- Create input type whitelist
	local InputTypes = {}
	if type(InputTypeFilter) == 'string' then
		InputTypes[InputTypeFilter] = true
	elseif type(InputTypeFilter) == 'table' then
		InputTypes = SupportLibrary.FlipTable(InputTypeFilter)
	end

	-- Create a UserInputService listener based on the given `InputState`
	return Gui['Input' .. InputState]:Connect(function(Input, GameProcessedEvent)

	-- Make sure this input was not captured by the client (unless `CatchAll` is enabled)

	-- Make sure this is the right input type

	-- Call back upon passing all conditions
		if GameProcessedEvent and not CatchAll then return end

		if not InputTypes[Input.UserInputType.Name] then return end

		Callback(Input)
	end)
end

function SupportLibrary.AreKeysPressed(...)
	-- Returns whether the given keys are pressed

	local RequestedKeysPressed = 0

	-- Get currently pressed keys
	local PressedKeys =
		SupportLibrary.GetListMembers(
			Game:GetService('UserInputService'):GetKeysPressed(),
			'KeyCode'
		)

	-- Go through each requested key
	for _, Key in pairs({ ... }) do
		-- Count requested keys that are pressed
		if SupportLibrary.IsInTable(PressedKeys, Key) then
			RequestedKeysPressed = RequestedKeysPressed + 1
		end
	end

	-- Return whether all the requested keys are pressed or not
	return RequestedKeysPressed == #{ ... }
end

function SupportLibrary.ConcatTable(TargetTable, ...)
	-- Inserts all values from given source tables into target

	local SourceTables = { ... }

	-- Insert values from each source table into target
	for TableOrder, SourceTable in ipairs(SourceTables) do
		for Key, Value in ipairs(SourceTable) do
			table.insert(TargetTable, Value)
		end
	end

	-- Return the destination table
	return TargetTable
end

function SupportLibrary.ClearTable(Table)
	-- Clears out every value in `Table`

	-- Clear each index
	for Index in pairs(Table) do
		Table[Index] = nil
	end

	-- Return the given table
	return Table
end

function SupportLibrary.Values(Table)
	-- Returns all the values in the given table

	local Values = {}

	-- Go through each key and get each value
	for _, Value in pairs(Table) do
		table.insert(Values, Value)
	end

	-- Return the values
	return Values
end

function SupportLibrary.Keys(Table)
	-- Returns all the keys in the given table

	local Keys = {}

	-- Go through each key and get each value
	for Key in pairs(Table) do
		table.insert(Keys, Key)
	end

	-- Return the values
	return Keys
end

function SupportLibrary.Call(Function, ...)
	-- Returns a callback to `Function` with the given arguments
	local Args = { ... }
	return function(...)
		return Function(unpack(SupportLibrary.ConcatTable({}, Args, { ... })))
	end
end

function SupportLibrary.Trim(String)
	-- Returns a trimmed version of `String` (adapted from code from lua-users)
	return (String:gsub('^%s*(.-)%s*$', '%1'))
end

function SupportLibrary.ChainCall(...)
	-- Returns function that passes arguments through given functions and returns the final result

	-- Get the given chain of functions
	local Chain = { ... }

	-- Return the chaining function
	return function(...)
		-- Get arguments
		local Arguments = { ... }

		-- Go through each function and store the returned data to reuse in the next function's arguments
		for _, Function in ipairs(Chain) do
			Arguments = { Function(unpack(Arguments)) }
		end

		-- Return the final returned data
		return unpack(Arguments)
	end
end

function SupportLibrary.CountKeys(Table)
	-- Returns the number of keys in `Table`

	local Count = 0

	-- Count each key
	for _ in pairs(Table) do
		Count = Count + 1
	end

	-- Return the count
	return Count
end

function SupportLibrary.Slice(Table, Start, End)
	-- Returns values from `Start` to `End` in `Table`

	local Slice = {}

	-- Go through the given indices
	for Index = Start, End do
		table.insert(Slice, Table[Index])
	end

	-- Return the slice
	return Slice
end

function SupportLibrary.FlipTable(Table)
	-- Returns a table with keys and values in `Table` swapped

	local FlippedTable = {}

	-- Flip each key and value
	for Key, Value in pairs(Table) do
		FlippedTable[Value] = Key
	end

	-- Return the flipped table
	return FlippedTable
end

function SupportLibrary.ScheduleRecurringTask(TaskFunction, Interval)
	-- Repeats `Task` every `Interval` seconds until stopped

	-- Create a task object
	local Task = {
		-- A switch determining if it's running or not
		Running = true,
		-- A function to stop this task
		Stop = function(Task)
			Task.Running = false
		end,
		-- References to the task function and set interval
		TaskFunction = TaskFunction,
		Interval = Interval,
	}

	coroutine.wrap(function(Task)

	-- Repeat the task
		while wait(Task.Interval) and Task.Running do
			Task.TaskFunction()
		end
	end)(Task)

	-- Return the task object
	return Task
end

function SupportLibrary.Loop(Interval, Function, ...)
	-- Calls the given function repeatedly at the specified interval until stopped

	local Args = { ... }

	-- Create state
	local Running = true
	local Stop = function()
		Running = nil
	end

	-- Start loop
	coroutine.wrap(function()
		while wait(Interval) and Running do
			Function(unpack(Args))
		end
	end)()

	-- Return stopping callback
	return Stop
end

function SupportLibrary.Clamp(Number, Minimum, Maximum)
	-- Returns the given number, clamped according to the provided min/max

	-- Clamp the number
	if Minimum and Number < Minimum then
		Number = Minimum
	elseif Maximum and Number > Maximum then
		Number = Maximum
	end

	-- Return the clamped number
	return Number
end

function SupportLibrary.ReverseTable(Table)
	-- Returns a new table with values in the opposite order

	local ReversedTable = {}

	-- Copy each value at the opposite key
	for Index, Value in ipairs(Table) do
		ReversedTable[#Table - Index + 1] = Value
	end

	-- Return the reversed table
	return ReversedTable
end

function SupportLibrary.CreateConsecutiveCallDeferrer(MaxInterval)
	-- Returns a callback for determining whether to execute consecutive calls

	local LastCallTime
	local function ShouldExecuteCall()
		-- Mark latest call time
		local CallTime = os.time()
		LastCallTime = CallTime

		-- Indicate whether call still latest
		wait(MaxInterval)
		return LastCallTime == CallTime
	end

	-- Return callback
	return ShouldExecuteCall
end

return SupportLibrary