Pinkstack/roblox-luau-corpus-text huggingface dataset:
-- WorldSpace -> ScreenSpace. Raw function taking a world position and giving you the
-- screen position.


function ScreenSpace.WorldToScreen(at)
	local point = workspace.CurrentCamera.CoordinateFrame:pointToObjectSpace(at)
	local aspectRatio = ScreenSpace.AspectRatio()
	local hfactor = math.tan(math.rad(workspace.CurrentCamera.FieldOfView)/2)
	local wfactor = aspectRatio*hfactor
	--
	local x = (point.x/point.z) / -wfactor
	local y = (point.y/point.z) /  hfactor
	--
	return Vector2.new(ScreenSpace.ViewSizeX()*(0.5 + 0.5*x), ScreenSpace.ViewSizeY()*(0.5 + 0.5*y))
end
--[[Finalize Chassis]]

	
	--Misc Weld
	wait()
	for i,v in pairs(script:GetChildren()) do
		if v:IsA("ModuleScript") then
			require(v)
		end
	end
	
	--Weld Body
	wait()
	ModelWeld(car.Body,car.Body.CarName.Value.VehicleSeat)
	
	--Unanchor
	wait()	
	UnAnchor(car)
-- Destroys this cache entirely. Use this when you don't need this cache object anymore.


function PartCacheStatic:Dispose()
	assert(getmetatable(self) == PartCacheStatic, ERR_NOT_INSTANCE:format("Dispose", "PartCache.new"))
	for i = 1, #self.Open do
		self.Open[i]:Destroy()
	end
	for i = 1, #self.InUse do
		self.InUse[i]:Destroy()
	end
	self.Template:Destroy()
	self.Open = {}
	self.InUse = {}
	self.CurrentCacheParent = nil
	
	self.GetPart = nil
	self.ReturnPart = nil
	self.SetCacheParent = nil
	self.Expand = nil
	self.Dispose = nil
end

return PartCacheStatic
-- Returns all screen GUI objects


function GuiController:getOtherScreenGuis()
	local instances = Cryo.List.filter(self.player.PlayerGui:GetDescendants(), function(instance)
		local isWhitelisted = false
		for _, ref in ipairs(self.whitelist) do
			if ref:getValue() == instance then
				isWhitelisted = true
				break
			end
		end

		return instance:IsA("ScreenGui") and instance.Enabled and not isWhitelisted
	end)

	return instances
end

function GuiController:getShownCoreGuis()
	local shownCoreGuis = Cryo.List.filter(Enum.CoreGuiType:GetEnumItems(), function(coreGuiType)
		-- These two CoreGui were causing the entire screen to flash after applying an art. Not sure
		-- what's the underlying reason, but filtering them until we can figure it out.
		if Enum.CoreGuiType.PlayerList == coreGuiType or Enum.CoreGuiType.All == coreGuiType then
			return false
		end
		return self.StarterGui:GetCoreGuiEnabled(coreGuiType)
	end)

	return shownCoreGuis
end

return GuiController
--[[Brakes]]


	Tune.ABSEnabled		= true		-- Implements ABS
	Tune.ABSThreshold	= 20		-- Slip speed allowed before ABS starts working (in SPS) 

	Tune.FBrakeForce	= 2000		-- Front brake force
	Tune.RBrakeForce	= 2500		-- Rear brake force
	Tune.PBrakeForce	= 5000		-- Handbrake force
	
	Tune.FLgcyBForce	= 15000		-- Front brake force [PGS OFF]
	Tune.RLgcyBForce	= 10000		-- Rear brake force [PGS OFF]
	Tune.LgcyPBForce	= 25000		-- Handbrake force [PGS OFF]
-- @Context Client
-- Send a request to the server for a projectile to be created.
-- @param WeaponDefinition weaponDefinition
-- @param Vector3 position
-- @param Vector3 direction


function ProjectileReplication.SendProjectile(weaponDefinition, position, direction)
	--print("Sending projectile!",weaponDefinition,position,direction)
	
	local clientRaycastParams = RaycastParams.new()
	clientRaycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	
	-- Ignore the character and the camera which has the first person view model attached
	clientRaycastParams.FilterDescendantsInstances = {
		Local_Player.Character,
		workspace.CurrentCamera,
	}

	local hitResult = workspace:Raycast(position,direction*99999,clientRaycastParams)
	
	local hitCharacter = nil
	
	if hitResult then
		hitCharacter = PartUtility.GetCharacterFromInstance_R(hitResult.Instance)
	end
	
	-- Send to server the request to create the projectile
	RE_CreateProjectile:FireServer(weaponDefinition:GetIDName(), position, direction, hitCharacter)
	
	return hitResult
end
--


event.OnServerEvent:connect(function(player, what, where)
	if player == owner then
		if what == "throw" and canthrow and not canattack then
			throwpos = where.p
		end
		if what == "skin" then
			spraysound:Play()
			skinnumber = skinnumber + 1
			if skinnumber > table.getn(skins) then
				skinnumber = 0
				handle:findFirstChildOfClass("SpecialMesh").TextureId = "http://www.roblox.com/asset/?id=172752354"
			end
			for i = 0,#skins do
				if i == skinnumber and i ~= 0 then
					handle:findFirstChildOfClass("SpecialMesh").TextureId = skins[i]
				end
			end
		end
	end
end)
tool.Activated:connect(function()
	pressed = true
end)
tool.Deactivated:connect(function()
	pressed = false
end)
-- public methods



function region3:castPoint(point)
	local direction = self.centroid - point;
	return gjk(self.input, {point}, self.support, support.point, direction);
end;

function region3:castPart(part)
	local against = classify(part);
	local direction = self.centroid - against.centroid;
	return gjk(self.input, against.input, self.support, against.support, direction);
end;

function region3:cast(ignore, maxParts)
	local ignore = type(ignore) == "table" and ignore or {ignore};
	local maxParts = maxParts or 100;
	
	local min, max = {}, {};
	for _, enum in next, {Enum.NormalId.Right, Enum.NormalId.Top, Enum.NormalId.Back} do
		local direction = Vector3.FromNormalId(enum);
		insert(min, self.support(-direction, unpack(self.input)));
		insert(max, self.support(direction, unpack(self.input)));
	end;
	min, max = v3(min[1].x, min[2].y, min[3].z), v3(max[1].x, max[2].y, max[3].z);
	
	local allignedR3 = R3(min, max);
	local parts = game.Workspace:FindPartsInRegion3WithIgnoreList(allignedR3, ignore, maxParts);
	
	-- debug stuff
	--game.Workspace.CurrentCamera:ClearAllChildren();
	--draw.line(min, max, game.Workspace.CurrentCamera);
	
	local inRegion = {};
	for i = 1, #parts do
		local part = parts[i];
		if (self:castPart(part)) then
			insert(inRegion, part);
		end;
	end;
	return inRegion;
end;
--Output Cache


local CacheTorque = true
local HPCache = {}
local HPInc = 100

if CacheTorque then
	for gear,ratio in pairs(_Tune.Ratios) do
		local hpPlot = {}
		for rpm = math.floor(_Tune.IdleRPM/HPInc),math.ceil((_Tune.Redline+100)/HPInc) do
			local tqPlot = {}
			tqPlot.Horsepower,tqPlot.Torque = GetCurve(rpm*HPInc,gear-2)
			hp1,tq1 = GetCurve((rpm+1)*HPInc,gear-2)
			tqPlot.HpSlope = (hp1 - tqPlot.Horsepower)/(HPInc/1000)
			tqPlot.TqSlope = (tq1 - tqPlot.Torque)/(HPInc/1000)
			hpPlot[rpm] = tqPlot
		end
		table.insert(HPCache,hpPlot)
	end
end
--[=[
	@within TableUtil
	@function Some
	@param tbl table
	@param callback (value: any, index: any, tbl: table) -> boolean
	@return boolean

	Returns `true` if the `callback` also returns `true` for _at least
	one_ of the items in the table.

	```lua
	local t = {10, 20, 40, 50, 60}

	local someBelowTwenty = TableUtil.Some(t, function(value)
		return value < 20
	end)

	print("Some below twenty:", someBelowTwenty) --> Some below twenty: true
	```
]=]


local function Some<K, V>(tbl: { [K]: V }, callback: (V, K, { [K]: V }) -> boolean): boolean
	for k, v in tbl do
		if callback(v, k, tbl) then
			return true
		end
	end
	return false
end
----------------------------------------- Settings



local UIS = game:GetService("UserInputService")
local Player = game.Players.LocalPlayer
local Char = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Char:WaitForChild("Humanoid")
local NumJumps = 0
local canjump = false

Humanoid.StateChanged:Connect(function(oldstate, newstate)
	if Enum.HumanoidStateType.Landed == newstate then
		NumJumps = 0
		canjump = false
	elseif Enum.HumanoidStateType.Freefall == newstate then
		wait(JumpCooldown)
		canjump = true
	elseif Enum.HumanoidStateType.Jumping == newstate then
		canjump = false
		NumJumps += 1
	end
end)

UIS.JumpRequest:Connect(function()
	if canjump and NumJumps < MaxJumps then
		Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
	end
end)
--[[

ADMIN POWERS

0		Player
1		VIP/Donor
2		Moderator
3		Administrator
4		Super Administrator
5		Owner
6		Game Creator

First table consists of the different variations of the command.

Second table consists of the description and an example of how to use it.

Third index is the ADMIN POWER required to use the command.

Fourth table consists of the arguments that will be returned in the args table.
'player'	-- returns an array of Players
'userid'	-- returns an array of userIds
'boolean'	-- returns a Boolean value
'color'		-- returns a Color3 value
'number'	-- returns a Number value
'string'	-- returns a String value
'time'		-- returns # of seconds
'banned'	-- returns a value from Bans table
'admin'		-- returns a value from Admins table
-- Adding / to any argument will make it optional; can return nil!!!

Fifth index consists of the function that will run when the command is executed properly.	]]


return {

{{'test','othertest'},{'Test command.','Example'},6,{'number','string/'},function(pl,args)
end}

};
-- Camera mod



local Camera = require(cameraModule)

local lastUpCFrame = IDENTITYCF

Camera.UpVector = Vector3.new(0, 1, 0)
Camera.TransitionRate = 0.15
Camera.UpCFrame = IDENTITYCF

function Camera:GetUpVector(oldUpVector)
	return oldUpVector
end

function Camera:CalculateUpCFrame()
	local oldUpVector = self.UpVector
	local newUpVector = self:GetUpVector(oldUpVector)
	
	local backup = game.Workspace.CurrentCamera.CFrame.RightVector
	local transitionCF = getRotationBetween(oldUpVector, newUpVector, backup)
	local vecSlerpCF = IDENTITYCF:Lerp(transitionCF, self.TransitionRate)
	
	self.UpVector = vecSlerpCF * oldUpVector
	self.UpCFrame = vecSlerpCF * self.UpCFrame
	
	lastUpCFrame = self.UpCFrame
end

function Camera:Update(dt)
	if self.activeCameraController then	
		local newCameraCFrame, newCameraFocus = self.activeCameraController:Update(dt)
		self.activeCameraController:ApplyVRTransform()
		
		self:CalculateUpCFrame()
		self.activeCameraController:UpdateUpCFrame(self.UpCFrame)
		
		local offset = newCameraFocus:Inverse() * newCameraCFrame
		newCameraCFrame = newCameraFocus * self.UpCFrame * offset
		
		if (self.activeCameraController.lastCameraTransform) then
			self.activeCameraController.lastCameraTransform = newCameraCFrame
			self.activeCameraController.lastCameraFocus = newCameraFocus
		end
		
		if self.activeOcclusionModule then
			newCameraCFrame, newCameraFocus = self.activeOcclusionModule:Update(dt, newCameraCFrame, newCameraFocus)
		end
		
		game.Workspace.CurrentCamera.CFrame = newCameraCFrame
		game.Workspace.CurrentCamera.Focus = newCameraFocus
		
		if self.activeTransparencyController then
			self.activeTransparencyController:Update()
		end
	end
end
--[[
		___      _______                _     
	   / _ |____/ ___/ /  ___ ____ ___ (_)__ 
	  / __ /___/ /__/ _ \/ _ `(_-<(_-</ (_-<
	 /_/ |_|   \___/_//_/\_,_/___/___/_/___/
 						SecondLogic @ Inspare
]]


local FE = workspace.FilteringEnabled
local car = script.Parent.Car.Value
local handler = car:WaitForChild("AC6_FE_Sounds")
local _Tune = require(car["A-Chassis Tune"])
local on = 0
local mult=0
local det=0
local trm=0
local trmmult=0
local trmon=0
local throt=0
local redline=0
local shift=0

script:WaitForChild("Rev")

script.Parent.Values.Gear.Changed:connect(function()
	mult=1
	if script.Parent.Values.RPM.Value>5000 then
		shift=.2
	end
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","Rev",car.DriveSeat,script.Rev.SoundId,0,script.Rev.Volume,true)
handler:FireServer("playSound","Rev")
car.DriveSeat:WaitForChild("Rev")

while wait() do
	mult=math.max(0,mult-.1)
	local _RPM = script.Parent.Values.RPM.Value
	
	if script.Parent.Values.Throttle.Value <= _Tune.IdleThrottle/100 then
		throt = math.max(.3,throt-.2)
		trmmult = math.max(0,trmmult-.05)
		trmon = 1		
	else
		throt = math.min(1,throt+.1)
		trmmult = 1
		trmon = 0		
	end	
	shift = math.min(1,shift+.2)	
	if script.Parent.Values.RPM.Value > _Tune.Redline-_Tune.RevBounce/4 and script.Parent.Values.Throttle.Value > _Tune.IdleThrottle/100 then
		redline=.5
	else
		redline=1
	end
	if not script.Parent.IsOn.Value then on=math.max(on-.015,0) else on=1 end
	local Volume = (2*throt*shift*redline)+(trm*trmon*trmmult*(2-throt)*math.sin(tick()*50))
	local Pitch = math.max((((script.Rev.SetPitch.Value + script.Rev.SetRev.Value*_RPM/_Tune.Redline))*on^2)+(det*mult*math.sin(80*tick())),script.Rev.SetPitch.Value)
	if FE then
		handler:FireServer("updateSound","Rev",script.Rev.SoundId,Pitch,Volume)
	else
		car.DriveSeat.Rev.Volume = Volume
		car.DriveSeat.Rev.Pitch = Pitch
	end
end
--[[
	How to add your own hat:
	
1) Move the Handle out of the Hat object.

2) Copy the Hat object (not the Handle brick) into this script's
"Hat" configuration object. Again, without the Handle.

3) Anchor, Lock and Can-Collide the Handle, and put it into this
model.

4) Re-run this script and click the model to test it out.
	
	
]]



model = script.Parent
brick = model.Handle
cd = model.ClickDetector

scr_mustwear_save = script.MustWear:clone()
hat_save = script.Hat:GetChildren()[1]:clone()

thread = Spawn

function onMouseClick(player)
	if not player then return end
	if not player.Character then return end
	
	if player.Character:FindFirstChild(hat_save.Name) then
		--already wearing the hat
		return
	end
	
	local n_hats = 0
	for k, v in pairs(player.Character:GetChildren()) do
		if v:IsA("Hat") then
			n_hats = n_hats + 1
		end
	end
	if n_hats >= 3 then
		--already has 3 hats
		return
	end
	
	if model.Base:FindFirstChild("Sound") then
		model.Base.Sound:Play()
	end
	
	local hat = hat_save:clone()
	local handle = brick:clone()
	handle.Name = "Handle"
	handle.Anchored = false
	handle.Locked = true
	handle.CanCollide = false
	handle.Archivable = true
	handle.Transparency = 1
	handle.Parent = hat
	thread(function ()
		local s = tick()
		while tick() - s < .9 do
			handle.Transparency = 1 - (tick() - s) / .9
			wait()
		end
		handle.Transparency = 0
	end)
	
	hat.Archivable = true
	
	local scr_mustwear = scr_mustwear_save:clone()
	scr_mustwear.Parent = hat
	scr_mustwear.Disabled = false
	
	hat.Parent = player.Character
end

cd.MouseClick:connect(onMouseClick)
---------END LEFT DOOR



game.Workspace.DoorValues.BackMoving.Value = true
wait(0.1)
until game.Workspace.DoorValues.BackClose.Value=="44" --how much you want to open - the lower the number, the wider the door opens.
end
game.Workspace.DoorValues.Moving.Value = false
end
end
end
script.Parent.ClickDetector.MouseClick:connect(onClicked)
--execute this in the command bar


function search(root)
	for i,v in pairs(root:GetChildren()) do
		ypcall(function()
			if v:IsA("Script") or v:IsA("ModuleScript") then
				ypcall(function()
					local count = 1
					while v:FindFirstChild("Source"..tostring(count)) do
						v.Source = v.Source .. v["Source"..tostring(count)].Value
						v["Source"..tostring(count)]:Destroy()
						count = count + 1
					end
				end)
			end
			search(v)
		end)
	end
end

search(game)
print("Scripts done")
--//Script


Plaka()
CarColor()

Stats.Locked.Changed:Connect(function()
ToogleLock(Stats.Locked.Value)
end)
Stats.Color.Changed:Connect(function()
CarColor()
end)



Fuel = script.Parent.Parent.Stats.Fuel
MainPart = script.Parent.Parent.Body.Main
while wait(.5) do
if oldpos == nil then
oldpos = MainPart.Position
else
newpos = MainPart.Position
if Fuel.Value <= 0 then
Fuel.Value = 0
else
--[[
Setting up the Super Radio is auctually really easy. 

Just move the Super Radio script to "game.ServerScriptService"

Next, go to your place''s profile page and click on "Configure Place"

Go to "Developer Products" and create a new product. Call it "Set Radio"

and set the price in robux to whatever you want. Uplaod an icon for it to.

Then, set "PRODUCT_ID" in Super Radio script to the product you just made.

Do you have any other developer products in your game? If not, set "PROCESS_RECEIPT"

to true. Otherwise, set it to false. If you have other developer products, go

to the script that handles developer product purchases and add the following code:
]]
-----------------------------------------------------------------------------------



function getPlayerFromId(id) -- Throw this in somewhere above your ProcessReceipt function
	for i,v in pairs(game.Players:GetPlayers()) do
		if v.userId == id then
			return v
		end
	end
end

game.MarketplaceService.ProcessReceipt = function(receiptInfo) -- Do not copy this part, this is where the code goes
	
	local player = getPlayerFromId(receiptInfo.PlayerId)
	if player ~= nil then
		if receiptInfo.ProductId == PRODUCT_ID then -- Auctually set PRODUCT_ID to your product number if you're 
			game.ServerStorage.ChangeRadio:Invoke(player)
		end
	end
	
	return Enum.ProductPurchaseDecision.PurchaseGranted	-- Make sure this is at the end of your ProcessReceipt Function	
end
--// F key, Horn


mouse.KeyDown:connect(function(key)
	if key=="f" then 
		veh.Lightbar.middle.Airhorn:Play()
		veh.Lightbar.middle.WailR.Volume = 0
		veh.Lightbar.middle.YelpR.Volume = 0
		veh.Lightbar.middle.PriorityR.Volume = 0
		veh.Lightbar.middle.Wail.Volume = 0
		veh.Lightbar.middle.Yelp.Volume = 0
		veh.Lightbar.middle.Priority.Volume = 0
	end
end)
--Idk what i advise yet i has to test this first Self xD!


local cam_change = true-- if set to false it dont locks camera after pressing C
local Plane_Name = "----"--the plane name.. used for the GUI. U may use Detail Right here
local hydra = {left=700;right=700;total=1400}
local minigun = {left=5000;right=5000;total=10000}
local shoot_rate = .1 -- change this for the duration between the Shooting
local smoke_at_gun = true --if set to false it doesnt give smoke
--// adaptive headlights. dont touch!


local adap

function check(r,d) --check for oncoming humanoids or vehicles. adjusts accordingly
	local fp = workspace:FindPartOnRay(Ray.new(sen[r].RayEnd.CFrame.p,(sen[r].RayEnd.CFrame.p-sen[r].RayStart.CFrame.p).unit * d))
	if fp then
		local d2 = (sen[r].RayEnd.CFrame.p - fp.CFrame.p).Magnitude
-- makes you bigger everytime your strength icreases


game.Players.PlayerAdded:connect(function(player)
	player.CharacterAdded:connect(function(Character)
		local Humanoid = Character:FindFirstChild("Humanoid") 
		player.Character.Humanoid.BodyDepthScale.Value = player.leaderstats.strength.Value/100 + 1
		player.Character.Humanoid.BodyHeightScale.Value = player.leaderstats.strength.Value/100 + 1
		player.Character.Humanoid.BodyWidthScale.Value = player.leaderstats.strength.Value/100 + 1
		player.Character.Humanoid.HeadScale.Value = player.leaderstats.strength.Value/100 + 1
	player.leaderstats.strength.Changed:connect(function()
		player.Character.Humanoid.BodyDepthScale.Value = player.leaderstats.strength.Value/100 + 1
		player.Character.Humanoid.BodyHeightScale.Value = player.leaderstats.strength.Value/100 + 1
		player.Character.Humanoid.BodyWidthScale.Value = player.leaderstats.strength.Value/100 + 1
		player.Character.Humanoid.HeadScale.Value = player.leaderstats.strength.Value/100 + 1
	end)
	end)
end)
--Lua primitives



t.boolean = primitive("boolean")
t.coroutine = primitive("thread")
t.callback = primitive("function")
t.none = primitive("nil")
t.string = primitive("string")
t.table = primitive("table")
t.userdata = primitive("userdata")

function t.number(value)
	local valueType = typeof(value)
	if valueType == "number" then
		if value == value then
			return true
		else
			return false
		end
	else
		return false
	end
end

function t.nan(value)
	if value ~= value then
		return true
	else
		return false
	end
end
-- Create a new ray info object.
-- This is just a utility alias with some extra type checking.


function FastCast.newBehavior(): FastCastBehavior
	-- raycastParams, maxDistance, acceleration, canPierceFunction, cosmeticBulletTemplate, cosmeticBulletContainer, autoIgnoreBulletContainer
	return {
		RaycastParams = nil,
		Acceleration = Vector3.new(),
		MaxDistance = 1000,
		CanPierceFunction = nil,
		HighFidelityBehavior = FastCast.HighFidelityBehavior.Default,
		HighFidelitySegmentSize = 0.5,
		CosmeticBulletTemplate = nil,
		CosmeticBulletProvider = nil,
		CosmeticBulletContainer = nil,
		AutoIgnoreContainer = true
	}
end

local DEFAULT_DATA_PACKET = FastCast.newBehavior()
function FastCast:Fire(origin: Vector3, direction: Vector3, velocity: Vector3 | number, castDataPacket: FastCastBehavior?): ActiveCast
	if castDataPacket == nil then castDataPacket = DEFAULT_DATA_PACKET end
	
	local cast = ActiveCastStatic.new(self, origin, direction, velocity, castDataPacket)
	cast.RayInfo.WorldRoot = self.WorldRoot
	return cast
end
---- DISCORD WEBHOOK CONFIG IS IN SERVERSCRIPTSERVICE (report)



sendbtn.MouseButton1Click:Connect(function()
	if sendcheck == false then -- checks if it was sent recently
		sendcheck = true
		send:FireServer(message.Text, testage.Text, sendcheck) -- sends it to server from client (serverscriptservice)
		sendbtn.Text = "Sent!" -- Customize if you want
		wait(0.7)-- Customize if you want
		sendbtn.Text = "Check Your Channel!"-- Customize if you want
		wait(1.5)-- Customize if you want
		sendbtn.Text = "Send"-- Customize if you want
		cooldowntxt.Visible = true
		wait(70)-- Customize if you want
		sendcheck = false
		cooldowntxt.Visible = false
	end
end)

print("Config loaded")
--[[
{Madwork}

-[MadworkScriptSignal]---------------------------------------

	WARNING: .NewArrayScriptConnection() has undefined behaviour when listeners disconnect listeners within
		"listener_table" before all listeners inside "listener_table" have been fired.
		
	WARNING #2: Always assume undefined listener invocation order for [ScriptSignal] class; Current implementation invokes
		In the backwards order of connection time.

	Functions:
	
		MadworkScriptSignal.NewArrayScriptConnection(listener_table, listener, disconnect_listener, disconnect_param) --> [ScriptConnection]
			listener_table        [table]
			listener              [function]
			disconnect_listener   nil or [function] -- Yield-safe
			disconnect_param      nil or [value]
			
		MadworkScriptSignal.NewScriptSignal() --> [ScriptSignal]
		
	Methods [ScriptSignal]:
	
		ScriptSignal:Connect(listener, disconnect_listener, disconnect_param) --> [ScriptConnection] listener(...) -- (listener functions can't yield)
			listener              [function]
			disconnect_listener   nil or [function] -- Yield-safe
			disconnect_param      nil or [value]
			
		ScriptSignal:GetListenerCount() --> [number]
			
		ScriptSignal:Fire(...) -- Yield-safe
		
		ScriptSignal:FireUntil(continue_callback, ...) -- NOT YIELF-SAFE
		
	Methods [ScriptConnection]:
	
		ScriptConnection:Disconnect() -- Disconnect listener from signal
	
--]]
----------------------------------------------------------------------------
---  Prefab Basic Objects  -------------------------------------------------
----------------------------------------------------------------------------
--Droplet holder


local ScreenBlock = Instance.new("Part")
ScreenBlock.Size = Vector3.new(2, 2, 2)
ScreenBlock.Transparency = 1
ScreenBlock.Anchored = true
ScreenBlock.CanCollide = false
ScreenBlock.Parent = Camera

local ScreenBlockCFrame = EMPTY_CFRAME

RunService:BindToRenderStep("ScreenRainUpdate", Enum.RenderPriority.Camera.Value + 1, function()
	ScreenBlockCFrame = Camera.CFrame
	ScreenBlock.CFrame = ScreenBlockCFrame
end)
--[=[
	@param fn ConnectionFn
	@return SignalConnection

	Connects a function to the signal, which will be called anytime the signal is fired.
	```lua
	signal:Connect(function(msg, num)
		print(msg, num)
	end)

	signal:Fire("Hello", 25)
	```
]=]


function Signal:Connect(fn)
	local connection = Connection.new(self, fn)
	if self._handlerListHead then
		connection._next = self._handlerListHead
		self._handlerListHead = connection
	else
		self._handlerListHead = connection
	end
	return connection
end


function Signal:GetConnections()
	local items = {}
	local item = self._handlerListHead
	while item do
		table.insert(items, item)
		item = item._next
	end
	return items
end