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


local Array = require(script.Array)
local AssertionError = require(script.AssertionError)
local Error = require(script.Error)
local mapModule = require(script.Map)
local Object = require(script.Object)
local PromiseModule = require(script.Promise)
local Set = require(script.Set)
local Symbol = require(script.Symbol)
local Timers = require(script.Timers)
local WeakMap = require(script.WeakMap)

export type Array<T> = Array.Array<T>
export type AssertionError = AssertionError.AssertionError
export type Error = Error.Error
export type Map<T, V> = mapModule.Map<T, V>
export type Object = Object.Object

export type PromiseLike<T> = PromiseModule.PromiseLike<T>
export type Promise<T> = PromiseModule.Promise<T>

export type Set<T> = Set.Set<T>
export type Symbol = Symbol.Symbol
export type Timeout = Timers.Timeout
export type Interval = Timers.Interval
export type WeakMap<T, V> = WeakMap.WeakMap<T, V>

return {
	Array = Array,
	AssertionError = AssertionError,
	Boolean = require(script.Boolean),
	console = require(script.console),
	Error = Error,
	extends = require(script.extends),
	instanceof = require(script.instanceof),
	Math = require(script.Math),
	Number = require(script.Number),
	Object = Object,
	Map = mapModule.Map,
	coerceToMap = mapModule.coerceToMap,
	coerceToTable = mapModule.coerceToTable,
	Set = Set,
	WeakMap = WeakMap,
	String = require(script.String),
	Symbol = Symbol,
	setTimeout = Timers.setTimeout,
	clearTimeout = Timers.clearTimeout,
	setInterval = Timers.setInterval,
	clearInterval = Timers.clearInterval,
	util = require(script.util),
}
-- Setup Remote Events


local function createEvent(eventName)
	local event = game.ReplicatedStorage:FindFirstChild(eventName)
	if not event then
		event = Instance.new("RemoteEvent", game.ReplicatedStorage)
		event.Name = eventName
	end
	return event
end
local updateEvent = createEvent("ROBLOX_PistolUpdateEvent")
local equipEvent = createEvent("ROBLOX_PistolEquipEvent")
local unequipEvent = createEvent("ROBLOX_PistolUnequipEvent")
local fireEvent = createEvent("ROBLOX_PistolFireEvent")
local reloadEvent = createEvent("ROBLOX_PistolReloadEvent")
--[=[
	@return string
	Returns a unique render name for every call, which can
	be used with the `BindToRenderStep` method optionally.

	```lua
	shake:BindToRenderStep(Shake.NextRenderName(), ...)
	```
]=]


function Shake.NextRenderName(): string
	renderId += 1
	return ("__shake_%.4i__"):format(renderId)
end
--[[
    Returns a promise for a function which may yield. wrapAsync calls the
    the function in a coroutine and resolves with the output of the function
    after any asynchronous actions, and rejects if the function throws an error.
]]


function AsyncUtils.wrapAsync(fn)
	assert(type(fn) == "function")
	return Promise.new(
		function(resolve, reject)
			coroutine.wrap(
				function()
					local ok, result = pcall(fn)
					if ok then
						resolve(result)
					else
						reject(result)
					end
				end
			)()
		end
	)
end
--[[ http://coffeescript.org/ ]]

 --
local coffee = script.Parent;
local drinking = false

coffee.Equipped:connect(function()
	coffee.Handle.OpenSound:Play()
end)

coffee.Activated:connect(function()
	if drinking then
		return
	end

	drinking = true
	coffee.GripForward = Vector3.new(0,-.759,-.651)
	coffee.GripPos = Vector3.new(1.5,-.5,.3)
	coffee.GripRight = Vector3.new(1,0,0)
	coffee.GripUp = Vector3.new(0,.651,-.759)

	coffee.Handle.DrinkSound:Play()

	wait(2)
	
	coffee.Parent.Humanoid.Health = coffee.Parent.Humanoid.Health + 100
	restPos()

	drinking = false
end)

coffee.Unequipped:connect(function()
	restPos()
	coffee.Handle.DrinkSound:Stop()
	drinking = false
end)

function restPos()
	coffee.GripForward = Vector3.new(-.976,0,-0.217)
	coffee.GripPos = Vector3.new(0.03,0,0)
	coffee.GripRight = Vector3.new(.217,0,-.976)
	coffee.GripUp = Vector3.new(0,1,0)
end
--[[Susupension]]


	Tune.SusEnabled		= true		-- works only in with PGSPhysicsSolverEnabled, defaults to false when PGS is disabled
	
	--Front Suspension
	Tune.FSusDamping	= 500		-- Spring Dampening
	Tune.FSusStiffness	= 9000		-- Spring Force
	Tune.FAntiRoll 		= 50		-- Anti-Roll (Gyro Dampening)
	
	Tune.FSusLength		= 2			-- Suspension length (in studs)
	Tune.FPreCompress	= .1		-- 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	= 9000		-- Spring Force
	Tune.FAntiRoll 		= 50		-- Anti-Roll (Gyro Dampening)

	Tune.RSusLength		= 2			-- Suspension length (in studs)
	Tune.RPreCompress	= .1		-- 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		= false			-- 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
-- 3D TextGen



This = script.Parent
Btn = This.Parent
Lift = Btn.Parent.Parent.Parent
Config = require(Lift.Settings)
Characters = require(script.Characters)

CustomLabel = Config["CUSTOMFLOORLABEL"][tonumber(Btn.Name:sub(4))]

function ChangeFloor(SF)
	if string.len(SF) == 1 then
		SetLabel(1,SF,-0.03)	
		SetLabel(2,"NIL",0)
	else
		SetLabel(1,SF:sub(1,1),0)	
		SetLabel(2,SF:sub(2,2),0)
	end
end


function SetLabel(ID,CHAR,OFFSET)
	if This:FindFirstChild("L"..ID) and Characters[CHAR] ~= nil then
		This["L"..ID].Mesh.Offset = Vector3.new(OFFSET, -0.004, 0)
		for i,l in pairs(Characters[CHAR]) do 
			This["L"..ID].Mesh.MeshId = "rbxassetid://"..l
		end
	end
end


if CustomLabel then
	ChangeFloor(CustomLabel)
else
	ChangeFloor(Btn.Name:sub(4))
end

script:Destroy()
--- Queues the hitbox to be destroyed in the next frame


function Hitbox:Destroy()
	self.HitboxPendingRemoval = true

	if self.HitboxObject then
		CollectionService:RemoveTag(self.HitboxObject, self.Tag)
	end

	self:HitStop()
	self.OnHit:Destroy()
	self.OnUpdate:Destroy()
end
---------------------------------------------------



This = script.Parent
Lift = This.Parent.Parent.Parent
CustomLabel = require(This.Parent.Parent.Parent.CustomLabel)
Characters = require(script.Characters)

CustomText = CustomLabel["CUSTOMFLOORLABEL"]

Lift:WaitForChild("Floor").Changed:connect(function(floor)
  --custom indicator code--
  ChangeFloor(tostring(floor))
end)

function ChangeFloor(SF)
	if CustomText[tonumber(SF)] then
		SF = CustomText[tonumber(SF)]
	end
	SetDisplay(1,(string.len(SF) == 2 and SF:sub(1,1) or "NIL"))		
	SetDisplay(2,(string.len(SF) == 2 and SF:sub(2,2) or SF))
end



function SetDisplay(ID,CHAR)
	if This.Display:FindFirstChild("DIG"..ID) and Characters[CHAR] ~= nil then
 		for i,l in pairs(Characters[CHAR]) do 
			for r=1,16 do	
				This.Display["DIG"..ID]["D"..r].BrickColor = (l:sub(r,r) == "1" and BrickColor.new(ActiveColour) or BrickColor.new(InactiveColour))
				This.Display["DIG"..ID]["D"..r].Material = (l:sub(r,r) == "1" and "Neon" or "SmoothPlastic")
			end
		end
	end
end
-- 	local function getPropertyWin32(_target: unknown, key: any)
-- 		if typeof(key) == "string" then
-- 			return lookup[tostring((function()
-- 				if Array.indexOf(Object.keys(proto), tostring(key)) ~= -1 then
-- 					return key
-- 				else
-- 					return key:lower()
-- 				end
-- 			end)())]
-- 		else
-- 			return real[tostring(key)]
-- 		end
-- 	end
--[[
	Picks certain keys out of a table and place them into a new table.

	Parameters:
	- t (table): table to pick keys from
	- keys (string[]): list of keys to pick from the table

	Returns:
	- picked (table): table containing all picked values
	- rest (table): table containing all other values from initial table
]]


return function(t, keys)
	local picked, rest = {}, {}
	for _, key in ipairs(keys) do
		picked[key] = t[key]
	end

	for key, value in pairs(t) do
		if picked[key] ~= nil then
			continue
		end

		rest[key] = value
	end

	return picked, rest
end
--use this to determine if you want this human to be harmed or not, returns boolean



function boom()
	wait(2)
	Used = true
	Object.Anchored = true
	Object.CanCollide = false
	Object.Sparks.Enabled = false
	Object.Orientation = Vector3.new(0,0,0)
	Object.Transparency = 1
	Object.Fuse:Stop()
	Object.Explode:Play()
	Object.Dist:Play()
	Object.Explosion:Emit(100)
	Explode()
end

boom()
--Electrons--



local function AttachParticleControl(source_part)
	
	local prtc = nil
	
	local function Start()
		prtc = script.Electron: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
--- Internal function to create an AdornmentData type
--- Creates a LineHandleAdornment and a timer value


function cache:_CreateAdornment(): AdornmentData
	local line: LineHandleAdornment = Instance.new("LineHandleAdornment")
	line.Name = DEFAULT_DEBUGGER_RAY_NAME
	line.Color3 = DEFAULT_DEBUGGER_RAY_COLOUR
	line.Thickness = DEFAULT_DEBUGGER_RAY_WIDTH

	line.Length = 0
	line.CFrame = DEFAULT_FAR_AWAY_CFRAME

	line.Adornee = workspace.Terrain
	line.Parent = workspace.Terrain

	return {
		Adornment = line,
		LastUse = 0
	}
end
---[ This just makes it so the pizzas go invisible ] --



script.Parent.Pizza1.Changed:Connect(function()
	wait(1)
	if script.Parent.Pizza1.Value == true then
		script.Parent.Pizza1Part.Transparency = 1
		for i, x in pairs(script.Parent.Pizza1Part:GetChildren()) do
			x.Transparency = 1
		end
		wait(script.Parent.RespawnTime.Value)
		script.Parent.Pizza1Part.Transparency = 0
		for i, x in pairs(script.Parent.Pizza1Part:GetChildren()) do
			x.Transparency = 0
		end
		script.Parent.Pizza1.Value = false
	end
end)
script.Parent.Pizza2.Changed:Connect(function()
	wait(1)
	if script.Parent.Pizza2.Value == true then
		script.Parent.Pizza2Part.Transparency = 1
		for i, x in pairs(script.Parent.Pizza2Part:GetChildren()) do
			x.Transparency = 1
		end
		wait(script.Parent.RespawnTime.Value)
		script.Parent.Pizza2Part.Transparency = 0
		for i, x in pairs(script.Parent.Pizza2Part:GetChildren()) do
			x.Transparency = 0
		end
		script.Parent.Pizza2.Value = false
	end
end)
script.Parent.Pizza3.Changed:Connect(function()
	wait(1)
	if script.Parent.Pizza3.Value == true then
		script.Parent.Pizza3Part.Transparency = 1
		for i, x in pairs(script.Parent.Pizza3Part:GetChildren()) do
			x.Transparency = 1
		end
		wait(script.Parent.RespawnTime.Value)
		script.Parent.Pizza3Part.Transparency = 0
		for i, x in pairs(script.Parent.Pizza3Part:GetChildren()) do
			x.Transparency = 0
		end
		script.Parent.Pizza3.Value = false
	end
end)
---- STATE MODIFICATION ----



function ActiveCastStatic:Pause()
	assert(getmetatable(self) == ActiveCastStatic, ERR_NOT_INSTANCE:format("Pause", "ActiveCast.new(...)"))
	assert(self.StateInfo.UpdateConnection ~= nil, ERR_OBJECT_DISPOSED)
	self.StateInfo.Paused = true
end

function ActiveCastStatic:Resume()
	assert(getmetatable(self) == ActiveCastStatic, ERR_NOT_INSTANCE:format("Resume", "ActiveCast.new(...)"))
	assert(self.StateInfo.UpdateConnection ~= nil, ERR_OBJECT_DISPOSED)
	self.StateInfo.Paused = false
end

function ActiveCastStatic:Terminate(resultOfCast: RaycastResult?, isDecayed: boolean?)
	assert(getmetatable(self) == ActiveCastStatic, ERR_NOT_INSTANCE:format("Terminate", "ActiveCast.new(...)"))
	assert(self.StateInfo.UpdateConnection ~= nil, ERR_OBJECT_DISPOSED)
	
	-- First: Set EndTime on the latest trajectory since it is now done simulating.
	local trajectories = self.StateInfo.Trajectories
	local lastTrajectory = trajectories[#trajectories]
	lastTrajectory.EndTime = self.StateInfo.TotalRuntime
	
	-- Disconnect the update connection.
	if self.StateInfo.UpdateConnection then
		self.StateInfo.UpdateConnection:Disconnect()
	end
	
	-- Now fire CastTerminating
	self.Caster.CastTerminating:FireSync(self, resultOfCast, isDecayed)
	
	-- And now set the update connection object to nil.
	if self.StateInfo.UpdateConnection then
		self.StateInfo.UpdateConnection = nil
	end
	
	-- And nuke everything in the table + clear the metatable.
	self.Caster = nil
	self.StateInfo = nil
	self.RayInfo = nil
	--self.UserData = nil
	setmetatable(self, nil)
end

return ActiveCastStatic
-- Hi, thanks for downloading my plugin! This script is here to remove any unnecessary folders, that are used by this plugin to store data in the place, once the game runs.
-- The data this plugin may store is nothing personal. Some data is used for the "Cross-Server Protocols" tool to save the protocols you make for example.


	
	
	
game:GetService("RunService").Heartbeat:wait()
local d = {
	game.ServerStorage:WaitForChild("3DNotesData",5),
	game.ServerStorage:WaitForChild("CSProtocols",5),
	game.ServerStorage:WaitForChild("crossServerPath",5),
	game.ServerStorage:WaitForChild("InstanceCollectionPlugin",5),
	game.ServerStorage:WaitForChild("CSVariables",5),
	game.ServerStorage:WaitForChild("UIPresets",5)
}
for i,v in pairs(d) do
	v:Destroy()
end
--Fucntion for the buttons.


Frame:WaitForChild("Delete").MouseButton1Click:Connect(function()
	deletenumber()
end)
Frame:WaitForChild("Ok").MouseButton1Click:Connect(function()
	finish()
end)
Frame:WaitForChild("B0").MouseButton1Click:Connect(function()
	addnumber(0)	--plays addnunber function with a number that matches the button. For example when we pess button0, we play the function with number 0
end)
Frame:WaitForChild("B1").MouseButton1Click:Connect(function()
	addnumber(1)
end)
Frame:WaitForChild("B2").MouseButton1Click:Connect(function()
	addnumber(2)
end)
Frame:WaitForChild("B3").MouseButton1Click:Connect(function()
	addnumber(3)
end)
Frame:WaitForChild("B4").MouseButton1Click:Connect(function()
	addnumber(4)
end)
Frame:WaitForChild("B5").MouseButton1Click:Connect(function()
	addnumber(5)
end)
Frame:WaitForChild("B6").MouseButton1Click:Connect(function()
	addnumber(6)
end)
Frame:WaitForChild("B7").MouseButton1Click:Connect(function()
	addnumber(7)
end)
Frame:WaitForChild("B8").MouseButton1Click:Connect(function()
	addnumber(8)
end)
Frame:WaitForChild("B9").MouseButton1Click:Connect(function()
	addnumber(9)
end)
--[[
	This code took me about 2 hours to do, 
	
	I could just use Roblox's normal physics (Part's Velocity property), but it's really gross
	and broken, so I just made this one.
	
	Also, be sure to credit me if you're gonna use this in your game.
	
	UPDATE: 'RunService' function has been removed from the script due that it only works
	for StarterGui, lol.
]]
---Basic_Settings:---


local light = true -- Set to false if u dont have light added
local maxv = 110 -- 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
--------------------------------------Dont change anything under here!----------------------------------------------



function Setup()
	for i,p in pairs(game.Players:GetChildren()) do
		if (p.Character == wand.Parent) then

			if (connect ~= nil) then connect:Disconnect() end
			connect = p.Chatted:Connect(PlayerTalked)
			owner = p
		end
	end
end

function PlayerTalked(words)
	 
	if (string.find(string.lower(words) , string.lower(inc)) ~= nil) and (wand.Parent == owner.Character) then
		print("Casting the spell ''" ..inc.. "''")
		CastSpell()
	end
end

function CastSpell()
	wand.Parent.Humanoid.Jump = true
	wait(.33)
	wand.Parent.UpperTorso.Velocity = Vector3.new(0,10000,0)
end

wand.Equipped:Connect(Setup)
-- Existance in this list signifies that it is an emote, the value indicates if it is a looping emote


local emoteNames = { wave = false, point = false, dance = true, dance2 = true, dance3 = true, laugh = false, cheer = false}

math.randomseed(tick())

function findExistingAnimationInSet(set, anim)
	if set == nil or anim == nil then
		return 0
	end

	for idx = 1, set.count, 1 do 
		if set[idx].anim.AnimationId == anim.AnimationId then
			return idx
		end
	end

	return 0
end

function configureAnimationSet(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 = 0
		for _, childPart in pairs(config:GetChildren()) do
			if (childPart:IsA("Animation")) then
				local newWeight = 1
				local weightObject = childPart:FindFirstChild("Weight")
				if (weightObject ~= nil) then
					newWeight = weightObject.Value
				end
				animTable[name].count = animTable[name].count + 1
				idx = animTable[name].count
				animTable[name][idx] = {}
				animTable[name][idx].anim = childPart
				animTable[name][idx].weight = newWeight
				animTable[name].totalWeight = animTable[name].totalWeight + animTable[name][idx].weight
				table.insert(animTable[name].connections, childPart.Changed:Connect(function(property) configureAnimationSet(name, fileList) end))
				table.insert(animTable[name].connections, childPart.ChildAdded:Connect(function(property) configureAnimationSet(name, fileList) end))
				table.insert(animTable[name].connections, childPart.ChildRemoved:Connect(function(property) configureAnimationSet(name, fileList) end))
			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
		end
	end

	-- preload anims
	for i, animType in pairs(animTable) do
		for idx = 1, animType.count, 1 do
			if PreloadedAnims[animType[idx].anim.AnimationId] == nil then
				Humanoid:LoadAnimation(animType[idx].anim)
				PreloadedAnims[animType[idx].anim.AnimationId] = true
			end				
		end
	end
end
--[[
	Responsible for displaying a single piece of artwork on the canvas.
]]


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

SurfaceSpot.defaultProps = {
	padding = UDim.new(0, 16),
}

function SurfaceSpot:init()
	self.scale, self.updateScale = Roact.createBinding(1)
	self.scaleMotor = Otter.createSingleMotor(self.scale:getValue())
	self.scaleMotor:onStep(self.updateScale)

	self.transparency, self.updateTransparency = Roact.createBinding(0)
	self.transparencyMotor = Otter.createSingleMotor(self.transparency:getValue())
	self.transparencyMotor:onStep(self.updateTransparency)
end

function SurfaceSpot:render()
	local image = self.props.image or self.image

	return Roact.createElement("Frame", {
		BackgroundTransparency = 1,
		Size = UDim2.fromScale(1, 1),
		[Roact.Ref] = self.props.innerRef,
	}, {
		-- Add extra padding if needed
		Padding = Roact.createElement("UIPadding", {
			PaddingTop = self.props.padding,
			PaddingBottom = self.props.padding,
			PaddingLeft = self.props.padding,
			PaddingRight = self.props.padding,
		}),
		Art = image and Roact.createElement("ImageLabel", {
			BackgroundTransparency = 1,
			ImageTransparency = self.transparency,
			Size = UDim2.fromScale(1, 1),
			AnchorPoint = Vector2.new(0.5, 0.5),
			Position = UDim2.fromScale(0.5, 0.5),
			Image = image,
			ScaleType = Enum.ScaleType.Fit,
		}, {
			UIScale = Roact.createElement("UIScale", {
				Scale = self.scale,
			}),
			UIAspectRatio = Roact.createElement("UIAspectRatioConstraint", {
				DominantAxis = Enum.DominantAxis.Height,
				AspectType = Enum.AspectType.FitWithinMaxSize,
			}),
		}),
	})
end

function SurfaceSpot:willUpdate(nextProps)
	if nextProps.image == self.props.image then
		return
	end

	-- Stores the image temporarily before render is called so that ImageLabel does not unmount after image props
	-- change, and before animation completes.
	if not nextProps.image then
		self.image = self.props.image
	else
		self.image = nil
	end
end

function SurfaceSpot:didUpdate(prevProps)
	if prevProps.image ~= self.props.image then
		task.spawn(function()
			if self.props.image then
				-- Scale image when it appears
				self.transparencyMotor:setGoal(Otter.instant(0))
				self.scaleMotor:setGoal(Otter.spring(1.2))
				task.wait(1)
				self.scaleMotor:setGoal(Otter.spring(1))
				task.wait(1)
			else
				-- Fade image out when it disappears
				self.transparencyMotor:setGoal(Otter.spring(1))
				task.wait(1)
				self.image = nil
			end
		end)
	end
end

return Roact.forwardRef(function(props, ref)
	return Roact.createElement(SurfaceSpot, Cryo.Dictionary.join(props, { innerRef = ref }))
end)
-- functions



return function(character, boost)
	local upperTorso	= character.UpperTorso
	
	local glow		= script[boost].GlowEmitter:Clone()
		glow.Parent		= upperTorso
	local icon		= script[boost].IconEmitter:Clone()
		icon.Parent		= upperTorso
	local spark		= script[boost].SparkEmitter:Clone()
		spark.Parent	= upperTorso
		
	local sound		= script[boost .. "Sound"]:Clone()
		sound.Parent	= upperTorso
	
	glow:Emit(8)
	icon:Emit(10)
	spark:Emit(25)
	sound:Play()
		
	Debris:AddItem(glow, 4)
	Debris:AddItem(icon, 2)
	Debris:AddItem(spark, 2)
	Debris:AddItem(sound, sound.TimeLength)
end
--[[
local tmp = hits:Clone()
tmp.Disabled=false
tmp.Parent=L3
local tmp = hits:Clone()
tmp.Disabled=false
tmp.Parent=L4
]]



while true do
	l=L1.Position
	angle=angle + DELTA
	L1.CFrame=CFrame.new( Vector3.new(l.X,l.Y,l.Z)) * CFrame.Angles(0, math.rad(angle), 0 )

	l=L2.Position
	angle=angle + DELTA
	L2.CFrame=CFrame.new( Vector3.new(l.X,l.Y,l.Z)) * CFrame.Angles(0, math.rad(angle+45), 0 )