Pinkstack/roblox-luau-corpus-text huggingface dataset:
------------------------------------------------------------------------------------------------------------



function configureAnimationSetOld(name, fileList)
	if (animTable[name] ~= nil) then
		for _, Connection in pairs(animTable[name].Connections) do
			Connection:Disconnect()
		end
	end
	animTable[name] = {}
	animTable[name].count = 0
	animTable[name].totalWeight = 0	
	animTable[name].Connections = {}

	local allowCustomAnimations = true

	local success, msg = pcall(function() allowCustomAnimations = game:GetService("StarterPlayer").AllowCustomAnimations end)
	if not success then
		allowCustomAnimations = true
	end

	-- check for config values
	local config = script:FindFirstChild(name)
	if (allowCustomAnimations and config ~= nil) then
		table.insert(animTable[name].Connections, config.ChildAdded:Connect(function(child) configureAnimationSet(name, fileList) end))
		table.insert(animTable[name].Connections, config.ChildRemoved:Connect(function(child) configureAnimationSet(name, fileList) end))
		local idx = 1
		for _, childPart in pairs(config:GetChildren()) do
			if (childPart:IsA("Animation")) then
				table.insert(animTable[name].Connections, childPart.Changed:Connect(function(property) configureAnimationSet(name, fileList) end))
				animTable[name][idx] = {}
				animTable[name][idx].anim = childPart
				local weightObject = childPart:FindFirstChild("Weight")
				if (weightObject == nil) then
					animTable[name][idx].weight = 1
				else
					animTable[name][idx].weight = weightObject.Value
				end
				animTable[name].count = animTable[name].count + 1
				animTable[name].totalWeight = animTable[name].totalWeight + animTable[name][idx].weight
				idx = idx + 1
			end
		end
	end

	-- fallback to defaults
	if (animTable[name].count <= 0) then
		for idx, anim in pairs(fileList) do
			animTable[name][idx] = {}
			animTable[name][idx].anim = Instance.new("Animation")
			animTable[name][idx].anim.Name = name
			animTable[name][idx].anim.AnimationId = anim.id
			animTable[name][idx].weight = anim.weight
			animTable[name].count = animTable[name].count + 1
			animTable[name].totalWeight = animTable[name].totalWeight + anim.weight
			-- print(name .. " [" .. idx .. "] " .. anim.id .. " (" .. anim.weight .. ")")
		end
	end
	
	-- preload anims
	for i, animType in pairs(animTable) do
		for idx = 1, animType.count, 1 do 
			Humanoid:LoadAnimation(animType[idx].anim)
		end
	end
end
--[[
	A utility used to create a function spy that can be used to robustly test
	that functions are invoked the correct number of times and with the correct
	number of arguments.

	This should only be used in tests.
]]



local assertDeepEqual = require(script.Parent.assertDeepEqual)

local function createSpy(inner)
	local self = {
		callCount = 0,
		values = {},
		valuesLength = 0,
	}

	self.value = function(...)
		self.callCount = self.callCount + 1
		self.values = {...}
		self.valuesLength = select("#", ...)

		if inner ~= nil then
			return inner(...)
		end
	end

	self.assertCalledWith = function(_, ...)
		local len = select("#", ...)

		if self.valuesLength ~= len then
			error(("Expected %d arguments, but was called with %d arguments"):format(
				self.valuesLength,
				len
			), 2)
		end

		for i = 1, len do
			local expected = select(i, ...)

			assert(self.values[i] == expected, "value differs")
		end
	end

	self.assertCalledWithDeepEqual = function(_, ...)
		local len = select("#", ...)

		if self.valuesLength ~= len then
			error(("Expected %d arguments, but was called with %d arguments"):format(
				self.valuesLength,
				len
			), 2)
		end

		for i = 1, len do
			local expected = select(i, ...)

			assertDeepEqual(self.values[i], expected)
		end
	end

	self.captureValues = function(_, ...)
		local len = select("#", ...)
		local result = {}

		assert(self.valuesLength == len, "length of expected values differs from stored values")

		for i = 1, len do
			local key = select(i, ...)
			result[key] = self.values[i]
		end

		return result
	end

	setmetatable(self, {
		__index = function(_, key)
			error(("%q is not a valid member of spy"):format(key))
		end,
	})

	return self
end

return createSpy
---------------------------
--[[
	--Main anchor point is the DriveSeat <car.DriveSeat>	
	
	Usage:
		MakeWeld(Part1,Part2,WeldType*,MotorVelocity**) *default is "Weld"  **Applies to Motor welds only
		ModelWeld(Model,MainPart)
	Example:
		MakeWeld(car.DriveSeat,misc.PassengerSeat)
		MakeWeld(car.DriveSeat,misc.SteeringWheel,"Motor",.2)
		ModelWeld(car.DriveSeat,misc.Door)
]]
--Weld stuff here



car.DriveSeat.ChildAdded:connect(function(child)
	if child.Name=="SeatWeld" and child:IsA("Weld") and game.Players:GetPlayerFromCharacter(child.Part1.Parent)~=nil then
		child.C0=CFrame.new(-1.2,-.5,0)*CFrame.fromEulerAnglesXYZ(-(math.pi/2),0,0)
	end
end)
--[[local EnableBackpack = script:WaitForChild("EnableBackpack")
if Services.Players:GetPlayerFromCharacter(Character) and Services.Players:GetPlayerFromCharacter(Character):FindFirstChild("PlayerGui") then
	EnableBackpack.Parent = Services.Players:GetPlayerFromCharacter(Character):FindFirstChild("PlayerGui")
	EnableBackpack.Disabled = false
	Services.Debris:AddItem(EnableBackpack,1)
end]]



if UnequipLoop then UnequipLoop:Disconnect();UnequipLoop = nil end

if Humanoid then
	Humanoid.Health = Humanoid.Health + 15
end

Character:SetPrimaryPartCFrame(CFrame.new(TargetLocation)*(Center.CFrame-Center.CFrame.p))

for i=1,#AffectedParts do
	for property, value in pairs(AffectedParts[i]) do
		if property ~= "Part" then
			AffectedParts[i].Part[property] = value
		end
	end
end

if ForceField then
	ForceField:Destroy()
end

if HeldTool then
	Humanoid:EquipTool(HeldTool)
end

if Services.Players:GetPlayerFromCharacter(Character) and Services.Players:GetPlayerFromCharacter(Character):FindFirstChild("PlayerGui") then
	FixCam.Parent = Services.Players:GetPlayerFromCharacter(Character):FindFirstChild("PlayerGui")
	FixCam.Disabled = false
end
--DO NOT CHANGE ANYTHING INSIDE OF THIS SCRIPT BESIDES WHAT YOU ARE TOLD TO UNLESS YOU KNOW WHAT YOU'RE DOING OR THE SCRIPT WILL NOT WORK!!


local hitPart = script.Parent
local debounce = true
local tool = game.ServerStorage.HeartThrower -- Change "Sword" to the name of your tool, make sure your tool is in ServerStorage

hitPart.Touched:Connect(function(hit)
	if debounce == true then
		if hit.Parent:FindFirstChild("Humanoid") then
			local plr = game.Players:FindFirstChild(hit.Parent.Name)
			if plr then
				debounce = false
				hitPart.BrickColor = BrickColor.new("Bright red")
				tool:Clone().Parent = plr.Backpack
				wait(3) -- Change "3" to however long you want the player to have to wait before they can get the tool again
				debounce = true
				hitPart.BrickColor = BrickColor.new("Bright green")
			end
		end
	end
end)
-- Projection UI for Vulpix


local PUI = {}; -- Yes, it's pronounced pooy, it stands for Projection User Interface [service].
local TS = game.TweenService;
local HB = game["Run Service"].Heartbeat;


function PUI:UpdateUI(UI, Object, Character, CameraCF, Data) -- UI Object, NPC / Object, Player.Character, Data
	local Time = 0.08; -- was 0.16
	local Info = TweenInfo.new(
		Time,
		Enum.EasingStyle.Sine,
		Enum.EasingDirection.InOut
	);
	
	local CharPos = Character.HumanoidRootPart.CFrame.p;
	local ObjectPos = Object.CFrame.p;	
	
	local Look = CFrame.new(ObjectPos, CharPos) - ObjectPos;	 
	
	local LV = CameraCF.p;	
	-- ^ or CharPos / CameraCF.p
	local Distance = 1; -- 4
	local Projected = Object.CFrame;
	local ProjectLook = CFrame.new(Object.Position, CameraCF.p) - ObjectPos; 
	Projected = CFrame.new(ObjectPos) * CFrame.new( ProjectLook.lookVector * Distance );
	Projected = CFrame.new(Projected.p, LV);
	local Goals = {
		CFrame = Projected;
	};
	
	TS:Create(UI, Info, Goals):Play();
	--wait(Time);
end



return PUI
-- setup emote chat hook
--[[
game.Players.LocalPlayer.Chatted:connect(function(msg)
	local emote = ""
	if msg == "/e dance" then
		emote = dances[math.random(1, #dances)]
	elseif (string.sub(msg, 1, 3) == "/e ") then
		emote = string.sub(msg, 4)
	elseif (string.sub(msg, 1, 7) == "/emote ") then
		emote = string.sub(msg, 8)
	end
	
	if (pose == "Standing" and emoteNames[emote] ~= nil) then
		playAnimation(emote, 0.1, Humanoid)
	end

end)
]]

--
--!strict


local function run(LightChanger, reverse)
	local lights = LightChanger:GetLights("Numbered")
	for groupNumber, lightGroup in lights do
		local angle = if groupNumber % 2 == 0 then 30 else -30
		if reverse then
			angle *= -1
		end
		LightChanger:Pan(angle, lightGroup)
	end
end

return function(LightChangerA, LightChangerB, reverse: boolean)
	run(LightChangerA, reverse)
	run(LightChangerB, reverse)
end
-- ROBLOX deviation START: Bindings are unique to Roact


export type ReactBinding<T> = {
	getValue: (self: ReactBinding<T>) -> T,
	-- FIXME Luau: can't create recursive type with different parameters, so we
	-- approximate for now
	map: <U>(self: ReactBinding<T>, (T) -> U) -> any,
	_source: string?,
}
export type ReactBindingUpdater<T> = (T) -> ()
--[=[
	Repeatedly calls a Promise-returning function up to `times` number of times, until the returned Promise resolves.

	If the amount of retries is exceeded, the function will return the latest rejected Promise.

	```lua
	local function canFail(a, b, c)
		return Promise.new(function(resolve, reject)
			-- do something that can fail

			local failed, thing = doSomethingThatCanFail(a, b, c)

			if failed then
				reject("it failed")
			else
				resolve(thing)
			end
		end)
	end

	local MAX_RETRIES = 10
	local value = Promise.retry(canFail, MAX_RETRIES, "foo", "bar", "baz") -- args to send to canFail
	```

	@since 3.0.0
	@param callback (...: P) -> Promise<T>
	@param times number
	@param ...? P
	@return Promise<T>
]=]


function Promise.retry(callback, times, ...)
	assert(isCallable(callback), "Parameter #1 to Promise.retry must be a function")
	assert(type(times) == "number", "Parameter #2 to Promise.retry must be a number")

	local args, length = { ... }, select("#", ...)

	return Promise.resolve(callback(...)):catch(function(...)
		if times > 0 then
			return Promise.retry(callback, times - 1, unpack(args, 1, length))
		else
			return Promise.reject(...)
		end
	end)
end
--[[Engine]]


	--Torque Curve
	Tune.Horsepower		= 250		--	[TORQUE CURVE VISUAL]
	Tune.IdleRPM		= 800		--		https://www.desmos.com/calculator/2uo3hqwdhf
	Tune.PeakRPM		= 8000		--		Use sliders to manipulate values
	Tune.Redline		= 8500		--		Copy and paste slider values into the respective tune values
	Tune.EqPoint		= 6800
	Tune.PeakSharpness	= 3.8
	Tune.CurveMult		= 0.07
	
	--Incline Compensation
	Tune.InclineComp	= .5			-- Torque compensation multiplier for inclines (applies gradient from 0-90 degrees)
	
	--Misc
	Tune.RevAccel		= 250		-- RPM acceleration when clutch is off
	Tune.RevDecay		= 75		-- RPM decay when clutch is off
	Tune.RevBounce		= 470		-- RPM kickback from redline
	Tune.IdleThrottle	= 3			-- Percent throttle at idle
	Tune.ClutchTol		= 150		-- Clutch engagement threshold (higher = faster response)
--[colorbin contents] NOT NUMBERED IN ORDER I WAS JUST KEEPING TRACK OF HOW MANY THERE ARE!
--red 1
--yellow 2
--orange 3
--viridian 4
--green 5
--magenta 6
--violet 7
--white 8
--silver 9
--navyblue 10
--blue 11
--black 12
--cyan 13



if k == "z" and ibo.Value==true then
---------------------------------------


ba=Instance.new("Part")
ba.CastShadow = false
ba.TopSurface=0
ba.BottomSurface=0
ba.Anchored=false
ba.CanCollide=false
ba.formFactor="Custom"
ba.Size=Vector3.new(1,0.1,1)
ba.CFrame=CFrame.new(script.Parent.CFrame.p)*CFrame.fromEulerAnglesXYZ(math.pi/2,0,0)
ba.Name="Effect"
ba.BrickColor=BrickColor.new "White"
ao=script.RingMesh:clone()
ao.Parent = ba
local fade = script.RingFade:Clone()
fade.Parent = ba
fade.Disabled = false
ba.Parent=script.Parent

fo=Instance.new("BodyPosition")
fo.maxForce= Vector3.new (99999999999999999,99999999999999999,99999999999999999)
fo.position = ba.Position
fo.Parent = ba
aa=Instance.new("BodyAngularVelocity")
aa.P=3000
aa.maxTorque=aa.maxTorque*30
aa.angularvelocity=Vector3.new(math.random(-70,70)/3,math.random(-70,70)/3,math.random(-70,70)/5)*100
aa.Parent=ba
--Launches a rocket.


local function LaunchRocket(Rocket,TargetPos)
	local Character = game.Players.LocalPlayer.Character
	local SpawnPosition = Handle.Position + (Handle.CFrame.lookVector * (Handle.Size.Z/2))
	local BodyVelocity = Rocket:FindFirstChild("BodyVelocity")
	local BodyGyro = Rocket:FindFirstChild("BodyGyro")
	local ExplodeEvent = Rocket:FindFirstChild("Explode")
	Rocket.Velocity = Vector3.new(0,0,0)
	Rocket.CFrame = CFrame.new(SpawnPosition,TargetPos)
	
	--Set the velocity and direction.
	if BodyVelocity and BodyGyro then
		local Direction = (TargetPos - SpawnPosition).unit
		BodyVelocity.Velocity = Direction * ROCKET_LAUNCH_SPEED
		BodyGyro.CFrame = CFrame.new(Vector3.new(0,0,0),Direction)
	end
	
	--Fire the event when touched.
	if ExplodeEvent then
		Rocket.Touched:Connect(function(TouchPart)
			if not IGNORE_LIST[string.lower(TouchPart.Name)] and not TouchPart:IsDescendantOf(Character) then
				ExplodeEvent:FireServer(Rocket.Position)
			end
		end)
	end
end
--------------------------------------------------------------------------------



while true do
	while Humanoid.Health < Humanoid.MaxHealth do
		
		local dt = wait(REGEN_STEP)
		local dh = dt*REGEN_RATE*Humanoid.MaxHealth
		if Character:FindFirstChild("Status").Value >=0 then
			Humanoid.Health = math.min(Humanoid.Health + dh, Humanoid.MaxHealth)
		end
	end
	Humanoid.HealthChanged:Wait()
end
--[[
	Calls any :finally handlers. We need this to be a separate method and
	queue because we must call all of the finally callbacks upon a success,
	failure, *and* cancellation.
]]


function Promise.prototype:_finalize()
	for _, callback in ipairs(self._queuedFinally) do
		-- Purposefully not passing values to callbacks here, as it could be the
		-- resolved values, or rejected errors. If the developer needs the values,
		-- they should use :andThen or :catch explicitly.
		coroutine.wrap(callback)(self._status)
	end

	self._queuedFinally = nil
	self._queuedReject = nil
	self._queuedResolve = nil

	-- Clear references to other Promises to allow gc
	if not Promise.TEST then
		self._parent = nil
		self._consumers = nil
	end

	task.defer(coroutine.close, self._thread)
end
--///////////////// Internal-Use Methods
--//////////////////////////////////////
--DO NOT REMOVE THIS. Chat must be filtered or your game will face
--moderation.


function methods:InternalApplyRobloxFilter(speakerName, message, toSpeakerName) --// USES FFLAG
	local runFilter = false
	if (runFilter) then
		local fromSpeaker = self:GetSpeaker(speakerName)
		local toSpeaker = toSpeakerName and self:GetSpeaker(toSpeakerName)

		if fromSpeaker == nil then
			return nil
		end

		local fromPlayerObj = fromSpeaker:GetPlayer()
		local toPlayerObj = toSpeaker and toSpeaker:GetPlayer()

		if fromPlayerObj == nil then
			return message
		end

		if allSpaces(message) then
			return message
		end

		local filterStartTime = tick()
		local filterRetries = 0
		while true do
			local success, message = pcall(function()
				if toPlayerObj then
					return Chat:FilterStringAsync(message, fromPlayerObj, toPlayerObj)
				else
					return Chat:FilterStringForBroadcast(message, fromPlayerObj)
				end
			end)
			if success then
				return message
			else
				warn("Error filtering message:", message)
			end
			filterRetries = filterRetries + 1
			if filterRetries > MAX_FILTER_RETRIES or (tick() - filterStartTime) > MAX_FILTER_DURATION then
				self:InternalNotifyFilterIssue()
				return nil
			end
			local backoffInterval = FILTER_BACKOFF_INTERVALS[math.min(#FILTER_BACKOFF_INTERVALS, filterRetries)]
			-- backoffWait = backoffInterval +/- (0 -> backoffInterval)
			local backoffWait = backoffInterval + ((math.random()*2 - 1) * backoffInterval)
			wait(backoffWait)
		end
	else
		--// Simulate filtering latency.
		--// There is only latency the first time the message is filtered, all following calls will be instant.
		if not StudioMessageFilteredCache[message] then
			StudioMessageFilteredCache[message] = true
			wait()
		end
		return message
	end

	return nil
end
--[[Weight and CG]]


	Tune.Weight			= 2900		-- Total weight (in pounds)
	Tune.WeightBSize	= {			-- Size of weight brick (dimmensions in studs ; larger = more stable)
	 --[[Width]]		6		,
	 --[[Height]]		3.5		,
	 --[[Length]]		15		}
	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
--[[
	Used to catch any errors that may have occurred in the promise.
]]


function Promise.prototype:catch(failureCallback)
	assert(
		failureCallback == nil or type(failureCallback) == "function",
		string.format(ERROR_NON_FUNCTION, "Promise:catch")
	)
	return self:_andThen(debug.traceback(nil, 2), nil, failureCallback)
end
--[[
	Returns the wagon model in workspace belonging to a player with a user ID
	matching the given ownerId. This is based on the OwnerId attribute of farm
	models, which gets set by the server when the farm is loaded for a player.

	The Wagon is identified by the Wagon CollectionService tag.
--]]



local CollectionService = game:GetService("CollectionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local WagonTag = require(ReplicatedStorage.Source.SharedConstants.CollectionServiceTag.WagonTag)
local Sift = require(ReplicatedStorage.Dependencies.Sift)
local getFarmModelFromOwnerId = require(ReplicatedStorage.Source.Utility.Farm.getFarmModelFromOwnerId)

local function getWagonModelFromOwnerId(ownerId: number): Model?
	local maybeFarm = getFarmModelFromOwnerId(ownerId)

	if not maybeFarm then
		return nil
	end

	local farm = maybeFarm :: Model

	local wagons = Sift.Array.filter(farm:GetChildren(), function(instance: Instance)
		return CollectionService:HasTag(instance, WagonTag.Wagon)
	end)

	-- At most, only one wagon will exist matching in a farm, so it's safe to grab the first list item
	return wagons[1] :: Model
end

return getWagonModelFromOwnerId
-- не забыть бы убрать!!!
--local Debris = game:GetService("Debris") -- это сервисная команда
--local TimeForDestroy = 10*60 -- минимальное время жизни (10 минут = 10*60)



local turret = require(game.ServerScriptService.GAVturret)

local V1 = 10 -- скорострельность
local SPEED = 400 -- скорость снарядов
local MAX_DIST = 70 -- дистанция срабатывания
local DAMAGE = 10 -- наносимые повреждения
local TYPE = "Single" -- AOE, SINGLE

wait()
me=script.Parent
pos = me.PrimaryPart

while true do
	local target = turret.findNearestHead(pos,MAX_DIST) --findNearestHead()
	if target ~= nil then
		if target ~= nil and target.Parent ~= nil and target.Parent.Humanoid.Health>0 then
			alt=turret.lookAt(target.Position,pos.Position) -- пушка только по горизотали!
			me:SetPrimaryPartCFrame(alt) -- направляем туда пушку
			-- вычисляем направление выстрела
			alt=turret.lookAtY(target.Position,me.Rocket.Position)-- ракета (пусковой механизм) полностью ориентируется
			me.Rocket.CFrame= alt
			-- в снаряд суём чья турель
			if me.Rocket:FindFirstChild("Owner") == nil then
				tmp=me.Owner:Clone()
				tmp.Parent = me.Rocket
			end
			turret.Fire(me.Rocket,DAMAGE,SPEED, TYPE) -- стреляем (место снаряда, повреждение) -- добавить создателя пушки
			wait() 
		end
	end
	wait(V1/10)
end
-- << LOCAL FUNCTIONS >>


local defaultSettingsToAdd = {"NoticeSoundId", "NoticeVolume", "NoticePitch", "ErrorSoundId", "ErrorVolume", "ErrorPitch", "AlertSoundId", "AlertVolume", "AlertPitch", "Prefix", "SplitKey"}
local defaultSettings = {}
coroutine.wrap(function()
	if not main.initialized then
		main.client.Signals.Initialized.Event:Wait()
	end
	for i,v in pairs(defaultSettingsToAdd) do
		defaultSettings[v] = settings[v]
	end
end)()
local function getDataTemplate()
	if not main.initialized then
		main.client.Signals.Initialized.Event:Wait()
	end
	return{
		
		DataKey 		= 0;
		DataToUpdate	= true;
		Theme			= settings.Theme;
		NoticeSoundId	= settings.NoticeSoundId;
		NoticeVolume	= settings.NoticeVolume;
		NoticePitch		= settings.NoticePitch;
		ErrorSoundId	= settings.ErrorSoundId;
		ErrorVolume		= settings.ErrorVolume;
		ErrorPitch		= settings.ErrorPitch;
		AlertSoundId	= settings.AlertSoundId;
		AlertVolume		= settings.AlertVolume;
		AlertPitch		= settings.AlertPitch;
		Prefix 			= settings.Prefix;
		SplitKey		= settings.SplitKey;
		MusicList 		= settings.MusicList;
		MuteLocalSound	= false;
		PreviousServer 	= game.JobId;
		Rank 			= 0;
		SaveRank		= true;
		PermRankedBy	= 3682;
		Donor 			= false;
		Gamepasses 		= {};
		Assets 			= {};
		
		DefaultSettings = defaultSettings; --If the owner changes these Settings, then update everyones data to the new setting.
		
		Groups 			= {};
		Friends 		= {};
		CommandsActive 	= {};
		LaserColor 		= Color3.fromRGB(255,0,0);
		PromptedDonor	= false;
		AutomaticRank	= false;
		Items 			= {};
		SetupData		= false;
		
	}
end

local function dataNotToSave()
	return{
		"Groups";
		"Friend";
		"CommandsActive";
		"LaserColor";
		"PromptedDonor";
		"AutomaticRank";
		"Items";
		"SetupData"
	}
end
-- ================================================================================
-- PUBLIC FUNCTIONS
-- ================================================================================


function Damping.new()
	local damping = setmetatable({
		P = 5;
		D = 0.1;
		Position = V3();
		Velocity = V3();
		Goal = V3();
		Last = tick();
	}, Damping)
	
	return damping	
end -- Damping.new()


function Damping:CheckNAN()
	self.Velocity = V3(CheckNAN(self.Velocity.X, 0), CheckNAN(self.Velocity.Y, 0), CheckNAN(self.Velocity.Z, 0))
	self.Position = V3(CheckNAN(self.Position.X, self.Goal.X), CheckNAN(self.Position.Y, self.Goal.Y), CheckNAN(self.Position.Z, self.Goal.Z))
end -- Damping:CheckNAN()


function Damping:Update()
	local t = tick()
	local dt = (t - self.Last)
	self.Last = t
	self.Velocity = (self.Velocity + (self.P * ((self.Goal - self.Position) + (-self.Velocity * self.D))))
	self.Position = (self.Position + (self.Velocity * dt))
	self:CheckNAN()
	return self.Position
end -- Damping:Update()

function Damping:UpdateAngle()
	self.Goal = (self.Position + DeltaAngleV3(self.Position, self.Goal))
	return self:Update()
end -- Damping:UpdateAngle()
--[[

	enumList = EnumList.new(name: string, enums: string[])

	enumList:Is(item)


	Example:

		direction = EnumList.new("Direction", {"Up", "Down", "Left", "Right"})
		leftDir = direction.Left
		print("IsDirection", direction:Is(leftDir))

--]]




type EnumNames = {string}

local Symbol = require(script.Parent.Symbol)

local EnumList = {}


function EnumList.new(name: string, enums: EnumNames)
	local scope = Symbol.new(name, nil)
	local enumItems: {[string]: Symbol.Symbol} = {}
	for _,enumName in ipairs(enums) do
		enumItems[enumName] = Symbol.new(enumName, scope)
	end
	local self = setmetatable({
		_scope = scope;
	}, {
		__index = function(_t, k)
			if (enumItems[k]) then
				return enumItems[k]
			elseif (EnumList[k]) then
				return EnumList[k]
			else
				error("Unknown " .. name .. ": " .. tostring(k), 2)
			end
		end;
		__newindex = function()
			error("Cannot add new " .. name, 2)
		end;
	})
	return self
end


function EnumList:Is(obj: any): boolean
	return Symbol.IsInScope(obj, self._scope)
end


export type EnumList = typeof(EnumList.new("", {""}))


return EnumList