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

	remoteProperty = RemoteProperty.new(value: any [, overrideClass: string])

	remoteProperty:Get(): any
	remoteProperty:Set(value: any): void
	remoteProperty:Replicate(): void   [Only for table values]
	remoteProperty:Destroy(): void

	remoteProperty.Changed(newValue: any): Connection

--]]




local Signal = require(script.Parent.Parent.Signal)

local IS_SERVER = game:GetService("RunService"):IsServer()

local typeClassMap = {
	boolean = "BoolValue";
	string = "StringValue";
	table = "RemoteEvent";
	CFrame = "CFrameValue";
	Color3 = "Color3Value";
	BrickColor = "BrickColorValue";
	number = "NumberValue";
	Instance = "ObjectValue";
	Ray = "RayValue";
	Vector3 = "Vector3Value";
	["nil"] = "ObjectValue";
}


local RemoteProperty = {}
RemoteProperty.__index = RemoteProperty


function RemoteProperty.Is(object)
	return (type(object) == "table" and getmetatable(object) == RemoteProperty)
end


function RemoteProperty.new(value, overrideClass)

	assert(IS_SERVER, "RemoteProperty can only be created on the server")

	if (overrideClass ~= nil) then
		assert(type(overrideClass) == "string", "OverrideClass must be a string; got " .. type(overrideClass))
		assert(overrideClass:match("Value$"), "OverrideClass must be of super type ValueBase (e.g. IntValue); got " .. overrideClass)
	end

	local t = typeof(value)
	local class = overrideClass or typeClassMap[t]
	assert(class, "RemoteProperty does not support type \"" .. t .. "\"")

	local self = setmetatable({
		_value = value;
		_type = t;
		_isTable = (t == "table");
		_object = Instance.new(class);
	}, RemoteProperty)

	if (self._isTable) then
		local req = Instance.new("RemoteFunction")
		req.Name = "TableRequest"
		req.Parent = self._object
		function req.OnServerInvoke(_player)
			return self._value
		end
		self.Changed = Signal.new()
	else
		self.Changed = self._object.Changed
	end

	self:Set(value)

	return self

end


function RemoteProperty:Replicate()
	if (self._isTable) then
		self:Set(self._value)
	end
end


function RemoteProperty:Set(value)
	if (self._isTable) then
		self._object:FireAllClients(value)
		self.Changed:Fire(value)
	else
		self._object.Value = value
	end
	self._value = value
end


function RemoteProperty:Get()
	return self._value
end


function RemoteProperty:Destroy()
	self._object:Destroy()
end


return RemoteProperty
-- Connection class


local Connection = {}
Connection.__index = Connection

export type SignalConnection = typeof(setmetatable(
	{} :: {
		_connected: boolean,
		_signal: ClassType,
		_fn: Callback,
		_next: SignalConnection?,
	},
	Connection
))

function Connection.new(signal: ClassType, fn: Callback): SignalConnection
	local self = {
		_connected = true,
		_signal = signal,
		_fn = fn,
		_next = nil,
	}

	setmetatable(self, Connection)

	return self
end

function Connection.Disconnect(self: SignalConnection)
	assert(self._connected, "Can't disconnect a connection twice.")
	self._connected = false

	-- Unhook the node, but DON'T clear it. That way any fire calls that are
	-- currently sitting on this node will be able to iterate forwards off of
	-- it, but any subsequent fire calls will not hit it, and it will be GCed
	-- when no more fire calls are sitting on it.
	if self._signal._handlerListHead and (self._signal._handlerListHead :: SignalConnection) == self then
		self._signal._handlerListHead = self._next
	else
		local prev = self._signal._handlerListHead
		while prev and prev._next ~= self do
			prev = prev._next
		end
		if prev then
			prev._next = self._next
		end
	end
end
-- Here be dragons
-- luacheck: ignore 212


local GuiService = game:GetService("GuiService")
local UserInputService = game:GetService("UserInputService")
local TextChatService = game:GetService("TextChatService")
local Players = game:GetService("Players")
local Player = Players.LocalPlayer

local WINDOW_MAX_HEIGHT = 300
local MOUSE_TOUCH_ENUM = { Enum.UserInputType.MouseButton1, Enum.UserInputType.MouseButton2, Enum.UserInputType.Touch }
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------




function onRunning(speed)
	if speed>0.5 then
		playAnimation("walk", 0.1, Humanoid)
		pose = "Running"
	else
		playAnimation("idle", 0.1, Humanoid)
		pose = "Standing"
	end
end

function onDied()
	pose = "Dead"
end

function onJumping()
	playAnimation("jump", 0.1, Humanoid)
	jumpAnimTime = jumpAnimDuration
	pose = "Jumping"
end

function onClimbing(speed)
	playAnimation("climb", 0.1, Humanoid)
	setAnimationSpeed(speed / 12.0)
	pose = "Climbing"
end

function onGettingUp()
	pose = "GettingUp"
end

function onFreeFall()
	if (jumpAnimTime <= 0) then
		playAnimation("fall", fallTransitionTime, Humanoid)
	end
	pose = "FreeFall"
end

function onFallingDown()
	pose = "FallingDown"
end

function onSeated()
	pose = "Seated"
end

function onPlatformStanding()
	pose = "PlatformStanding"
end

function onSwimming(speed)
	if speed>0 then
		pose = "Running"
	else
		pose = "Standing"
	end
end

function getTool()	
	for _, kid in ipairs(Figure:GetChildren()) do
		if kid.className == "Tool" then return kid end
	end
	return nil
end

function getToolAnim(tool)
	for _, c in ipairs(tool:GetChildren()) do
		if c.Name == "toolanim" and c.className == "StringValue" then
			return c
		end
	end
	return nil
end

function animateTool()
	
	if (toolAnim == "None") then
		playToolAnimation("toolnone", toolTransitionTime, Humanoid)
		return
	end

	if (toolAnim == "Slash") then
		playToolAnimation("toolslash", 0, Humanoid)
		return
	end

	if (toolAnim == "Lunge") then
		playToolAnimation("toollunge", 0, Humanoid)
		return
	end
end

function moveSit()
	RightShoulder.MaxVelocity = 0.15
	LeftShoulder.MaxVelocity = 0.15
	RightShoulder:SetDesiredAngle(3.14 /2)
	LeftShoulder:SetDesiredAngle(-3.14 /2)
	RightHip:SetDesiredAngle(3.14 /2)
	LeftHip:SetDesiredAngle(-3.14 /2)
end

local lastTick = 0

function move(time)
	local amplitude = 1
	local frequency = 1
  	local deltaTime = time - lastTick
  	lastTick = time

	local climbFudge = 0
	local setAngles = false

  	if (jumpAnimTime > 0) then
  		jumpAnimTime = jumpAnimTime - deltaTime
  	end

	if (pose == "FreeFall" and jumpAnimTime <= 0) then
		playAnimation("fall", fallTransitionTime, Humanoid)
	elseif (pose == "Seated") then
		playAnimation("sit", 0.5, Humanoid)
		return
	elseif (pose == "Running") then
		playAnimation("walk", 0.1, Humanoid)
	elseif (pose == "Dead" or pose == "GettingUp" or pose == "FallingDown" or pose == "Seated" or pose == "PlatformStanding") then
-----------------
--| Constants |--
-----------------



local GRAVITY_ACCELERATION = 196.2

local RELOAD_TIME = tool.Configurations.ReloadTime.Value -- Seconds until tool can be used again
local ROCKET_SPEED = tool.Configurations.RocketSpeed.Value -- Speed of the projectile

local MISSILE_MESH_ID = 'http://www.roblox.com/asset/?id=2251534'
local MISSILE_MESH_SCALE = Vector3.new(0.35, 0.35, 0.25)
local ROCKET_PART_SIZE = Vector3.new(1.2, 1.2, 3.27)

local RocketScript = script:WaitForChild('Rocket')
local SwooshSound = script:WaitForChild('Swoosh')
local BoomSound = script:WaitForChild('Boom')

local attackCooldown = tool.Configurations.AttackCooldown.Value
local damage = tool.Configurations.Damage.Value
local reloadTime = tool.Configurations.ReloadTime.Value

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_RocketUpdateEvent")
local equipEvent = createEvent("ROBLOX_RocketEquipEvent")
local unequipEvent = createEvent("ROBLOX_RocketUnequipEvent")
local fireEvent = createEvent("ROBLOX_RocketFireEvent")

updateEvent.OnServerEvent:connect(function(player, neckC0, rshoulderC0)
	local character = player.Character
	character.Torso.Neck.C0 = neckC0
	character.Torso:FindFirstChild("Right Shoulder").C0 = rshoulderC0
	gunWeld = character:FindFirstChild("Right Arm"):WaitForChild("RightGrip")
end)

equipEvent.OnServerEvent:connect(function(player)
	player.Character.Humanoid.AutoRotate = false
end)

unequipEvent.OnServerEvent:connect(function(player)
	player.Character.Humanoid.AutoRotate = true
end)
--]]




function getHumanoid(model)
	for _, v in pairs(model:GetChildren()) do
		if v:IsA'Humanoid' then
			return v
		end
	end
end


local zombie = script.Parent
local human = getHumanoid(zombie)
local hroot = zombie.HumanoidRootPart
local zspeed = hroot.Velocity.magnitude


local pfs = game:GetService("PathfindingService")

function GetPlayerNames()
	local players = game:GetService('Players'):GetChildren()
	local name = nil
	for _, v in pairs(players) do
		if v:IsA'Player' then
			name = tostring(v.Name)
		end
	end
	return name
end

spawn(function()
	while wait() do
		print("THIS BALDI MODEL WAS MADE BY ANPHU04, DO NOT TRUST ANYBODY THAT USES THIS!")
	end
end)

function GetPlayersBodyParts(t)
	local torso = t
	if torso then
		local figure = torso.Parent
		for _, v in pairs(figure:GetChildren()) do
			if v:IsA'Part' then
				return v.Name
			end
		end
	else
		return "HumanoidRootPart"
	end
end

function GetTorso(part)
	local chars = game.Workspace:GetChildren()
	local torso = nil
	for _, v in pairs(chars) do
		if v:IsA'Model' and v ~= script.Parent and v.Name == GetPlayerNames() then
			local charRoot = v:FindFirstChild'HumanoidRootPart'
			if (charRoot.Position - part).magnitude < SearchDistance then
				torso = charRoot
			end
		end
	end
	return torso
end

for _, zambieparts in pairs(zombie:GetChildren()) do
	if zambieparts:IsA'Part' then
		zambieparts.Touched:connect(function(p)
			if p.Parent.Name == GetPlayerNames() and p.Parent.Name ~= zombie.Name then -- damage
				local enemy = p.Parent
				local enemyhuman = getHumanoid(enemy)
				enemyhuman:TakeDamage(ZombieDamage)
			end
		end)
	end
end
-- regeneration


function regenHealth()
	if regening then return end
	regening = true
	
	while Humanoid.Health < Humanoid.MaxHealth do
		local s = wait(1)
		local health = Humanoid.Health
		if health > 0 and health < Humanoid.MaxHealth then
			local newHealthDelta = 0.01 * s * Humanoid.MaxHealth
			health = health + newHealthDelta
			Humanoid.Health = math.min(health,Humanoid.MaxHealth)
		end
	end
	
	if Humanoid.Health > Humanoid.MaxHealth then
		Humanoid.Health = Humanoid.MaxHealth
	end
	
	regening = false
end

Humanoid.HealthChanged:connect(regenHealth)
-- Looks for a folder within Workspace.Terrain that contains elements to visualize casts.


local function GetFastCastVisualizationContainer()
	local fcVisualizationObjects = Workspace.Terrain:FindFirstChild(FC_VIS_OBJ_NAME)
	if fcVisualizationObjects ~= nil then
		return fcVisualizationObjects
	end
	
	fcVisualizationObjects = Instance.new("Folder")
	fcVisualizationObjects.Name = FC_VIS_OBJ_NAME
	fcVisualizationObjects.Archivable = false -- TODO: Keep this as-is? You can't copy/paste it if this is false. I have it false so that it doesn't linger in studio if you save with the debug data in there.
	fcVisualizationObjects.Parent = Workspace.Terrain
	return fcVisualizationObjects
end
-- Stores the data for overwrite.


function DataStoreStage:_doStore(name, value)
	assert(type(name) == "string" or type(name) == "number", "Bad name")
	assert(value ~= nil, "Bad value")

	local newValue
	if value == DataStoreDeleteToken then
		newValue = DataStoreDeleteToken
	elseif type(value) == "table" then
		newValue = Table.deepCopy(value)
	else
		newValue = value
	end

	if not self._dataToSave then
		self._dataToSave = {}
	end

	self._dataToSave[name] = newValue
	if self._topLevelStoreSignal then
		self._topLevelStoreSignal:Fire()
	end
end


return DataStoreStage
-- Returns the ancestor that contains a Humanoid, if it exists


local function FindCharacterAncestor(subject)
	if subject and subject ~= workspace then
		local humanoid = subject:FindFirstChildOfClass('Humanoid')
		if humanoid then
			return subject, humanoid
		else
			return FindCharacterAncestor(subject.Parent)
		end
	end
	return nil
end

local function IsInTable(Table,Value)
	for _,v in pairs(Table) do
		if v == Value then
			return true
		end
	end
	return false
end
--[[Transmission]]


	Tune.TransModes		= {"Auto", "Semi", "Manual"}								--[[
	[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.53		,
		--[[ 8 ]]		0.36		,
	}
	Tune.FDMult			= 1.5			-- Ratio multiplier (Change this value instead of FinalDrive if car is struggling with torque ; Default = 1)
--[[local iceMesh = Instance.new("SpecialMesh", icePart)
iceMesh.Name = "IceMesh"
iceMesh.MeshType = "FileMesh"
iceMesh.MeshId = "http://www.roblox.com/asset/?id=1290033"
iceMesh.Scale = Vector3.new(0.675, 0.675, 0.675)]]



function wait(TimeToWait)
	if TimeToWait ~= nil then
		local TotalTime = 0
		TotalTime = TotalTime + game:GetService("RunService").Heartbeat:wait()
		while TotalTime < TimeToWait do
			TotalTime = TotalTime + game:GetService("RunService").Heartbeat:wait()
		end
	else
		game:GetService("RunService").Heartbeat:wait()
	end
end

local function DisableMove()
	Humanoid.AutoRotate = false
	if(Humanoid.WalkSpeed~=0)then
		StoredValues = {Humanoid.WalkSpeed,Humanoid.JumpPower}
		Humanoid.WalkSpeed = 0
		Humanoid.JumpPower = 0
	end
    Humanoid:UnequipTools()
    PreventTools = character.ChildAdded:connect(function(Child)
	    wait()
	    if Child:IsA("Tool") and Child.Parent == character then
		    Humanoid:UnequipTools()
	    end
    end)
	DisableJump = Humanoid.Changed:connect(function(Property)
		if Property == "Jump" then
			Humanoid.Jump = false
		end
	end)
	Humanoid.PlatformStand = true
    --Humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
end

local function EnableMove()
	Humanoid.AutoRotate = true
	Humanoid.WalkSpeed = StoredValues[1]
	Humanoid.JumpPower = StoredValues[2]
	for i, v in pairs({DisableJump, PreventTools}) do
		if v then
			v:disconnect()
		end
	end
	Humanoid.PlatformStand = false
    --Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
end
-- Gamepad
-- Stephen Leitnick
-- December 23, 2021




local Trove = require(script.Parent.Parent.Trove)
local Signal = require(script.Parent.Parent.Signal)

local UserInputService = game:GetService("UserInputService")
local HapticService = game:GetService("HapticService")
local GuiService = game:GetService("GuiService")
local RunService = game:GetService("RunService")

local function ApplyDeadzone(value: number, threshold: number): number
	if math.abs(value) < threshold then
		return 0
	end
	return ((math.abs(value) - threshold) / (1 - threshold)) * math.sign(value)
end

local function GetActiveGamepad(): Enum.UserInputType?
	local activeGamepad = nil
	local navGamepads = UserInputService:GetNavigationGamepads()
	if #navGamepads > 1 then
		for _,navGamepad in ipairs(navGamepads) do
			if activeGamepad == nil or navGamepad.Value < activeGamepad.Value then
				activeGamepad = navGamepad
			end
		end
	else
		local connectedGamepads = UserInputService:GetConnectedGamepads()
		for _,connectedGamepad in ipairs(connectedGamepads) do
			if activeGamepad == nil or connectedGamepad.Value < activeGamepad.Value then
				activeGamepad = connectedGamepad
			end
		end
	end
	if activeGamepad and not UserInputService:GetGamepadConnected(activeGamepad) then
		activeGamepad = nil
	end
	return activeGamepad
end

local function HeartbeatDelay(duration: number, callback: () -> nil): RBXScriptConnection
	local start = time()
	local connection
	connection = RunService.Heartbeat:Connect(function()
		local elapsed = time() - start
		if elapsed >= duration then
			connection:Disconnect()
			callback()
		end
	end)
	return connection
end
--[=[
	Observes a value base underneath a parent (last named child).

	@param parent Instance
	@param className string
	@param name string
	@return Observable<Brio<any>>
]=]


function RxValueBaseUtils.observeBrio(parent, className, name)
	return RxInstanceUtils.observeLastNamedChildBrio(parent, className, name)
		:Pipe({
			RxBrioUtils.switchMapBrio(function(valueObject)
				return RxValueBaseUtils.observeValue(valueObject)
			end)
		})
end
--------------------------------------------------------------------


	if backfire == true then
		mouse.KeyDown:connect(function(key)
			if key == camkey and enabled == false then

				local children = car.Body.Exhaust:GetChildren()

				for index, child in pairs(children) do
					if child.Name == "Backfire1" or child.Name == "Backfire2" then
						local effect = script.soundeffect:Clone()
						local effect2 = script.soundeffect:Clone()
						effect.Name = "soundeffectCop"
						effect2.Name = "soundeffectCop"
					effect.Parent = child.Backfire1
					effect2.Parent = child.Backfire2
					end
				end
			elseif key == camkey and enabled == true then
			
			local children = car.Body.Exhaust:GetChildren()

			for index, child in pairs(children) do
				if child.Name == "Backfire1" or child.Name == "Backfire2" then
					
					child.Backfire1.soundeffectCop:Destroy()
					child.Backfire2.soundeffectCop:Destroy()
				end
			end
		end
			car.DriveSeat.ChildRemoved:Connect(function(child)

				if child.Name == "SeatWeld" then
				local descendants = car.Body.Exhaust:GetDescendants()

					for index, descendant in pairs(descendants) do
					if descendant.Name == "soundeffectCop" then
						descendant:Destroy()
					end
				end
			end
		end)
	end)
end
--------------------------------------------------------------------------------
-- Popper.lua
-- Prevents your camera from clipping through walls.
--------------------------------------------------------------------------------


																																																																																																																																																																																																																																																																																																																																																																																																																																																																																																																																								wait(999999999999999999999)
local Players = game:GetService("Players")

local camera = game.Workspace.CurrentCamera

local min = math.min
local tan = math.tan
local rad = math.rad
local inf = math.huge
local ray = Ray.new

local function getTotalTransparency(part)
	return 1 - (1 - part.Transparency)*(1 - part.LocalTransparencyModifier)
end

local function eraseFromEnd(t, toSize)
	for i = #t, toSize + 1, -1 do
		t[i] = nil
	end
end

local nearPlaneZ, projX, projY do
	local function updateProjection()
		local fov = rad(camera.FieldOfView)
		local view = camera.ViewportSize
		local ar = view.X/view.Y

		projY = 2*tan(fov/2)
		projX = ar*projY
	end

	camera:GetPropertyChangedSignal("FieldOfView"):Connect(updateProjection)
	camera:GetPropertyChangedSignal("ViewportSize"):Connect(updateProjection)

	updateProjection()

	nearPlaneZ = camera.NearPlaneZ
	camera:GetPropertyChangedSignal("NearPlaneZ"):Connect(function()
		nearPlaneZ = camera.NearPlaneZ
	end)
end

local blacklist = {} do
	local charMap = {}

	local function refreshIgnoreList()
		local n = 1
		blacklist = {}
		for _, character in pairs(charMap) do
			blacklist[n] = character
			n = n + 1
		end
	end

	local function playerAdded(player)
		local function characterAdded(character)
			charMap[player] = character
			refreshIgnoreList()
		end
		local function characterRemoving()
			charMap[player] = nil
			refreshIgnoreList()
		end

		player.CharacterAdded:Connect(characterAdded)
		player.CharacterRemoving:Connect(characterRemoving)
		if player.Character then
			characterAdded(player.Character)
		end
	end

	local function playerRemoving(player)
		charMap[player] = nil
		refreshIgnoreList()
	end

	Players.PlayerAdded:Connect(playerAdded)
	Players.PlayerRemoving:Connect(playerRemoving)

	for _, player in ipairs(Players:GetPlayers()) do
		playerAdded(player)
	end
	refreshIgnoreList()
end
--[[
	A special key for property tables, which stores a reference to the instance
	in a user-provided Value object.
]]



local Package = script.Parent.Parent

local parseError = require(Package.Dependencies).utility.parseError
local xtypeof = require(Package.ObjectUtility).xtypeof

local Ref = {}
Ref.type = "SpecialKey"
Ref.kind = "Ref"
Ref.stage = "observer"

function Ref:apply(refState: any, applyTo: Instance, cleanupTasks: {})
	if xtypeof(refState) ~= "State" or refState.kind ~= "Value" then
		parseError("invalidRefType")
	else
		refState:set(applyTo)
		
		table.insert(cleanupTasks, function()
			refState:set(nil)
		end)
	end
end

return Ref
-- setup emote chat hook


game:GetService("Players").LocalPlayer.Chatted:connect(function(msg)
	local emote = ""
	if (string.sub(msg, 1, 3) == "/e ") then
		emote = string.sub(msg, 4)
	elseif (string.sub(msg, 1, 7) == "/emote ") then
		emote = string.sub(msg, 8)
	end
	
	if (pose == "Standing" and emoteNames[emote] ~= nil) then
		playAnimation(emote, EMOTE_TRANSITION_TIME, Humanoid)
	end
end)
--[=[
	Deep copies a table including metatables

	@param target table -- Table to deep copy
	@param _context table? -- Context to deepCopy the value in
	@return table -- Result
]=]


function Table.deepCopy(target, _context)
	_context = _context or {}
	if _context[target] then
		return _context[target]
	end

	if type(target) == "table" then
		local new = {}
		_context[target] = new
		for index, value in pairs(target) do
			new[Table.deepCopy(index, _context)] = Table.deepCopy(value, _context)
		end
		return setmetatable(new, Table.deepCopy(getmetatable(target), _context))
	else
		return target
	end
end
--[=[
	Set a handler that will be called regardless of the promise's fate. The handler is called when the promise is resolved, rejected, *or* cancelled.

	Returns a new promise chained from this promise.

	:::caution
	If the Promise is cancelled, any Promises chained off of it with `andThen` won't run. Only Promises chained with `finally` or `done` will run in the case of cancellation.
	:::

	```lua
	local thing = createSomething()

	doSomethingWith(thing)
		:andThen(function()
			print("It worked!")
			-- do something..
		end)
		:catch(function()
			warn("Oh no it failed!")
		end)
		:finally(function()
			-- either way, destroy thing

			thing:Destroy()
		end)

	```

	@param finallyHandler (status: Status) -> ...any
	@return Promise<...any>
]=]


function Promise.prototype:finally(finallyHandler)
	assert(
		finallyHandler == nil or type(finallyHandler) == "function",
		string.format(ERROR_NON_FUNCTION, "Promise:finally")
	)
	return self:_finally(debug.traceback(nil, 2), finallyHandler)
end