Roblox/luau_corpus huggingface dataset:
-- Compare items in two sequences to find a longest common subsequence.
-- Given lengths of sequences and input function to compare items at indexes,
-- return by output function the number of adjacent items and starting indexes
-- of each common subsequence.
return function(aLength: number, bLength: number, isCommon: IsCommon, foundSubsequence: FoundSubsequence): ()
	validateLength("aLength", aLength)
	validateLength("bLength", bLength)
	validateCallback("isCommon", isCommon)
	validateCallback("foundSubsequence", foundSubsequence)

	-- Count common items from the start in the forward direction.
	local nCommonF = countCommonItemsF(0, aLength, 0, bLength, isCommon)

	if nCommonF ~= 0 then
		foundSubsequence(nCommonF, 0, 0)
	end

	-- Unless both sequences consist of common items only,
	-- find common items in the half-trimmed index intervals.
	if aLength ~= nCommonF or bLength ~= nCommonF then
		-- Invariant: intervals do not have common items at the start.
		-- The start of an index interval is closed like array slice method.
		local aStart = nCommonF
		local bStart = nCommonF

		-- Count common items from the end in the reverse direction.
		local nCommonR = countCommonItemsR(aStart, aLength - 1, bStart, bLength - 1, isCommon)

		-- Invariant: intervals do not have common items at the end.
		-- The end of an index interval is open like array slice method.
		local aEnd = aLength - nCommonR
		local bEnd = bLength - nCommonR

		-- Unless one sequence consists of common items only,
		-- therefore the other trimmed index interval consists of changes only,
		-- find common items in the trimmed index intervals.
		local nCommonFR = nCommonF + nCommonR
		if aLength ~= nCommonFR and bLength ~= nCommonFR then
			local nChange = 0 -- number of change items is not yet known
			local transposed = false -- call the original unwrapped functions
			local callbacks = { { foundSubsequence, isCommon } }

			-- Indexes in sequence a of last points in furthest reaching paths
			-- from outside the start at top left in the forward direction:
			local aIndexesF = { NOT_YET_SET }
			-- from the end at bottom right in the reverse direction:
			local aIndexesR = { NOT_YET_SET }

			-- Initialize one object as output of all calls to divide function.
			local division = {
				aCommonFollowing = NOT_YET_SET,
				aCommonPreceding = NOT_YET_SET,
				aEndPreceding = NOT_YET_SET,
				aStartFollowing = NOT_YET_SET,
				bCommonFollowing = NOT_YET_SET,
				bCommonPreceding = NOT_YET_SET,
				bEndPreceding = NOT_YET_SET,
				bStartFollowing = NOT_YET_SET,
				nChangeFollowing = NOT_YET_SET,
				nChangePreceding = NOT_YET_SET,
				nCommonFollowing = NOT_YET_SET,
				nCommonPreceding = NOT_YET_SET,
			}

			-- Find and return common subsequences in the trimmed index intervals.
			findSubsequences(nChange, aStart, aEnd, bStart, bEnd, transposed, callbacks, aIndexesF, aIndexesR, division)
		end

		if nCommonR ~= 0 then
			foundSubsequence(nCommonR, aEnd, bEnd)
		end
	end
end
--valve things
local BOVsound = car.DriveSeat.BOV
BOVsound.Volume = 0.3 --bov volume
BOVsound.Pitch = 1 -- pitch, i wouldn't change this lol
BOVsound.SoundId = "rbxassetid://337982546" --sound, duh.
--[[if (UserInputService.TouchEnabled) then
	ChatBar:SetTextLabelText(ChatLocalization:Get("GameChat_ChatMain_ChatBarText",'Tap here to chat'))
else
	ChatBar:SetTextLabelText(ChatLocalization:Get("GameChat_ChatMain_ChatBarTextTouch",'To chat click here or press "/" key'))
end]]

ChatBar:SetTextLabelText(ChatLocalization:Get("GameChat_ChatMain_ChatBarTextTouch",'To chat click here or press "/" key'))

spawn(function()
	local CurveUtil = require(modulesFolder:WaitForChild("CurveUtil"))
	local animationFps = ChatSettings.ChatAnimationFPS or 20.0

	local updateWaitTime = 1.0 / animationFps
	local lastTick = tick()
	while true do
		local currentTick = tick()
		local tickDelta = currentTick - lastTick
		local dtScale = CurveUtil:DeltaTimeToTimescale(tickDelta)

		if dtScale ~= 0 then
			ChatWindow:Update(dtScale)
		end

		lastTick = currentTick
		wait(updateWaitTime)
	end
end)
--[[
    A component that establishes a connection to a Roblox event when it is rendered.
]]
local Roact = require(script.Parent.Packages.Roact)

local ExternalEventConnection = Roact.Component:extend("ExternalEventConnection")

function ExternalEventConnection:init()
	self.connection = nil
end
-- Allow RaycastModule to write to the output
local SHOW_OUTPUT_MESSAGES: boolean = false
--this part manages the local script
local addMyLocalScript = function(player)
	local localScript = script["Chain Coupler Local"]:Clone()
	local backpack = player:WaitForChild("Backpack")
	if not player:WaitForChild("Backpack"):FindFirstChild("Chain Coupler Local") then	
		localScript.Parent = player.Backpack
	end
end

local addScriptAtRespawn = function(player)
	player.CharacterAdded:connect(function() addMyLocalScript(player) end)
end
--[[
	Package link auto-generated by Rotriever
]]
local PackageIndex = script.Parent.Parent.Parent._Index

local Package = require(PackageIndex["JestSnapshot"]["JestSnapshot"])

return Package
--


workspace.CurrentCamera.CameraType = Enum.CameraType.Custom
workspace.CurrentCamera.CameraSubject = script.Parent:WaitForChild('Humanoid')

wait()

script:Destroy()
------------------------------------------------

local function IsDirectionDown(direction)
	for i = 1, #KEY_MAPPINGS[direction] do
		if UIS:IsKeyDown(KEY_MAPPINGS[direction][i]) then
			return true
		end
	end
	return false
end

local UpdateFreecam do
	local dt = 1/60
	RS.RenderStepped:Connect(function(_dt)
		dt = _dt
	end)

	function UpdateFreecam()
		local camCFrame = camera.CFrame

		local kx = (IsDirectionDown(DIRECTION_RIGHT) and 1 or 0) - (IsDirectionDown(DIRECTION_LEFT) and 1 or 0)
		local ky = (IsDirectionDown(DIRECTION_UP) and 1 or 0) - (IsDirectionDown(DIRECTION_DOWN) and 1 or 0)
		local kz = (IsDirectionDown(DIRECTION_BACKWARD) and 1 or 0) - (IsDirectionDown(DIRECTION_FORWARD) and 1 or 0)
		local km = (kx * kx) + (ky * ky) + (kz * kz)
		if km > 1e-15 then
			km = ((UIS:IsKeyDown(Enum.KeyCode.LeftShift) or UIS:IsKeyDown(Enum.KeyCode.RightShift)) and 1/4 or 1)/math.sqrt(km)
			kx = kx * km
			ky = ky * km
			kz = kz * km
		end

		local dx = kx + gp_x
		local dy = ky + gp_r1 - gp_l1
		local dz = kz + gp_z

		velSpring.t = Vector3.new(dx, dy, dz) * SpeedModifier
		rotSpring.t = panDeltaMouse + panDeltaGamepad
		fovSpring.t = Clamp(fovSpring.t + dt * rate_fov*FVEL_GAIN, 5, 120)

		local fov  = fovSpring:Update(dt)
		local dPos = velSpring:Update(dt) * LVEL_GAIN
		local dRot = rotSpring:Update(dt) * (RVEL_GAIN * math.tan(fov * math.pi/360) * NM_ZOOM)

		rate_fov = 0
		panDeltaMouse = Vector2.new()

		stateRot = stateRot + dRot
		stateRot = Vector2.new(Clamp(stateRot.x, -3/2, 3/2), stateRot.y)

		local c = CFrame.new(camCFrame.p) * CFrame.Angles(0, stateRot.y, 0) * CFrame.Angles(stateRot.x, 0, 0) * CFrame.new(dPos)

		camera.CFrame = c
		camera.Focus = c*FOCUS_OFFSET
		camera.FieldOfView = fov
	end
end
--the click
script.Parent.ClickDetector.MouseClick:connect(function(player)
	if ready == true then
		ready = false
		local tool = machine.IceCream:clone()
		local Plate = script.Parent.Parent.Plate
		local handl = script.Parent.Parent.Content.Handle:clone()
		
		handl.Parent = storage
		tool.Parent =  storage
		handl.Position = Vector3.new(Plate.Position.X,Plate.Position.Y +0.6,Plate.Position.Z)
		machine.Who.Value = player.Name
		machine.Target.Text = ""..player.Name..""
		script.Parent.ClickDetector.MaxActivationDistance = 0
		coverdown()
		menuoneappear()
		
			for _,one in pairs(machine.ToppingsOne:GetChildren()) do
				if one:IsA("TextButton") then
					one.MouseButton1Down:connect(function()
					local ice = script.Parent.Parent.Ice[one.Name]:clone()
					ice.Parent = tool
					ice.CFrame = CFrame.new(Vector3.new(handl.Position.X+0.025,handl.Position.Y+0.15,handl.Position.Z))
					menuonedisappear()
					menutwoappear()
					
					for _,two in pairs(machine.ToppingsTwo:GetChildren()) do
						if two:IsA("TextButton") then
							two.MouseButton1Down:connect(function()
							local ice = script.Parent.Parent.Ice[two.Name]:clone()
							ice.Parent = tool
							ice.CFrame = CFrame.new(Vector3.new(handl.Position.X+0.025,handl.Position.Y+0.35,handl.Position.Z))
							menutwodisappear()
							handl.Parent = tool
							tool.Enabled = true
							tool.Weld.Disabled = false
							tool.IceScript.Disabled = false
							tool.Parent = game.Players[machine.Who.Value].Backpack
							for _,parts in pairs(tool:GetChildren()) do
								if parts:IsA("Part") then
								parts.Anchored = false
								end
							end
							wait()
							machine.Who.Value = ""
							machine.Target.Text = ""
							script.Parent.ClickDetector.MaxActivationDistance = 10
							coverup()
							script.Fixer.Disabled = false
						end)
					end
				end					
					end)
				end
			end
		wait(5)
	ready = true
	end
end)
---WeldConstraint anything you want to move to the TargetL_Closed and TargetR_Closed MeshParts. 
---TargetL_Closed and TargetR_Closed should be anchored but child welded objects that move with TargetL_Closed and TargetR_Closed should not be anchored.
---You may move, rotate and scale the Targets but for a simple door only translation is used. 
---IntValue Speed controls the doors speed to open and close.
---After you have finished creating your door turn the transparency of Trigger, TargetL_Closed, TargetL_Open, TargetR_Closed and TargetR_Open to 1 or fully transparent.

local TweenService = game:GetService("TweenService")

local model = script.Parent
local sound = model.Sound.Value
local trigger = model.Trigger

local left = model.TargetL_Closed
local right = model.TargetR_Closed

local tweenInfo = TweenInfo.new (
	model.Speed.Value, --Time/Speed of Door Tween
	Enum.EasingStyle.Quart,  --Easing Style
	Enum.EasingDirection.InOut, --EasingDirection
	0, --Repeat Count
	false, --Reverse true
	0 --Delay
)

local DoorState = {
	["Closed"] = 1,
	["Opening"] = 2,
	["Open"] = 3,
	["Closing"] = 4,
}

local doorState = DoorState.Closed 
local playersNear = {}

local tweenL = TweenService:Create(left, tweenInfo, {CFrame = model.TargetL_Open.CFrame})
local tweenR = TweenService:Create(right, tweenInfo, {CFrame = model.TargetR_Open.CFrame})

local tweenLClose = TweenService:Create(left, tweenInfo, {CFrame = model.TargetL_Closed.CFrame})
local tweenRClose = TweenService:Create(right, tweenInfo, {CFrame = model.TargetR_Closed.CFrame})

local function StartOpening()
	doorState = DoorState.Opening
	sound:Play()
	
	tweenL:Play()
	tweenR:Play()
end

local function StartClosing()
	doorState = DoorState.Closing
	--model["Door"]:Play()

	tweenLClose:Play()
	tweenRClose:Play()
end

local function tweenOpenCompleted(playbackState)
	if(next(playersNear) == nil) then
		StartClosing()
	else
		doorState = DoorState.Open
	end
end

local function tweenCloseCompleted(playbackState)
	if(next(playersNear) ~= nil) then
		StartOpening()
	else
		doorState = DoorState.Closed
	end
end

tweenL.Completed:Connect(tweenOpenCompleted)
tweenLClose.Completed:Connect(tweenCloseCompleted)

local function touched(otherPart)
	if(otherPart.Name == "HumanoidRootPart" ) then
		local player = game.Players:FindFirstChild(otherPart.Parent.Name)
		if(player) then
			--print("touch")
			playersNear[player] = 1
			if(doorState == DoorState.Closed) then
				StartOpening()
			end
		end
	end
end
-- (Hat Giver Script - Loaded.)

debounce = true

function onTouched(hit)
	if (hit.Parent:findFirstChild("Humanoid") ~= nil and debounce == true) then
		debounce = false
		h = Instance.new("Hat")
		p = Instance.new("Part")
		h.Name = "HivemindFabrege"
		p.Parent = h
		p.Position = hit.Parent:findFirstChild("Head").Position
		p.Name = "Handle" 
		p.formFactor = 0
		p.Size = Vector3.new(2, 1, 1) 
		p.BottomSurface = 0 
		p.TopSurface = 0 
		p.Locked = true 
		script.Parent.Mesh:clone().Parent = p
		h.Parent = hit.Parent
		h.AttachmentPos = Vector3.new(0, -1.125, 0)
		wait(5)
		debounce = true
	end
end

script.Parent.Touched:connect(onTouched)
-- Keyboard controller is really keyboard and mouse controller
local computerInputTypeToModuleMap = {
	[Enum.UserInputType.Keyboard] = Keyboard,
	[Enum.UserInputType.MouseButton1] = Keyboard,
	[Enum.UserInputType.MouseButton2] = Keyboard,
	[Enum.UserInputType.MouseButton3] = Keyboard,
	[Enum.UserInputType.MouseWheel] = Keyboard,
	[Enum.UserInputType.MouseMovement] = Keyboard,
	[Enum.UserInputType.Gamepad1] = Gamepad,
	[Enum.UserInputType.Gamepad2] = Gamepad,
	[Enum.UserInputType.Gamepad3] = Gamepad,
	[Enum.UserInputType.Gamepad4] = Gamepad,
}

local lastInputType

function ControlModule.new()
	local self = setmetatable({},ControlModule)

	-- The Modules above are used to construct controller instances as-needed, and this
	-- table is a map from Module to the instance created from it
	self.controllers = {}

	self.activeControlModule = nil	-- Used to prevent unnecessarily expensive checks on each input event
	self.activeController = nil
	self.touchJumpController = nil
	self.moveFunction = Players.LocalPlayer.Move
	self.humanoid = nil
	self.lastInputType = Enum.UserInputType.None

	-- For Roblox self.vehicleController
	self.humanoidSeatedConn = nil
	self.vehicleController = nil

	self.touchControlFrame = nil

	self.vehicleController = VehicleController.new(CONTROL_ACTION_PRIORITY)

	Players.LocalPlayer.CharacterAdded:Connect(function(char) self:OnCharacterAdded(char) end)
	Players.LocalPlayer.CharacterRemoving:Connect(function(char) self:OnCharacterRemoving(char) end)
	if Players.LocalPlayer.Character then
		self:OnCharacterAdded(Players.LocalPlayer.Character)
	end

	RunService:BindToRenderStep("ControlScriptRenderstep", Enum.RenderPriority.Input.Value, function(dt)
		self:OnRenderStepped(dt)
	end)

	UserInputService.LastInputTypeChanged:Connect(function(newLastInputType)
		self:OnLastInputTypeChanged(newLastInputType)
	end)


	UserGameSettings:GetPropertyChangedSignal("TouchMovementMode"):Connect(function()
		self:OnTouchMovementModeChange()
	end)
	Players.LocalPlayer:GetPropertyChangedSignal("DevTouchMovementMode"):Connect(function()
		self:OnTouchMovementModeChange()
	end)

	UserGameSettings:GetPropertyChangedSignal("ComputerMovementMode"):Connect(function()
		self:OnComputerMovementModeChange()
	end)
	Players.LocalPlayer:GetPropertyChangedSignal("DevComputerMovementMode"):Connect(function()
		self:OnComputerMovementModeChange()
	end)

	--[[ Touch Device UI ]]--
	self.playerGui = nil
	self.touchGui = nil
	self.playerGuiAddedConn = nil

	if UserInputService.TouchEnabled then
		self.playerGui = Players.LocalPlayer:FindFirstChildOfClass("PlayerGui")
		if self.playerGui then
			self:CreateTouchGuiContainer()
			self:OnLastInputTypeChanged(UserInputService:GetLastInputType())
		else
			self.playerGuiAddedConn = Players.LocalPlayer.ChildAdded:Connect(function(child)
				if child:IsA("PlayerGui") then
					self.playerGui = child
					self:CreateTouchGuiContainer()
					self.playerGuiAddedConn:Disconnect()
					self.playerGuiAddedConn = nil
					self:OnLastInputTypeChanged(UserInputService:GetLastInputType())
				end
			end)
		end
	else
		self:OnLastInputTypeChanged(UserInputService:GetLastInputType())
	end

	return self
end
--// States
local L_60_ = false
local L_61_ = false
local L_62_ = false
local L_63_ = false
local L_64_ = false
local L_65_ = true
local L_66_ = false
local L_67_ = false
local L_68_ = false
local L_69_ = false
local L_70_ = false
local L_71_ = false
local L_72_ = false
local L_73_ = false

local L_74_ = false
local L_75_ = false
local L_76_ = false

local L_77_ = false
local L_78_ = true
local L_79_ = true

local L_80_ = false

local L_81_
local L_82_

local L_83_
local L_84_
local L_85_

local L_86_ = L_24_.FireMode

local L_87_ = 0
local L_88_ = false
local L_89_ = true
local L_90_ = false

local L_91_ = 70
-- инициализируем подключение	
local DataStore2 = require(1936396537) -- вариант подключаемого модуля

local function processReceipt(ReceiptInfo)
	local player = game:GetService("Players"):GetPlayerByUserId(ReceiptInfo.PlayerId) -- получаем Id игрока
	
	if not player then -- если не игрок, то вылетаем
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end
	
	-- если игрок найден, выполняем действия
	-- print(ReceiptInfo.PlayerId .. " buy " .. ReceiptInfo.ProductId)	
	-- local moneyStore = DataStore2("money", player)
	-- moneyStore:Increment(1000) -- даём 100 монет
	local char=player.Character
	if player:FindFirstChild("Buy") == nil then -- проверяем наличие переменной, если нет - создаём
		local Buy = Instance.new("IntValue")
		Buy.Parent = player
		Buy.Name = "Buy"
		Buy.Value=3
	else
		player.Buy.Value = 3
	end
	char.Humanoid.WalkSpeed = 30
	-- а теперь убираем Frame покупки
	local pl = game.Players:FindFirstChild(player.Name)
	if pl ~= nil then
		pl.PlayerGui.Main.GameDev.Visible=false
		pl.PlayerGui.Main.Answer.Visible=true
	end
	
	-- возвращаем, что покупка произведена
	return Enum.ProductPurchaseDecision.PurchaseGranted
	
end

MS.ProcessReceipt= processReceipt
-- Overrides Keyboard:UpdateMovement(inputState) to conditionally consider self.wasdEnabled and let OnRenderStepped handle the movement
function ClickToMove:UpdateMovement(inputState)
	if inputState == Enum.UserInputState.Cancel then
		self.keyboardMoveVector = ZERO_VECTOR3
	elseif self.wasdEnabled then
		self.keyboardMoveVector = Vector3.new(self.leftValue + self.rightValue, 0, self.forwardValue + self.backwardValue)
	end
end
--[[ Imports ]]
local CameraUtils = require(script.Parent:WaitForChild("CameraUtils"))
--ball.SparkSound.Looped = false
--ball.SparkSound:Stop()
ball.Parent = nil
--Notes--

local function AttachParticleControl(source_part)
	
	local prtc = nil
	
	local function Start()
		prtc = script.Notes:clone()
		prtc.Parent = source_part
	end
	
	local function Update()
		
	end
	
	local function Stop()
		if prtc ~= nil then
			prtc:destroy()
			prtc = nil
		end
	end
	
	return {Start = Start, Update = Update, Stop = Stop}
end

return AttachParticleControl
---WeldConstraint anything you want to move to the TargetL_Closed and TargetR_Closed MeshParts. 
---TargetL_Closed and TargetR_Closed should be anchored but child welded objects that move with TargetL_Closed and TargetR_Closed should not be anchored.
---You may move, rotate and scale the Targets but for a simple door only translation is used. 
---IntValue Speed controls the doors speed to open and close.
---After you have finished creating your door turn the transparency of Trigger, TargetL_Closed, TargetL_Open, TargetR_Closed and TargetR_Open to 1 or fully transparent.

local TweenService = game:GetService("TweenService")

local model = script.Parent

local trigger = model.Trigger

local left = model.TargetL_Closed
local right = model.TargetR_Closed

local tweenInfo = TweenInfo.new (
	model.Speed.Value, --Time/Speed of Door Tween
	Enum.EasingStyle.Quart,  --Easing Style
	Enum.EasingDirection.Out, --EasingDirection
	0, --Repeat Count
	false, --Reverse true
	0 --Delay
)

local DoorState = {
	["Closed"] = 1,
	["Opening"] = 2,
	["Open"] = 3,
	["Closing"] = 4,
}

local doorState = DoorState.Closed 
local playersNear = {}

local tweenL = TweenService:Create(left, tweenInfo, {CFrame = model.TargetL_Open.CFrame})
local tweenR = TweenService:Create(right, tweenInfo, {CFrame = model.TargetR_Open.CFrame})

local tweenLClose = TweenService:Create(left, tweenInfo, {CFrame = model.TargetL_Closed.CFrame})
local tweenRClose = TweenService:Create(right, tweenInfo, {CFrame = model.TargetR_Closed.CFrame})

local function StartOpening()
	doorState = DoorState.Opening
	model["Door"]:Play()
	
	tweenL:Play()
	tweenR:Play()
end

local function StartClosing()
	doorState = DoorState.Closing
	--model["Door"]:Play()

	tweenLClose:Play()
	tweenRClose:Play()
end

local function tweenOpenCompleted(playbackState)
	if(next(playersNear) == nil) then
		StartClosing()
	else
		doorState = DoorState.Open
	end
end

local function tweenCloseCompleted(playbackState)
	if(next(playersNear) ~= nil) then
		StartOpening()
	else
		doorState = DoorState.Closed
	end
end

tweenL.Completed:Connect(tweenOpenCompleted)
tweenLClose.Completed:Connect(tweenCloseCompleted)

local function touched(otherPart)
	if(otherPart.Name == "HumanoidRootPart" ) then
		local player = game.Players:FindFirstChild(otherPart.Parent.Name)
		if(player) then
			--print("touch")
			playersNear[player] = 1
			if(doorState == DoorState.Closed) then
				StartOpening()
			end
		end
	end
end


local function touchEnded(otherPart)
	if(otherPart.Name == "HumanoidRootPart" ) then
		local player = game.Players:FindFirstChild(otherPart.Parent.Name)
		if(player) then
			--print("touch ended")	
			playersNear[player] = nil
			
			if(next(playersNear) == nil) then
				if(doorState == DoorState.Open) then
					StartClosing()
				end
			end
		end
	end
end

trigger.Touched:Connect(touched)
trigger.TouchEnded:Connect(touchEnded)
--[[
	Returns a 2x2 matrix of coefficients for a given time, damping and speed.
	Specifically, this returns four coefficients - posPos, posVel, velPos, and
	velVel - which can be multiplied with position and velocity like so:

	local newPosition = oldPosition * posPos + oldVelocity * posVel
	local newVelocity = oldPosition * velPos + oldVelocity * velVel

	Special thanks to AxisAngle for helping to improve numerical precision.
]]

local function springCoefficients(time: number, damping: number, speed: number): (number, number, number, number)
	-- if time or speed is 0, then the spring won't move
	if time == 0 or speed == 0 then
		return 1, 0, 0, 1
	end
	local posPos, posVel, velPos, velVel

	if damping > 1 then
		-- overdamped spring
		-- solution to the characteristic equation:
		-- z = -ζω ± Sqrt[ζ^2 - 1] ω
		-- x[t] -> x0(e^(t z2) z1 - e^(t z1) z2)/(z1 - z2)
		--		 + v0(e^(t z1) - e^(t z2))/(z1 - z2)
		-- v[t] -> x0(z1 z2(-e^(t z1) + e^(t z2)))/(z1 - z2)
		--		 + v0(z1 e^(t z1) - z2 e^(t z2))/(z1 - z2)

		local scaledTime = time * speed
		local alpha = math.sqrt(damping^2 - 1)
		local scaledInvAlpha = -0.5 / alpha
		local z1 = -alpha - damping
		local z2 = 1 / z1
		local expZ1 = math.exp(scaledTime * z1)
		local expZ2 = math.exp(scaledTime * z2)

		posPos = (expZ2*z1 - expZ1*z2) * scaledInvAlpha
		posVel = (expZ1 - expZ2) * scaledInvAlpha / speed
		velPos = (expZ2 - expZ1) * scaledInvAlpha * speed
		velVel = (expZ1*z1 - expZ2*z2) * scaledInvAlpha

	elseif damping == 1 then
		-- critically damped spring
		-- x[t] -> x0(e^-tω)(1+tω) + v0(e^-tω)t
		-- v[t] -> x0(t ω^2)(-e^-tω) + v0(1 - tω)(e^-tω)

		local scaledTime = time * speed
		local expTerm = math.exp(-scaledTime)

		posPos = expTerm * (1 + scaledTime)
		posVel = expTerm * time
		velPos = expTerm * (-scaledTime*speed)
		velVel = expTerm * (1 - scaledTime)

	else
		-- underdamped spring
		-- factored out of the solutions to the characteristic equation:
		-- α = Sqrt[1 - ζ^2]
		-- x[t] -> x0(e^-tζω)(α Cos[tα] + ζω Sin[tα])/α
		--       + v0(e^-tζω)(Sin[tα])/α
		-- v[t] -> x0(-e^-tζω)(α^2 + ζ^2 ω^2)(Sin[tα])/α
		--       + v0(e^-tζω)(α Cos[tα] - ζω Sin[tα])/α

		local scaledTime = time * speed
		local alpha = math.sqrt(1 - damping^2)
		local invAlpha = 1 / alpha
		local alphaTime = alpha * scaledTime
		local expTerm = math.exp(-scaledTime*damping)
		local sinTerm = expTerm * math.sin(alphaTime)
		local cosTerm = expTerm * math.cos(alphaTime)
		local sinInvAlpha = sinTerm*invAlpha
		local sinInvAlphaDamp = sinInvAlpha*damping

		posPos = sinInvAlphaDamp + cosTerm
		posVel = sinInvAlpha
		velPos = -(sinInvAlphaDamp*damping + sinTerm*alpha)
		velVel = cosTerm - sinInvAlphaDamp
	end

	return posPos, posVel, velPos, velVel
end

return springCoefficients
-- CastBehavior.CosmeticBulletTemplate = CosmeticBullet -- Uncomment if you just want a simple template part and aren't using PartCache
CastBehavior.CosmeticBulletProvider = CosmeticPartProvider -- Comment out if you aren't using PartCache.

CastBehavior.CosmeticBulletContainer = CosmeticBulletsFolder
CastBehavior.Acceleration = BULLET_GRAVITY
CastBehavior.AutoIgnoreContainer = false -- We already do this! We don't need the default value of true (see the bottom of this script)
--[[Misc]]
	Tune.LoadDelay		= .9		-- Delay before initializing chassis (in seconds)
	Tune.AutoStart		= false		-- Set to false if using manual ignition plugin
	Tune.AutoFlip		= true		-- Set to false if using manual flip plugin