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


local CutsceneFolder = workspace.Cutscenes:WaitForChild("level1") -- The folder that contains the cutscene data (Cameras...)
local Destroy = false -- Destroy folder after loading? you don't want your player to see your cameras floating around!
local NoYield = false -- Generally you want this to be set to false, because loading takes a little bit of time, and you don't want to interact with the cutscene when it's not loaded
local SafeMode = true -- This is adviced to be turned on, especially if the cutscene folder data is too big to load at one frame. when turned on, it loads a camera every frame, not all at once.

local Cutscene = require(CutsceneModule)

local Demo = Cutscene.new(Camera, Looping, Speed, FreezeControls) -- Create cutscene
Demo:Load(CutsceneFolder, Destroy, NoYield, SafeMode) -- Load cutscene data from folder

local PlayOnPartTouch = script:FindFirstChild("PlayOnPartTouch")
local PlayOnPlayerJoin = script:FindFirstChild("PlayOnPlayerJoin")
local PlayOnCharacterAdded = script:FindFirstChild("PlayOnCharacterAdded")
local PlayOnCharacterDied = script:FindFirstChild("PlayOnCharacterDied")
local PlayOnEventFire = script:FindFirstChild("PlayOnEventFire")
local PlayOnRemoteEventFire = script:FindFirstChild("PlayOnRemoteEventFire")
local ProtectTheCharacterWhilePlaying = script:FindFirstChild("ProtectTheCharacterWhilePlaying")
local CharacterProtector = script:FindFirstChild("CharacterProtector")
local Music = script:FindFirstChild("Music")
local StopMusicWhenFinished = script:FindFirstChild("StopMusicWhenFinished")
local StopOnEventFire = script:FindFirstChild("StopOnEventFire")
local StopOnRemoteEventFire = script:FindFirstChild("StopOnRemoteEventFire")
local PlayOnce = script:FindFirstChild("PlayOnce")
local Debounce = script:FindFirstChild("Cooldown")
local OnFinishedRemove = script:FindFirstChild("OnFinishedRemove")
local bin = true
local Player = game:GetService("Players").LocalPlayer
local CutsceneGui = script:FindFirstChild("Cutscene")
-- PROPERTIES


IconController.topbarEnabled = true
IconController.controllerModeEnabled = false
IconController.previousTopbarEnabled = checkTopbarEnabled()
IconController.leftGap = 12
IconController.midGap = 12
IconController.rightGap = 12
IconController.leftOffset = 0
IconController.rightOffset = 0
IconController.voiceChatEnabled = false
IconController.mimicCoreGui = true
IconController.healthbarDisabled = false
IconController.activeButtonBCallbacks = 0
IconController.disableButtonB = false
--[[Transmission]]


	Tune.TransModes		= {"Auto"}								--[[
	[Modes]
		"Auto"		: Automatic shifting
		"Semi"		: Clutchless manual shifting, dual clutch transmission
		"Manual"	: Manual shifting with clutch
		
		>Include within brackets
			eg: {"Semi"} or {"Auto", "Manual"}								
		>First mode is default mode													]]
	
	--Automatic Settings
	Tune.AutoShiftMode	= "Speed"												--[[
	[Modes]
		"Speed"		: Shifts based on wheel speed
		"RPM"		: Shifts based on RPM											]]	
	Tune.AutoUpThresh	= -200		--Automatic upshift point 	(relative to peak RPM, positive = Over-rev)
	Tune.AutoDownThresh = 1400		--Automatic downshift point (relative to peak RPM, positive = Under-rev)
	
	--Gear Ratios
	Tune.FinalDrive		= 4.06			-- Gearing determines top speed and wheel torque
	Tune.Ratios			= {				-- Higher ratio = more torque, Lower ratio = higher top speed
		--[[Reverse]]	3.70		,	-- Copy and paste a ratio to add a gear
		--[[Neutral]]	0			,	-- Ratios can also be deleted
		--[[ 1 ]]		3.53		,	-- Reverse, Neutral, and 1st gear are required
		--[[ 2 ]]		2.04		,
		--[[ 3 ]]		1.38		,
		--[[ 4 ]]		1.03		,
	    --[[ 5 ]]		0.81		,
	    --[[ 6 ]]       0.64		,
	    --[[ 7 ]]       0.52        ,
    }
	Tune.FDMult			= 1.5			-- Ratio multiplier (Change this value instead of FinalDrive if car is struggling with torque ; Default = 1)
--Button Event


for _, b in pairs(scroll:GetChildren()) do
	if b.ClassName=="TextButton" then
		b.MouseButton1Click:Connect(function()
			local result = event:InvokeServer(".", b.Tool.Value)
			frame.Visible = false
			frame.Search.Text = ""
			if result then
				player.Character.Humanoid:UnequipTools()
				player.Character.Humanoid:EquipTool(result)
			end
		end)
	end
end
--manually add the rest
--table.insert(_G.Safezones, {["Position"] = workspace.SpeciesSelectionArea.SpiritSelectionAnchor.Position, ["Magnitude"] = workspace.SpeciesSelectionArea.SpiritSelectionAnchor.Radius.Value, ["Spawn"] = true})


table.insert(_G.Safezones, workspace.BiomeSelectionArea.SpawnSelectionAnchor.CFrame)

for _,part in pairs(workspace.SpawnParts:GetChildren()) do
	table.insert(_G.Safezones, part.CFrame)

end
----
----


	if hit.Parent:findFirstChild("Humanoid") ~= nil then
		local target1 = "RightUpperLeg"
		local target2 = "RightUpperLeg2"
		if hit.Parent:findFirstChild(target2) == nil then
			local g = script.Parent.Parent[target2]:clone()
			g.Parent = hit.Parent
			local C = g:GetChildren()
			for i=1, #C do
				if C[i].className == "UnionOperation" or C[i].className =="Part" or C[i].className == "WedgePart" or C[i].className == "MeshPart" then
					local W = Instance.new("Weld")
					W.Part0 = g.Middle
					W.Part1 = C[i]
					local CJ = CFrame.new(g.Middle.Position)
					local C0 = g.Middle.CFrame:inverse()*CJ
					local C1 = C[i].CFrame:inverse()*CJ
					W.C0 = C0
					W.C1 = C1
					W.Parent = g.Middle
				end
				local Y = Instance.new("Weld")
				Y.Part0 = hit.Parent[target1]
				Y.Part1 = g.Middle
				Y.C0 = CFrame.new(0, 0, 0)
				Y.Parent = Y.Part0
			end

		local h = g:GetChildren()
		for i = 1, # h do
			h[i].Anchored = false
			h[i].CanCollide = false
		end
	end
	end
--[=[
	@return Keyboard

	Constructs a new keyboard input capturer.

	```lua
	local keyboard = Keyboard.new()
	```
]=]


function Keyboard.new()
	local self = setmetatable({}, Keyboard)
	self._trove = Trove.new()
	self.KeyDown = self._trove:Construct(Signal)
	self.KeyUp = self._trove:Construct(Signal)
	self:_setup()
	return self
end
--Functions


local function onTouched(hit)
	local Humanoid = hit.Parent:FindFirstChild("Humanoid")
	local player = game.Players:GetPlayerFromCharacter(hit.Parent)

	if Humanoid and Debounce == false then
		local leaderstats = player:FindFirstChild("leaderstats")
		Debounce = true

		if Debounce == true and leaderstats then
			local sound = script.Parent["Game Sound Correct"]

			if not sound.IsPlaying then
				sound:Play()
		
				Debounce = false
			leaderstats.Guesses.Value = leaderstats.Guesses.Value + AMOUNT_GIVEN
			wait(2)
				wait(10)
		end
	end
end
end
--[[ SCRIPT VARIABLES ]]


local CHAT_BUBBLE_FONT = Enum.Font.Fantasy
local CHAT_BUBBLE_FONT_SIZE = Enum.FontSize.Size24 -- if you change CHAT_BUBBLE_FONT_SIZE_INT please change this to match
local CHAT_BUBBLE_FONT_SIZE_INT = 24 -- if you change CHAT_BUBBLE_FONT_SIZE please change this to match
local CHAT_BUBBLE_LINE_HEIGHT = CHAT_BUBBLE_FONT_SIZE_INT + 10
local CHAT_BUBBLE_TAIL_HEIGHT = 14
local CHAT_BUBBLE_WIDTH_PADDING = 30
local CHAT_BUBBLE_FADE_SPEED = 1.5

local BILLBOARD_MAX_WIDTH = 400
local BILLBOARD_MAX_HEIGHT = 250	--This limits the number of bubble chats that you see above characters

local ELIPSES = "..."
local MaxChatMessageLength = 128 -- max chat message length, including null terminator and elipses.
local MaxChatMessageLengthExclusive
if FFlagUserChatNewMessageLengthCheck2 then
	MaxChatMessageLengthExclusive = MaxChatMessageLength - getMessageLength(ELIPSES) - 1
else
	MaxChatMessageLengthExclusive = MaxChatMessageLength - string.len(ELIPSES) - 1
end

local NEAR_BUBBLE_DISTANCE = 65	--previously 45
local MAX_BUBBLE_DISTANCE = 100	--previously 80
--


script.Parent.OnServerEvent:Connect(function(p)
	local Character = p.Character
	local Humanoid = Character.Humanoid
	local RootPart = Character.HumanoidRootPart
	local Slash1 = RS.Effects.Part1:Clone()
	local Anim = Humanoid:LoadAnimation(script.Animation)
	Anim:Play()
	Humanoid.WalkSpeed = 10
	script.Attack:Play()
	Slash1.Parent = FX
	Slash1.CFrame = RootPart.CFrame * CFrame.new(0,0,-3)
	local BV = Instance.new("BodyVelocity",Slash1)
	BV.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
	BV.Velocity = p.Character.HumanoidRootPart.CFrame.LookVector * 60
	Slash1.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Name ~= p.Name then
			hit.Parent.Humanoid:TakeDamage(Damage)
			local HitEffect = Effects.Hit1.Attachment:Clone()
			local RootPart2 = hit.Parent.HumanoidRootPart
			HitEffect.Parent = RootPart2
			for _,Particles in pairs(HitEffect:GetDescendants()) do
				if Particles:IsA("ParticleEmitter") then
					Particles:Emit(Particles:GetAttribute("EmitCount"))
				end
			end
			HitEffect.Hit:Play()
			local vel = Instance.new("BodyVelocity", RootPart2)
			vel.MaxForce = Vector3.new(1,1,1) * 1000000;
			vel.Parent = RootPart2
			vel.Velocity = Vector3.new(1,1,1) * p.Character:WaitForChild("HumanoidRootPart").CFrame.LookVector * 0
			vel.Name  =  "SmallMoveVel"
			game.Debris:AddItem(vel,1)
			Slash1:Destroy()
	end
	wait(1)
	Slash1.Anchored = true
	for _,Particles in pairs(Slash1.Part.Parent:GetDescendants()) do
		if Particles:IsA("ParticleEmitter") then
			Particles.Enabled = false
		end
		end
		Slash1.PointLight.Enabled = false
end)
end)
--[=[
	Cleans up all objects in the trove. This is
	similar to calling `Remove` on each object
	within the trove.
]=]


function Trove:Clean()
	for _,obj in ipairs(self._objects) do
		self:_cleanupObject(obj[1], obj[2])
	end
	table.clear(self._objects)
end


function Trove:_cleanupObject(object, cleanupMethod)
	if cleanupMethod == FN_MARKER then
		object()
	elseif cleanupMethod == THREAD_MARKER then
		coroutine.close(object)
	else
		object[cleanupMethod](object)
	end
end
--[[**
	matches given tuple against tuple type definition

	@param ... The type definition for the tuples

	@returns A function that will return true iff the condition is passed
**--]]


function t.tuple(...)
	local checks = {...}
	return function(...)
		local args = {...}
		for i = 1, #checks do
			local success, errMsg = checks[i](args[i])
			if success == false then
				return false, string.format("Bad tuple index #%d:\n\t%s", i, errMsg or "")
			end
		end
		return true
	end
end
--- Sets a metatable on a table such that it errors when
-- indexing a nil value
-- @tparam table _table Table to error on indexing
-- @treturn table _table The same table


function Table.readonly(_table)
	return setmetatable(_table, {
		__index = function(self, index)
			error(("Bad index %q"):format(tostring(index)), 2)
		end;
		__newindex = function(self, index, value)
			error(("Bad index %q"):format(tostring(index)), 2)
		end;
	})
end
--calls


caf.Call1.Changed:Connect(function()
	if vaf.Moving.Value == true then
	else
		if vaf.IsOnFirstFloor.Value == true then
			caf.Call1.Value = false
		else
			caf.Call1.Value = false
			vaf.Moving.Value = true
			--
			door2.Close:Fire()
			wait(sef.DoorMoveTime.Value)
			wait(sef.StartMovingDelayTime.Value)
			elev2.SoundBrick.Brick.MoveSound:Play()
			elev1.SoundBrick.Brick.MoveSound:Play()
			elev1.SoundBrick.Brick.MoveSound.Volume = 0
			wait(sef.TravelTime.Value)
			elev2.TeleportBrick.CanTouch = true
			wait(0.2)
			elev2.TeleportBrick.CanTouch = false
			elev2.SoundBrick.Brick.MoveSound:Stop()
			elev1.SoundBrick.Brick.MoveSound.Volume = sef.DefaultMoveSoundLoudness.Value
			wait(sef.DoorDelayTime.Value)
			door1.Open:Fire()
			--
			vaf.Moving.Value = false
			vaf.IsOnFirstFloor.Value = true
		end
	end
end)

caf.Call2.Changed:Connect(function()
	if vaf.Moving.Value == true then
	else
		if vaf.IsOnFirstFloor.Value == false then
			caf.Call2.Value = false
		else
			caf.Call2.Value = false
			vaf.Moving.Value = true
			--
			door1.Close:Fire()
			wait(sef.DoorMoveTime.Value)
			wait(sef.StartMovingDelayTime.Value)
			elev1.SoundBrick.Brick.MoveSound:Play()
			elev2.SoundBrick.Brick.MoveSound:Play()
			elev2.SoundBrick.Brick.MoveSound.Volume = 0
			vaf.Moving.Value = true
			wait(sef.TravelTime.Value)
			elev1.TeleportBrick.CanTouch = true
			wait(0.2)
			elev1.TeleportBrick.CanTouch = false
			elev1.SoundBrick.Brick.MoveSound:Stop()
			elev2.SoundBrick.Brick.MoveSound.Volume = sef.DefaultMoveSoundLoudness.Value
			wait(sef.DoorDelayTime.Value)
			door2.Open:Fire()
			--
			vaf.Moving.Value = false
			vaf.IsOnFirstFloor.Value = false
		end
	end
end)
---Basic_Settings:---


local light = true -- Set to false if u dont have light added
local maxv = 150 -- Max Speed In REAL KT.. Check Online for the real Aviation speed for this plane
local minspeed = -30 -- min speed In real KT 
local Spd_keep = true-- Set to false if U dont want the function to Speed up/down if u hold M/N down, and after release it stops
-- ROBLOX deviation: toBeFalsy checks for Lua falsy values, not JS falsy values


local function toBeFalsy(
	-- ROBLOX deviation: self param in Lua needs to be explicitely defined
	self: MatcherState,
	received: any,
	expected: nil
)
	local matcherName = "toBeFalsy"
	local options: MatcherHintOptions = {
		isNot = self.isNot,
		promise = self.promise,
	}
	ensureNoExpected(expected, matcherName, options)

	local pass = not received

	local message = function()
		return matcherHint(matcherName, nil, "", options)
			.. "\n\n"
			.. string.format("Received: %s", printReceived(received))
	end

	return { message = message, pass = pass }
end

local function toBeGreaterThan(
	-- ROBLOX deviation: self param in Lua needs to be explicitely defined
	self: MatcherState,
	received: number,
	expected: number
)
	local matcherName = "toBeGreaterThan"
	local isNot = self.isNot
	local options: MatcherHintOptions = {
		isNot = isNot,
		promise = self.promise,
	}
	ensureNumbers(received, expected, matcherName, options)

	local pass = received > expected

	local message = function()
		return matcherHint(matcherName, nil, nil, options)
			.. "\n\n"
			.. string.format("Expected:%s > %s\n", isNot and " never" or "", printExpected(expected))
			.. string.format("Received:%s   %s", isNot and "      " or "", printReceived(received))
	end

	return { message = message, pass = pass }
end

local function toBeGreaterThanOrEqual(
	-- ROBLOX deviation: self param in Lua needs to be explicitely defined
	self: MatcherState,
	received: number,
	expected: number
)
	local matcherName = "toBeGreaterThanOrEqual"
	local isNot = self.isNot
	local options: MatcherHintOptions = {
		isNot = isNot,
		promise = self.promise,
	}
	ensureNumbers(received, expected, matcherName, options)

	local pass = received >= expected

	local message = function()
		return matcherHint(matcherName, nil, nil, options)
			.. "\n\n"
			.. string.format("Expected:%s >= %s\n", isNot and " never" or "", printExpected(expected))
			.. string.format("Received:%s    %s", isNot and "      " or "", printReceived(received))
	end

	return { message = message, pass = pass }
end
--[=[
	@param object any -- Object to remove
	Removes the object from the Trove and cleans it up.

	```lua
	local part = Instance.new("Part")
	trove:Add(part)
	trove:Remove(part)
	```
]=]


function Trove:Remove(object: any): boolean
	if self._cleaning then
		error("Cannot call trove:Remove() while cleaning", 2)
	end
	return self:_findAndRemoveFromObjects(object, true)
end
--[[Engine]]


	--Torque Curve
	Tune.Horsepower		= 650		--	[TORQUE CURVE VISUAL]
	Tune.IdleRPM		= 700		--		https://www.desmos.com/calculator/2uo3hqwdhf
	Tune.PeakRPM		= 11000		--		Use sliders to manipulate values
	Tune.Redline		= 13000		--		Copy and paste slider values into the respective tune values
	Tune.EqPoint		= 5500
	Tune.PeakSharpness	= 7.5
	Tune.CurveMult		= 0.16
	
	--Incline Compensation
	Tune.InclineComp	= 1.7			-- Torque compensation multiplier for inclines (applies gradient from 0-90 degrees)
	
	--Misc
	Tune.RevAccel		= 150		-- RPM acceleration when clutch is off
	Tune.RevDecay		= 75		-- RPM decay when clutch is off
	Tune.RevBounce		= 500		-- RPM kickback from redline
	Tune.IdleThrottle	= 3			-- Percent throttle at idle
	Tune.ClutchTol		= 500		-- Clutch engagement threshold (higher = faster response)
--- Overwrites a table's value
-- @function Table.deepOverwrite
-- @tparam table target Target table
-- @tparam table source Table to read from
-- @treturn table target


local function deepOverwrite(target, source)
	for index, value in pairs(source) do
		if type(target[index]) == "table" and type(value) == "table" then
			target[index] = deepOverwrite(target[index], value)
		else
			target[index] = value
		end
	end
	return target
end
Table.deepOverwrite = deepOverwrite
--script.Parent.AAA.Velocity = script.Parent.AAA.CFrame.lookVector *script.Parent.Speed.Value


script.Parent.AAAA.Velocity = script.Parent.AAAA.CFrame.lookVector *script.Parent.Speed.Value
script.Parent.B.Velocity = script.Parent.B.CFrame.lookVector *script.Parent.Speed.Value
script.Parent.BB.Velocity = script.Parent.BB.CFrame.lookVector *script.Parent.Speed.Value
-- Placeholder texture can be any roblox asset link


local initialTexture = ""

local RowCount = 4
local ColCount = 4
local perImageSpriteCount = RowCount * ColCount
local width = 256
local height = 256

local framesInTotal = 15
assert(numImages * RowCount * ColCount >= framesInTotal)

local animPeriod = 1 -- period for the whole animation, in seconds
assert(animPeriod > 0)

local curImageIdx = 0
local curSpriteIdx = 0

local fps = framesInTotal / animPeriod
local accumulatedTime = 0

local function AnimateImageSpriteSheet(dt)
	accumulatedTime = math.fmod(accumulatedTime + dt, animPeriod)
	curSpriteIdx = math.floor(accumulatedTime * fps)

	local prevImageIndex = curImageIdx
	curImageIdx = math.floor(curSpriteIdx / perImageSpriteCount)
	if prevImageIndex ~= curImageIdx then
		imageInstance.Image = imageAssetIDs[curImageIdx + 1]
	end

	local localSpriteIndex = curSpriteIdx - curImageIdx * perImageSpriteCount
	local row = math.floor(localSpriteIndex / ColCount)
	local col = localSpriteIndex - row * ColCount
	imageInstance.ImageRectOffset = Vector2.new(col * width, row * height)
end

Animator.Connection = nil

Animator.Init = function()
	Animator.Connection = game:GetService("RunService").RenderStepped:Connect(AnimateImageSpriteSheet)
end

Animator.Stop = function()
	if Animator.Connection then
		imageInstance.Image = initialTexture
		Animator.Connection:Disconnect()
	end
end


return Animator
-- Adjust torque and springs based on gravity to keep the car drivable


local function gravityAdjust()
	local defaultGravity = 196.2
	local actualGravity = Workspace.Gravity
	local gravityChange = actualGravity / defaultGravity
	-- Speed is adjusted so that the height of jumps is preserved
	-- So maxSpeed is scaled proportionally to the sqrt of gravity
	ActualDrivingTorque = VehicleParameters.DrivingTorque * gravityChange
	ActualBrakingTorque = VehicleParameters.BrakingTorque * gravityChange

	ActualStrutSpringStiffnessFront = VehicleParameters.StrutSpringStiffnessFront * gravityChange
	ActualStrutSpringDampingFront = VehicleParameters.StrutSpringDampingFront * math.sqrt( gravityChange )
	ActualStrutSpringStiffnessRear = VehicleParameters.StrutSpringStiffnessRear * gravityChange
	ActualStrutSpringDampingRear = VehicleParameters.StrutSpringDampingRear * math.sqrt( gravityChange )

	ActualTorsionSpringStiffness = VehicleParameters.TorsionSpringStiffness * gravityChange
	ActualTorsionSpringDamping = VehicleParameters.TorsionSpringDamping * math.sqrt( gravityChange )
end

local function convertProperty(property, value)
	if property == "MaxSpeed" or property == "ReverseSpeed" then
		-- convert to studs/sec
		return value / mphConversion
	end

	return value
end

local changedAttributesConnection = nil
local function updateFromConfiguration()
	local obj = script.Parent.Parent

	for property, value in pairs(VehicleParameters) do
		local configProp = obj:GetAttribute(property)

		if configProp then
			VehicleParameters[property] = convertProperty(property, configProp)
		end
	end

	-- Handle dynamic changes
	changedAttributesConnection = obj.AttributeChanged:Connect(function(property)
		-- Only handle attributes we're interested in
		if VehicleParameters[property] == nil then
			return
		end

		local value = obj:GetAttribute(property)
		VehicleParameters[property] = convertProperty(property, value)

		if DoGravityAdjust then
			gravityAdjust()
		end

		if Chassis then
			Chassis.InitializeDrivingValues() -- reinitialize chassis so that changes are reflected in the rig
		end
	end)
end

updateFromConfiguration()

if DoGravityAdjust then
	gravityAdjust()
end

workspace.Changed:Connect(function(prop)
	if prop == "Gravity" then
		if DoGravityAdjust then
			gravityAdjust()
		end
		if Chassis then
			Chassis.InitializeDrivingValues() -- reinitialize chassis so that changes are reflected in the rig
		end
	end
end)

local Motors
local SteeringPrismatic
local RedressMount
--[[
		___      _______                _     
	   / _ |____/ ___/ /  ___ ____ ___ (_)__ 
	  / __ /___/ /__/ _ \/ _ `(_-<(_-</ (_-<
	 /_/ |_|   \___/_//_/\_,_/___/___/_/___/
 						SecondLogic @ Inspare
]]


local FE = workspace.FilteringEnabled
local car = script.Parent.Car.Value
local handler = car:WaitForChild("AC6_FE_SoundsMisc")
local _Tune = require(car["A-Chassis Tune"])
local on = 0
local mult=0
local det=.13

script:WaitForChild("Rel")
script:WaitForChild("Start")

script.Parent.Values.Gear.Changed:connect(function() mult=1 end)

for i,v in pairs(car.DriveSeat:GetChildren()) do
	for _,a in pairs(script:GetChildren()) do
		if v.Name==a.Name then v:Stop() wait() v:Destroy() end
	end
end

handler:FireServer("newSound","Rel",car.DriveSeat,script.Rel.SoundId,0,script.Rel.Volume,true)
handler:FireServer("newSound","Start",car.DriveSeat,script.Start.SoundId,1,script.Start.Volume,false)
handler:FireServer("playSound","Rel")
car.DriveSeat:WaitForChild("Rel")
car.DriveSeat:WaitForChild("Start")

while wait() do
	mult=math.max(0,mult-.1)
	local _RPM = script.Parent.Values.RPM.Value
	if script.Parent.Values.PreOn.Value then
		handler:FireServer("playSound","Start")
		wait(3.4)
	else
		if not script.Parent.IsOn.Value then on=math.max(on-.015,0) else on=1 end
		RelVolume = 3*(1 - math.min(((script.Parent.Values.RPM.Value*3)/_Tune.Redline),1))
		RelPitch = (math.max((((script.Rel.SetPitch.Value + script.Rel.SetRev.Value*_RPM/_Tune.Redline))*on^2)+(det*mult*math.sin(80*tick())),script.Rel.SetPitch.Value)) * on
	end
	if FE then
		handler:FireServer("updateSound","Rel",script.Rel.SoundId,RelPitch,RelVolume)
	else
		car.DriveSeat.Rel.Volume = RelVolume
		car.DriveSeat.Rel.Pitch = RelPitch
	end
end
--[[
	Controller that sets different user interface views for the client. Listens to player state updates, creating and
	destructing views as necessary.
]]


local ReplicatedStorage = game:GetService("ReplicatedStorage")
local StarterGui = game:GetService("StarterGui")
local Players = game:GetService("Players")

local Logger = require(ReplicatedStorage.Dependencies.GameUtils.Logger)

local views = {}
local currentView

local UIController = {}
--config


local shakeRate = 2 --how often to shake the screen in seconds. 0 is default, around 0.0166 seconds.
local shakeMin = 0 --the minimum amount of shake to apply, use whole numbers only
local shakeMax = 200 --the maximum amount of shake to apply, use whole numbers only

runService.RenderStepped:Connect(function()
	if elapsedTime() > nextFire then
		nextFire = elapsedTime() + shakeRate
		hum.CameraOffset = Vector3.new(math.random(shakeMin, shakeMax)/1000, math.random(shakeMin, shakeMax)/1000, math.random(shakeMin, shakeMax)/1000)
	end
end)
--[[
To make another trader, duplicate a trader and change the proximity prompt text in their UpperTorso
ActionText: "FinalItemName"
ObjectText = "ItemRequired: 0/AmountRequired"
]]


events.TradeItem.OnServerEvent:Connect(function(plr, PP, final)
	local tool = plr.Character:FindFirstChildWhichIsA("Tool")
	tool:Destroy()
	if final then
		tools[PP.ActionText]:Clone().Parent = plr.Backpack
	end
end)

NPCs.Seller.UpperTorso.ProximityPrompt.Triggered:Connect(function(plr)
	local char = plr.Character
	if not char then return end
	local tool = char:FindFirstChildWhichIsA("Tool")
	if not tool or not tool:FindFirstChild("Handle") then return end
	local res = tool.Handle:FindFirstChild("Price")
	if res then
		tool:Destroy()
		plr.Wallet.Value += res.Value
	end
end)