Pinkstack/roblox-luau-corpus-text huggingface dataset:
--[[
	~= EXAMPLE CODE =~
	return function(gui,gTable,guiData)
		local name = gTable.Name
		if name == "YesNoPrompt" then
			local new = Instance.new("ScreenGui")
			local frame = Instance.new("Frame",new)
			frame.Size = UDim2.new(0,400,0,400)
			local yes = Instance.new("TextButton",frame)
			yes.Size = UDim2.new(0.5,0,1,0)
			yes.Text = "Yes"
			local no = yes:Clone()
			no.Text = "No"
			no.Position = UDim2.new(0.5,0,0,0)
			
			local gTable,gIndex = client.UI.Register(new)
			
			local ans
			local waiting = true
			
			gTable.CustomDestroy = function()
				waiting = false
			end
			
			yes.MouseButton1Click:Connect(function()
				ans = "Yes"
				gTable:Destroy()
			end)
			
			no.MouseButton1Click:Connect(function()
				ans = "No"
				gTable:Destroy()
			end)
			
			repeat wait() until ans or not waiting  --// Wait until answer
			return ans or false
		end
	end
	
--]]



service = nil
client = nil

return function(gui: ScreenGui, guiData, gTable)
	local TWEEN_TIME = 2
	local SEQUENCE = {
		Color3.fromRGB(255, 85, 88), 
		Color3.fromRGB(78, 140, 255), 
		Color3.fromRGB(78, 255, 149)
	}
	local CLASSES = {
		Frame = true;
		TextBox = true;
		TextLabel = true;
		TextButton = true;
		ImageLabel = true;
		ImageButton = true; 
		ScrollingFrame = true;
	}
	
	local contents = {}
	local OrgColors = {}
	
	local function getCont(obj)
		for _, v in obj:GetChildren() do 
			if CLASSES[v.ClassName] then
				local OrgColor = {}
				OrgColor.Background = v.BackgroundColor3
				if v:IsA("ImageLabel") or v:IsA("ImageButton") then 
					OrgColor.Image = v.ImageColor3 
				end
				OrgColors[v] = OrgColor
				table.insert(contents, v)
				getCont(v)
			end
		end
	end
	
	getCont(gui)
	
	if gTable.Name == "List" then
		gui.Drag.Main.BackgroundTransparency = 0
	end
	
	local function tweenToColor(color1, color2, time)
		local Info = TweenInfo.new(time, Enum.EasingStyle.Linear)
		for _, v in contents do
			local orgcolor = OrgColors[v]
			v.BackgroundColor3 = color1:lerp(orgcolor.Background, 0.75)
			if orgcolor.Image then
				v.ImageColor3 = color1:lerp(orgcolor.Image, 0.75)
				service.TweenService:Create(v, Info, {
					BackgroundColor3 = color2:lerp(orgcolor.Background, 0.75),
					ImageColor3 = color2:lerp(orgcolor.Image, 0.75)
				}):Play()
			else
				service.TweenService:Create(v, Info, {
					BackgroundColor3 = color2:lerp(orgcolor.Background, 0.75)
				}):Play()
			end
		end
		task.wait(time)
	end
	
	service.TrackTask("Thread: Colorize_"..tostring(gTable.Name),function()
		repeat 
			for i in SEQUENCE do
				local one, two = SEQUENCE[i], SEQUENCE[i+1] or SEQUENCE[1]
				
				tweenToColor(one, two, TWEEN_TIME)
			end
		until not task.wait(if gTable.Active then 0 else 1) and gTable.Destroyed
		
	end)
end
-- Push dedented lines of markup onto output and return true;
-- otherwise return false because:
-- * props include a multiline string
-- * text has more than one adjacent line
-- * markup does not close


function dedentMarkup(input: Array<string>, output: Array<string>): boolean
	local line = input[#output + 1]

	if not dedentStartTag(input, output) then
		return false
	end

	if string.find(input[#output], "/>") then
		return true
	end

	local isText = false
	local stack: Array<number> = {}
	table.insert(stack, getIndentationLength(line))

	while #stack > 0 and #output < #input do
		line = input[#output + 1]

		if isFirstLineOfTag(line) then
			if string.find(line, "</") then
				table.insert(output, dedentLine(line))
				table.remove(stack)
			else
				if not dedentStartTag(input, output) then
					return false
				end

				if not string.find(input[#output], "/>") then
					table.insert(stack, getIndentationLength(line))
				end
			end
			isText = false
		else
			if isText then
				return false -- because text has more than one adjacent line
			end

			local getIndentationLengthOfTag = stack[#stack]
			table.insert(output, line:sub(getIndentationLengthOfTag + 3))
			isText = true
		end
	end

	return #stack == 0
end
-------------------------
--| Exposed Functions |--
-------------------------



function PopperCam:Update(EnabledCamera)
	if PopperEnabled then
		-- First, prep some intermediate vars
		local cameraCFrame = Camera.CFrame
		local focusPoint = Camera.Focus.p

		if FFlagUserPortraitPopperFix and SubjectPart then
			focusPoint = SubjectPart.CFrame.p
		end

		local ignoreList = {}
		for _, character in pairs(PlayerCharacters) do
			ignoreList[#ignoreList + 1] = character
		end
		for i = 1, #VehicleParts do
			ignoreList[#ignoreList + 1] = VehicleParts[i]
		end
		
		-- Get largest cutoff distance
		local largest = Camera:GetLargestCutoffDistance(ignoreList)

		-- Then check if the player zoomed since the last frame,
		-- and if so, reset our pop history so we stop tweening
		local zoomLevel = (cameraCFrame.p - focusPoint).Magnitude
		if math_abs(zoomLevel - LastZoomLevel) > 0.001 then
			LastPopAmount = 0
		end
		
		-- Finally, zoom the camera in (pop) by that most-cut-off amount, or the last pop amount if that's more
		local popAmount = largest
		if LastPopAmount > popAmount then
			popAmount = LastPopAmount
		end

		if popAmount > 0 then
			Camera.CFrame = cameraCFrame + (cameraCFrame.lookVector * popAmount)
			LastPopAmount = popAmount - POP_RESTORE_RATE -- Shrink it for the next frame
			if LastPopAmount < 0 then
				LastPopAmount = 0
			end
		end

		LastZoomLevel = zoomLevel
		
		-- Stop shift lock being able to see through walls by manipulating Camera focus inside the wall
		if EnabledCamera and EnabledCamera:GetShiftLock() and not EnabledCamera:IsInFirstPerson() then
			if EnabledCamera:GetCameraActualZoom() < 1 then
				local subjectPosition = EnabledCamera.lastSubjectPosition 
				if subjectPosition then
					Camera.Focus = CFrame_new(subjectPosition)
					Camera.CFrame = CFrame_new(subjectPosition - MIN_CAMERA_ZOOM*EnabledCamera:GetCameraLook(), subjectPosition)
				end
			end
		end
	end
end
-- When tool deselected


function onDeselected(mouse)
	myMouse = nil
end

rayPart					= Instance.new("Part")
rayPart.Name			= "MG Ray"
rayPart.Transparency	= .5
rayPart.Anchored		= true
rayPart.CanCollide		= false
rayPart.TopSurface		= Enum.SurfaceType.Smooth
rayPart.BottomSurface	= Enum.SurfaceType.Smooth
rayPart.formFactor		= Enum.FormFactor.Custom
rayPart.BrickColor		= BrickColor.new("Bright yellow")
rayPart.Reflectance		= 0
rayPart.Material = Enum.Material.SmoothPlastic

function fireCoax()
	local MGAmmo = tankStats.MGAmmo;
	if MGAmmo.Value <= 0 then
		return false;
	end;
	
	local machineGun = parts.Parent.Gun.Coax
	local PL				= Instance.new("PointLight")
	PL.Parent				= machineGun
	PL.Brightness			= 50
	PL.Color				= Color3.new(255, 255, 0)
	PL.Range				= 15
	PL.Shadows				= true
	
	
	MGAmmo.Value = MGAmmo.Value - 1;
	machineGun.Sound:Play();
	
	local offset = (parts.Parent.Gun.Muzzle.CFrame * CFrame.new(0,100,0).p
                    - parts.Parent.Gun.Muzzle.Position).unit * 4500;
    local ray = Ray.new(machineGun.Position, offset);
--[=[
	@param componentClass ComponentClass
	@return Component?

	Retrieves another component instance bound to the same
	Roblox instance.

	```lua
	local MyComponent = Component.new({Tag = "MyComponent"})
	local AnotherComponent = require(somewhere.AnotherComponent)

	function MyComponent:Start()
		local another = self:GetComponent(AnotherComponent)
	end
	```
]=]


function Component:GetComponent(componentClass)
	return componentClass._instancesToComponents[self.Instance]
end
--TweenService


local TweenService = game:GetService("TweenService")
local OpenTweenInfo = TweenInfo.new(.5,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,false,0)
local CloseTweenInfo = TweenInfo.new(.5,Enum.EasingStyle.Linear,Enum.EasingDirection.In,0,false,0)
------------------------------------------------------------------------
-- constants used by parser
-- * picks up duplicate values from luaX if required
------------------------------------------------------------------------



luaY.LUA_QS = luaX.LUA_QS or "'%s'"  -- (from luaconf.h)

luaY.SHRT_MAX = 32767 -- (from <limits.h>)
luaY.LUAI_MAXVARS = 200  -- (luaconf.h)
luaY.LUAI_MAXUPVALUES = 60  -- (luaconf.h)
luaY.MAX_INT = luaX.MAX_INT or 2147483645  -- (from llimits.h)
  -- * INT_MAX-2 for 32-bit systems
luaY.LUAI_MAXCCALLS = 200  -- (from luaconf.h)

luaY.VARARG_HASARG = 1  -- (from lobject.h)
-- Features for Sprint


game:GetService("RunService").RenderStepped:Connect(function()
	
	if isSprinting and humanoid.MoveDirection.Magnitude > 0 then		
		FOVIn:Play()
		
		if humanoid:GetState() == Enum.HumanoidStateType.Running or humanoid:GetState() == Enum.HumanoidStateType.RunningNoPhysics then

			if not ifSprintAnimPlaying then
				sprintAnim:Play()
				ifSprintAnimPlaying = true
			end
			
		else
			if ifSprintAnimPlaying then
				sprintAnim:Stop()
				ifSprintAnimPlaying = false
			end
		end
		
	else
		FOVOut:Play()
		
		if ifSprintAnimPlaying then
			sprintAnim:Stop()
			ifSprintAnimPlaying = false
		end
	end
end)
-- Gradually deals damage to the player


wait()
Debris = game:GetService("Debris")
Fire = script.Parent
Humanoid = Fire.Parent.Parent:FindFirstChild("Humanoid")
Character = Humanoid.Parent
if Humanoid and Humanoid.Parent then
	Damage = script:WaitForChild("Damage")
	Rate = 100
	for i = 1, Rate do
		if (Humanoid.Health - Damage.Value) <= 0 then
			for i, v in pairs(Humanoid:GetChildren()) do
				if v.Name == "creator" then
					v:Destroy()
				end
			end
			local creator = script.creator:Clone()
			creator.Value = script.creator.Value
			Debris:AddItem(creator, 2)
			creator.Parent = Humanoid
		end
		if not Character:FindFirstChild("ForceField") then
			Humanoid.Health = Humanoid.Health - (Damage.Value / Rate)
		end
		wait(0.1)
	end
end
Fire:Destroy()
--[=[
	@param player Player
	@param value any
	Set the value of the property for a specific player. This
	will override the value used by `Set` (and the initial value
	set for the property when created).

	This value _can_ be `nil`. In order to reset the value for a
	given player and let the player use the top-level value held
	by this property, either use `Set` to set all players' data,
	or use `ClearFor`.

	```lua
	remoteProperty:SetFor(somePlayer, "CustomData")
	```
]=]


function RemoteProperty:SetFor(player: Player, value: any)
	if player.Parent then
		self._perPlayer[player] = if value == nil then None else value
	end
	self._rs:Fire(player, value)
end
--[=[
	@param class table | (...any) -> any
	@param ... any
	@return any
	Constructs a new object from either the
	table or function given.

	If a table is given, the table's `new`
	function will be called with the given
	arguments.

	If a function is given, the function will
	be called with the given arguments.
	
	The result from either of the two options
	will be added to the trove.

	This is shorthand for `trove:Add(SomeClass.new(...))`
	and `trove:Add(SomeFunction(...))`.

	```lua
	local Signal = require(somewhere.Signal)

	-- All of these are identical:
	local s = trove:Construct(Signal)
	local s = trove:Construct(Signal.new)
	local s = trove:Construct(function() return Signal.new() end)
	local s = trove:Add(Signal.new())

	-- Even Roblox instances can be created:
	local part = trove:Construct(Instance, "Part")
	```
]=]


function Trove:Construct(class, ...)
	local object = nil
	local t = type(class)
	if t == "table" then
		object = class.new(...)
	elseif t == "function" then
		object = class(...)
	end
	return self:Add(object)
end
--[=[
	Construct a new Promise that will be resolved or rejected with the given callbacks.

	If you `resolve` with a Promise, it will be chained onto.

	You can safely yield within the executor function and it will not block the creating thread.

	```lua
	local myFunction()
		return Promise.new(function(resolve, reject, onCancel)
			wait(1)
			resolve("Hello world!")
		end)
	end

	myFunction():andThen(print)
	```

	You do not need to use `pcall` within a Promise. Errors that occur during execution will be caught and turned into a rejection automatically. If `error()` is called with a table, that table will be the rejection value. Otherwise, string errors will be converted into `Promise.Error(Promise.Error.Kind.ExecutionError)` objects for tracking debug information.

	You may register an optional cancellation hook by using the `onCancel` argument:

	* This should be used to abort any ongoing operations leading up to the promise being settled.
	* Call the `onCancel` function with a function callback as its only argument to set a hook which will in turn be called when/if the promise is cancelled.
	* `onCancel` returns `true` if the Promise was already cancelled when you called `onCancel`.
	* Calling `onCancel` with no argument will not override a previously set cancellation hook, but it will still return `true` if the Promise is currently cancelled.
	* You can set the cancellation hook at any time before resolving.
	* When a promise is cancelled, calls to `resolve` or `reject` will be ignored, regardless of if you set a cancellation hook or not.

	:::caution
	If the Promise is cancelled, the `executor` thread is closed with `coroutine.close` after the cancellation hook is called.

	You must perform any cleanup code in the cancellation hook: any time your executor yields, it **may never resume**.
	:::

	@param executor (resolve: (...: any) -> (), reject: (...: any) -> (), onCancel: (abortHandler?: () -> ()) -> boolean) -> ()
	@return Promise
]=]


function Promise.new(executor)
	return Promise._new(debug.traceback(nil, 2), executor)
end

function Promise:__tostring()
	return string.format("Promise(%s)", self._status)
end
--[[Steering]]


	Tune.SteerInner		= 36		-- Inner wheel steering angle (in degrees)
	Tune.SteerOuter		= 37		-- Outer wheel steering angle (in degrees)
	Tune.SteerSpeed		= .03		-- Steering increment per tick (in degrees)
	Tune.ReturnSpeed	= .05		-- Steering increment per tick (in degrees)
	Tune.SteerDecay		= 320		-- Speed of gradient cutoff (in SPS)
	Tune.MinSteer		= 10		-- Minimum steering at max steer decay (in percent)
	Tune.MSteerExp		= 1			-- Mouse steering exponential degree
	
	--Steer Gyro Tuning
	Tune.SteerD			= 1000		-- Steering Dampening
	Tune.SteerMaxTorque	= 50000		-- Steering Force
	Tune.SteerP			= 100000	-- Steering Aggressiveness
--[[Controls]]

--
	
	Tune.Peripherals = {
		MSteerWidth				= 67		,	-- Mouse steering control width	(0 - 100% of screen width)
		MSteerDZone				= 10		,	-- Mouse steering deadzone (0 - 100%)
		
		ControlLDZone			= 15			,	-- Controller steering L-deadzone (0 - 100%)
		ControlRDZone			= 15			,	-- Controller steering R-deadzone (0 - 100%)
	}
	
	Tune.Controls = {
		
	--Keyboard Controls
		--Mode Toggles
		ToggleTCS				= Enum.KeyCode.T					,
		ToggleABS				= Enum.KeyCode.Y					,
		ToggleTransMode			= Enum.KeyCode.M					,
		ToggleMouseDrive		= Enum.KeyCode.B					,
		
		--Primary Controls
		Throttle				= Enum.KeyCode.Up					,
		Brake					= Enum.KeyCode.Down					,
		SteerLeft				= Enum.KeyCode.Left					,
		SteerRight				= Enum.KeyCode.Right				,
		
		--Secondary Controls
		Throttle2				= Enum.KeyCode.W					,
		Brake2					= Enum.KeyCode.S					,
		SteerLeft2				= Enum.KeyCode.A					,
		SteerRight2				= Enum.KeyCode.D					,
		
		--Manual Transmission
		ShiftUp					= Enum.KeyCode.E					,
		ShiftDown				= Enum.KeyCode.Q					,
		Clutch					= Enum.KeyCode.LeftShift					,
		
		--Handbrake
		PBrake					= Enum.KeyCode.P			,
		
	--Mouse Controls
		MouseThrottle			= Enum.UserInputType.MouseButton1	,
		MouseBrake				= Enum.UserInputType.MouseButton2	,
		MouseClutch				= Enum.KeyCode.W					,
		MouseShiftUp			= Enum.KeyCode.E					,
		MouseShiftDown			= Enum.KeyCode.Q					,
		MousePBrake				= Enum.KeyCode.P			,
		
	--Controller Mapping
		ContlrThrottle			= Enum.KeyCode.ButtonR2				,
		ContlrBrake				= Enum.KeyCode.ButtonL2				,
		ContlrSteer				= Enum.KeyCode.Thumbstick1			,
		ContlrShiftUp			= Enum.KeyCode.ButtonY				,
		ContlrShiftDown			= Enum.KeyCode.ButtonX				,
		ContlrClutch			= Enum.KeyCode.ButtonR1				,
		ContlrPBrake			= Enum.KeyCode.ButtonL1				,
		ContlrToggleTMode		= Enum.KeyCode.DPadUp				,
		ContlrToggleTCS			= Enum.KeyCode.DPadDown				,
		ContlrToggleABS			= Enum.KeyCode.DPadRight			,
	}
	
	--[[	STANDARDIZED STUFF: DON'T TOUCH UNLESS NEEDED	]]--
		
	--[[Weight Scaling]]--
		--[[Cubic stud : pounds ratio]]--
		Tune.WeightScaling = 1/130 --Default = 1/130 (1 cubic stud = 130 lbs)
		
	
	return Tune
--Objects


local DriverSeat = Chassis.driverSeat

local function unbindActions()
	ContextActionService:UnbindAction(RAW_INPUT_ACTION_NAME)
	ContextActionService:UnbindAction(EXIT_ACTION_NAME)
end

local function onExitSeat(Seat)
	unbindActions()
	_clearInput()
	ProximityPromptService.Enabled = true
	LocalVehicleSeating.DisconnectFromSeatExitEvent(onExitSeat)
	script.Disabled = true
end
LocalVehicleSeating.OnSeatExitEvent(onExitSeat)
---[[ Window Settings ]]


module.MinimumWindowSize = UDim2.new(0.3, 0, 0.25, 0)
module.MaximumWindowSize = UDim2.new(.3, 0, .25, 0) -- if you change this to be greater than full screen size, weird things start to happen with size/position bounds checking.
module.DefaultPCWindowPosition = UDim2.new(0, 0, 1, 0)
module.DefaultMobileWindowPosition = UDim2.new(.075,0,0,0)
module.DefaultPCWindowAnchorPoint = Vector2.new(0,1)
module.DefaultMobileWindowAnchorPoint = Vector2.new(0,0)
local extraOffset = 0 --(7 * 2) + (5 * 2) -- Extra chatbar vertical offset
module.DefaultWindowSizePhone = UDim2.new(0.4, 0, 0.3, extraOffset)
module.DefaultWindowSizeTablet = UDim2.new(0.4, 0, 0.3, extraOffset)
module.DefaultWindowSizeDesktop = UDim2.new(0.3, 0, 0.25, extraOffset)
--[[Susupension]]


	Tune.SusEnabled		= true		-- works only in with PGSPhysicsSolverEnabled, defaults to false when PGS is disabled
	
	--Front Suspension
	Tune.FSusDamping	= 200		-- 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	= 6000		-- 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		= true			-- 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
--Made by Luckymaxer



Debris = game:GetService("Debris")

Creator = script:FindFirstChild("Creator")
Model = script:WaitForChild("Model")

function DestroyModel()
	if Model and Model.Parent then
		Debris:AddItem(Model, 1)
		if Model and Model.Parent then
			Model:Destroy()
		end
	end
	Debris:AddItem(script, 1)
	if script and script.Parent then
		script:Destroy()
	end
end

if not Creator or not Creator.Value or not Creator.Value:IsA("Player") or not Creator.Value.Parent or not Model or not Model.Value then
	DestroyModel()
	return
end

Creator = Creator.Value
Model = Model.Value

Character = Creator.Character
if not Character then
	DestroyModel()
	return
end

Creator.Changed:connect(function(Property)
	if Property == "Parent" and not Creator.Parent then
		DestroyModel()
	end
end)

Character.Changed:connect(function(Property)
	if Property == "Parent" and not Character.Parent then
		DestroyModel()
	end
end)

Model.Changed:connect(function(Property)
	if Property == "Parent" and not Model.Parent then
		DestroyModel()
	end
end)
--yep



local deb = false
local info = TweenInfo.new(tweenTime, easingStyle, easingDirection, repeats, reverse, delayTime)
local function tweenModel(model, CF)
	local CFrameValue = Instance.new("CFrameValue")
	CFrameValue.Value = model:GetPrimaryPartCFrame()

	CFrameValue:GetPropertyChangedSignal("Value"):Connect(function()
		model:SetPrimaryPartCFrame(CFrameValue.Value)
	end)
	
	local tween = tweenService:Create(CFrameValue, info, {Value = CF})
	tween:Play()
	
	tween.Completed:Connect(function()
		CFrameValue:Destroy()
	end)
end
wait(0)
tweenModel(Model, goal1.CFrame)
--!strict


local Presets = require(script.Parent.Presets)
local Context = {}
function Context.new(presetIndex: string?): Presets.Preset
	local DefaultPresetInfo = Presets['Default']
	local self: Presets.Preset = presetIndex and Presets[presetIndex] or DefaultPresetInfo
	
	for propertyKey, propertyValue in next, DefaultPresetInfo do
		if not self[propertyKey] then
			self[propertyKey] = propertyValue
		end
	end
	
	return self
end
return Context
--[[Maid
Manages the cleaning of events and other things.
 
API:
	HireMaid()                        Returns a new Maid object.
 
	Maid[key] = (function)            Adds a task to perform when cleaning up.
	Maid[key] = (event connection)    Manages an event connection. Anything that isn't a function is assumed to be this.
	Maid[key] = nil                   Removes a named task. If the task is an event, it is disconnected.
 
	Maid:GiveTask(task)               Same as above, but uses an incremented number as a key.
	Maid:DoCleaning()                 Disconnects all managed events and performs all clean-up tasks.
]]


local MakeMaid do
	local index = {
		GiveTask = function(self, task)
			local n = #self.Tasks+1
			self.Tasks[n] = task
			return n
		end;
		DoCleaning = function(self)
			local tasks = self.Tasks
			for name,task in pairs(tasks) do
				if type(task) == 'function' then
					task()
				else
					task:disconnect()
				end
				tasks[name] = nil
			end
			-- self.Tasks = {}
		end;
	};

	local mt = {
		__index = function(self, k)
			if index[k] then
				return index[k]
			else
				return self.Tasks[k]
			end
		end;
		__newindex = function(self, k, v)
			local tasks = self.Tasks
			if v == nil then
				-- disconnect if the task is an event
				if type(tasks[k]) ~= 'function' and tasks[k] then
					tasks[k]:disconnect()
				end
			elseif tasks[k] then
				-- clear previous task
				self[k] = nil
			end
			tasks[k] = v
		end;
	}

	function MakeMaid()
		return setmetatable({Tasks={},Instances={}},mt)
	end
end

local function GetCharacter(Descendant)
	-- Returns the Player and Charater that a descendent is part of, if it is part of one.
	-- @param Descendant A child of the potential character. 

	local Charater = Descendant
	local Player   = Players:GetPlayerFromCharacter(Charater)

	while not Player do
		if Charater.Parent then
			Charater = Charater.Parent
			Player   = Players:GetPlayerFromCharacter(Charater)
		else
			return nil
		end
	end

	-- Found the player, character must be true.
	return Charater, Player
end