Pinkstack/roblox-luau-corpus-text huggingface dataset:
--Update list of players in admin panel


local selectPlrFrame = panel.Pages.MainButtonsFrame.ButtonsScroller.SelectPlayerFrame
local scroller = selectPlrFrame.PlayersScroller
local selectedFrame = selectPlrFrame.SelectedPlayerFrame
selectedFrame.Visible = false

function updatePlayers()
	for i, child in pairs(scroller:GetChildren()) do
		if child:IsA("TextButton") then
			child:Destroy()
		end
	end
	
	for i, plr in pairs(game.Players:GetPlayers()) do
		
		local btn = script.PlayerButton:Clone()
		
		local name = plr.Name
		btn.PlayerName.Text = name
		
		local image = game.Players:GetUserThumbnailAsync(plr.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size100x100)
		btn.PlayerImage.Image = image
		
		btn.MouseButton1Click:Connect(function()
			
			selectedFrame.PlayerName.Text = name
			selectedFrame.DisplayName.Text = "@" .. plr.DisplayName
			selectedFrame.UserId.Text = plr.UserId
			selectedFrame.InGame.Text = "Currently in server 🟢"
			selectedFrame.PlayerImage.Image = image
			
			selectedFrame.Visible = true
		end)
		
		btn.Parent = scroller
	end
end
updatePlayers()
game.Players.PlayerAdded:Connect(updatePlayers)
game.Players.PlayerRemoving:Connect(updatePlayers)
--Blood Parts Function


local createBlood = function(position)
	
	local randomSize = math.random(2, 20) / 10
	
	local bloodClone = bloodPart:Clone()
	bloodClone.Position = position + Vector3.new(0, 0.05, 0)
	bloodClone.Size = Vector3.new(randomSize, 0.1, randomSize)
	
	bloodClone.Parent = bloodCache
	
	if math.random(2) == 1 then
		bloodClone.BloodSound:Play()
	end
	
	return bloodClone
end
--[=[
	This can't be cheap. Consider deeply if you want this or not.

	@param selectFromBrio ((value: T) -> U)?
	@return (source: Observable<Brio<T>>) -> Observable<Brio{U}>
]=]


function RxBrioUtils.reduceToAliveList(selectFromBrio)
	assert(type(selectFromBrio) == "function" or selectFromBrio == nil, "Bad selectFromBrio")

	return function(source)
		return Observable.new(function(sub)
			local topMaid = Maid.new()

			local subscribed = true
			topMaid:GiveTask(function()
				subscribed = false
			end)
			local aliveBrios = {}
			local fired = false

			local function updateBrios()
				if not subscribed then -- No work if we don't need to.
					return
				end

				aliveBrios = BrioUtils.aliveOnly(aliveBrios)
				local values = {}
				if selectFromBrio then
					for _, brio in pairs(aliveBrios) do
						-- Hope for no side effects
						local value = selectFromBrio(brio:GetValue())
						assert(value ~= nil, "Bad value")

						table.insert(values, value)
					end
				else
					for _, brio in pairs(aliveBrios) do
						local value = brio:GetValue()
						assert(value ~= nil, "Bad value")

						table.insert(values, value)
					end
				end

				local newBrio = BrioUtils.first(aliveBrios, values)
				topMaid._lastBrio = newBrio

				fired = true
				sub:Fire(newBrio)
			end

			local function handleNewBrio(brio)
				-- Could happen due to throttle or delay...
				if brio:IsDead() then
					return
				end

				local maid = Maid.new()
				topMaid[maid] = maid -- Use maid as key so it's unique (reemitted brio)

				maid:GiveTask(function() -- GC properly
					topMaid[maid] = nil
					updateBrios()
				end)
				maid:GiveTask(brio:GetDiedSignal():Connect(function()
					topMaid[maid] = nil
				end))

				table.insert(aliveBrios, brio)
				updateBrios()
			end

			topMaid:GiveTask(source:Subscribe(
				function(brio)
					if not Brio.isBrio(brio) then
						warn(("[RxBrioUtils.mergeToAliveList] - Not a brio, %q"):format(tostring(brio)))
						topMaid._lastBrio = nil
						sub:Fail("Not a brio")
						return
					end

					handleNewBrio(brio)
				end,
				function(...)
					sub:Fail(...)
				end,
				function(...)
					sub:Complete(...)
				end))

			-- Make sure we emit an empty list if we discover nothing
			if not fired then
				updateBrios()
			end

			return topMaid
		end)
	end
end
--[[Transmission]]


	Tune.TransModes		= {"Auto", "Semi"}								--[[
	[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		,
	}
	Tune.FDMult			= 1.5			-- Ratio multiplier (Change this value instead of FinalDrive if car is struggling with torque ; Default = 1)
--		bg.CFrame = bg.CFrame * CFrame.Angles(0,0,0)


		IfOnLand()
		bv.Velocity = Vector3.new(0,0,0)
		seat.Anchored = true
		seat.Velocity = Vector3.new(0,0,0)
		wait()
		seat.Anchored = false
	end

end)

seat.Changed:connect(function(property)
if property == "Occupant" then
if seat.Occupant then
local p = game.Players:GetPlayerFromCharacter(seat.Occupant.Parent)
if p then
DriveEnabled = true
StartEngine()
end
else
walk:Stop()
DriveEnabled = false
lastLodged = tick()
wait(0.3)
Speed = 0
bv.Velocity = Vector3.new(0,0,0)
IfOnLand()
end
end
end)

local DespawnCoroutine = coroutine.wrap(function()
while wait(1) do
if tick()-breakTime >= 0 then
sp:Destroy()
end
end
end)
DespawnCoroutine()
--[=[
	Loading logic for Nevermore

	@private
	@class LoaderClass
]=]



local Loader = {}
Loader.ClassName = "Loader"
Loader.__index = Loader

function Loader.new(script)
	return setmetatable({
		_script = script;
	}, Loader)
end

local function waitForValue(objectValue)
	local value = objectValue.Value
	if value then
		return value
	end

	return objectValue.Changed:Wait()
end

function Loader:__call(value)
	if type(value) == "string" then
		local object = self._script.Parent[value]
		if object:IsA("ObjectValue") then
			return require(waitForValue(object))
		else
			return require(object)
		end
	else
		return require(value)
	end
end

function Loader:__index(value)
	if type(value) == "string" then
		local object = self._script.Parent[value]
		if object:IsA("ObjectValue") then
			return require(waitForValue(object))
		else
			return require(object)
		end
	else
		return require(value)
	end
end


return Loader
--FastCast.VisualizeCasts = true



local caster = FastCast.new()

local castParams = RaycastParams.new()
castParams.FilterType = Enum.RaycastFilterType.Blacklist
castParams.IgnoreWater = true

local bulletCache = PartCache.new(bulletTemplate, 100, bulletsFolder)

local castBehavior = FastCast.newBehavior()
castBehavior.RaycastParams = castParams
castBehavior.Acceleration = Vector3.new(0, -workspace.Gravity, 0)
castBehavior.AutoIgnoreContainer = false
castBehavior.CosmeticBulletContainer = bulletsFolder
castBehavior.CosmeticBulletProvider = bulletCache

local ammoLeft = 30
local reloading = false

local function reload()
	if reloading then return end
	reloading = true
	wait(5)
	ammoLeft = 30
	reloading = false
end

local function onEquipped()
	castParams.FilterDescendantsInstances = {tool.Parent, bulletsFolder}
end

local function onLengthChanged(cast, lastPoint, direction, length, velocity, bullet)
	if bullet then 
		local bulletLength = bullet.Size.Z/2
		local offset = CFrame.new(0, 0, -(length - bulletLength))
		bullet.CFrame = CFrame.lookAt(lastPoint, lastPoint + direction):ToWorldSpace(offset)
	end
end

local function onRayHit(cast, result, velocity, bullet)
	local hit = result.Instance
	
	local character = hit:FindFirstAncestorWhichIsA("Model")
	if character and character:FindFirstChild("Humanoid") then
		character.Humanoid:TakeDamage(50)
	end
	
	delay(2, function()
		bulletCache:ReturnPart(bullet)
	end)
end

local function fire(player, mousePosition)
	if tool.Parent:IsA("Backpack") then return end
	
	if ammoLeft > 0 and not reloading then
		local origin = firePoint.WorldPosition
		local direction = (mousePosition - origin).Unit
		
		caster:Fire(origin, direction, 1000, castBehavior)
		ammoLeft -= 1
	else
		reload()
	end
end

fireEvent.OnServerEvent:Connect(fire)
reloadEvent.OnServerEvent:Connect(reload)
tool.Equipped:Connect(onEquipped)

caster.LengthChanged:Connect(onLengthChanged)
--check mass to see if object is large enough to spray blood on


if dmg<1000 then
	for x = 1, math.floor(dmg*(math.random(1,7)*.105)) do
		local bloodRay = Ray.new(origin,(game.Players.LocalPlayer.Character.Torso.CFrame.p.unit * Vector3.new(math.random(-7,7)/60,math.random(-7,7)/60,math.random(-7,7)/60)).unit * 12)
		local hitPart, hitPoint = workspace:FindPartOnRayWithIgnoreList(bloodRay,{workspace.CurrentCamera,humanoid.Parent})
		if hitPart and hitPart.Transparency==0 and hitPart:GetMass() > 5 and hitPart.Anchored then
			local blood = Instance.new("Part",game.Workspace["Ray_Ignore"])

			blood.formFactor = "Custom"
			blood.Size = Vector3.new(math.random(1,3600)*.001,0.2,math.random(1,3600)*.001)
			blood.BrickColor = BrickColor.new("Bright red")
			blood.Anchored = true
			blood.CanCollide = false
			Instance.new("BlockMesh",blood).Scale = Vector3.new(math.random(0,112)*.001,0.1,math.random(0,112)*.001)
			local sc=script.bl:clone()
			sc.Parent=blood
			sc.Disabled=false
			blood.TopSurface = "Smooth"
			blood.BottomSurface = "Smooth"
			blood.Reflectance=0.2
			blood.Transparency=1
			local decalpick=math.random(1,3)
			if decalpick==1 then
			local crap=script.Decal1:clone()
			crap.Name="Decal"
			crap.Parent=blood
			elseif decalpick==2 then
			local crap=script.Decal2:clone()
			crap.Name="Decal"
			crap.Parent=blood
			elseif decalpick==3 then
			local crap=script.Decal3:clone()
			crap.Name="Decal"
			crap.Parent=blood
			end
			local normal = GetSurfaceNormal(hitPart,hitPoint).unit
			if pcall(function()
				blood.CFrame = CFrame.new(hitPoint,hitPoint + normal) * CFrame.Angles(1.57,math.random(0,300)/100,0) end) then
			end
			end
		end
	end
end

local hp=game.Players.LocalPlayer.Character.Humanoid.Health



character.Humanoid.HealthChanged:connect(function(health)
	--[[if game.Workspace:FindFirstChild("Ray_Ignore") then
splatterBlood(game.Players.LocalPlayer.Character.Torso.Position,game.Players.LocalPlayer.Character.Humanoid,hp-health)
end]]--
hp=game.Players.LocalPlayer.Character.Humanoid.Health
healthGUIUpdate(health)
end)
-- aboutWindow Functions


local function showAboutWindow()
	aboutWindow.Visible = true
	TweenService:Create(aboutWindow, Bar_Button_TweenInfo, {Size = UDim2.new(0,513, 0, 378), GroupTransparency = 0}):Play()
end

local function hideAboutWindow()
	TweenService:Create(aboutWindow, Bar_Button_TweenInfo, {Size = UDim2.new(0,500, 0, 365), GroupTransparency = 1}):Play()
	task.wait(0.3)
	aboutWindow.Visible = false
end
-- Container for temporary connections (disconnected automatically)


local Connections = {};

function DecorateTool.Equip()
	-- Enables the tool's equipped functionality

	-- Start up our interface
	ShowUI();

end;

function DecorateTool.Unequip()
	-- Disables the tool's equipped functionality

	-- Clear unnecessary resources
	HideUI();
	ClearConnections();

end;

function ClearConnections()
	-- Clears out temporary connections

	for ConnectionKey, Connection in pairs(Connections) do
		Connection:disconnect();
		Connections[ConnectionKey] = nil;
	end;

end;

function ShowUI()
	-- Creates and reveals the UI

	-- Reveal UI if already created
	if DecorateTool.UI then

		-- Reveal the UI
		DecorateTool.UI.Visible = true;

		-- Update the UI every 0.1 seconds
		UIUpdater = Support.ScheduleRecurringTask(UpdateUI, 0.1);

		-- Skip UI creation
		return;

	end;

	-- Create the UI
	DecorateTool.UI = Core.Tool.Interfaces.BTDecorateToolGUI:Clone();
	DecorateTool.UI.Parent = Core.UI;
	DecorateTool.UI.Visible = true;

	-- Enable each decoration type UI
	EnableOptionsUI(DecorateTool.UI.Smoke);
	EnableOptionsUI(DecorateTool.UI.Fire);
	EnableOptionsUI(DecorateTool.UI.Sparkles);

	-- Update the UI every 0.1 seconds
	UIUpdater = Support.ScheduleRecurringTask(UpdateUI, 0.1);

end;
--Change sound id to the id you want to play




debounce = false

script.Parent.Touched:connect(function(hit)
if not debounce then
debounce = true
if(hit.Parent:FindFirstChild("Humanoid")~=nil)then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
local sound = script.Parent.Sound:Clone()
sound.Parent = player.PlayerGui
sound:Play()
wait(0)--change to how long before the sound plays again after retouching it
end
debounce = false
end
end)
-- maps a value from one range to another, clamping to the output range. order does not matter


function CameraUtils.mapClamp(x, inMin, inMax, outMin, outMax)
	return math.clamp(
		(x - inMin)*(outMax - outMin)/(inMax - inMin) + outMin,
		math.min(outMin, outMax),
		math.max(outMin, outMax)
	)
end
--// # key, ManOn


mouse.KeyDown:connect(function(key)
	if key=="f" then 
		veh.Lightbar.middle.Man:Play()
		veh.Lightbar.middle.Wail.Volume = 1
		veh.Lightbar.middle.Yelp.Volume = 1
		veh.Lightbar.middle.Priority.Volume = 1
		script.Parent.Parent.Sirens.Man.BackgroundColor3 = Color3.fromRGB(215, 135, 110)
		veh.Lightbar.MAN.Transparency = 0
	end
end)
--local debris = game:GetService("Debris")



local bot = script.Parent -- bot stuff
local bhum = bot:WaitForChild('Humanoid')
local bhrp = bot:WaitForChild('HumanoidRootPart')

local findPath = PFS:CreatePath({WaypointSpacing = math.huge})
local actPath = PFS:CreatePath({WaypointSpacing = math.huge})

local followedChar -- the one we are already following

local char -- the one which we follow

local function nearestChar()
	while wait() do
		local nearChar, nearDist = nil, nil
		local distance
		local firstPos

		for i,v in pairs(workspace:GetChildren()) do
			if v:FindFirstChild('Humanoid') and v ~= bot and v.Humanoid.Health > 0 and v:FindFirstChild('HumanoidRootPart') then
				findPath:ComputeAsync(bhrp.Position, v.HumanoidRootPart.Position)
				if findPath.Status == Enum.PathStatus.Success then
					distance = 0
					for i,waypoint in ipairs(findPath:GetWaypoints()) do
						if i ~= 1 then
							distance = distance + (waypoint.Position - firstPos).Magnitude
						end
						firstPos = waypoint.Position
					end
					if nearDist == nil then
						nearDist = distance
						nearChar = v
					else
						if distance < nearDist then
							nearDist = distance
							nearChar = v
						end
					end
				end
			end
		end
		char = nearChar
	end
end

spawn(nearestChar)

local count = 0

RunS.Heartbeat:Connect(function()
	if count >= 3 then -- You may change this number to your liking, but if you set it too low nextbot will lag
		count = 0
		if char ~= nil and char:FindFirstChild('HumanoidRootPart') then
			actPath:ComputeAsync(bhrp.Position, char.HumanoidRootPart.Position)
			for i,v in ipairs(actPath:GetWaypoints()) do
				if i ~= 1 then
					bhum:MoveTo(v.Position)
					bhum.MoveToFinished:Wait()
				end
			end
		end
	else
		count = count + 1
	end
end)
--[=[
	Creates a new Blend State which is actually just a ValueObject underneath.

	@param defaultValue T
	@return ValueObject<T>
]=]


function Blend.State(defaultValue)
	return ValueObject.new(defaultValue)
end

function Blend.Dynamic(...)
	return Blend.Computed(...)
		:Pipe({
			-- This switch map is relatively expensive, so we don't do this for defaul computed
			-- and instead force the user to switch to another promise
			Rx.switchMap(function(promise, ...)
				if Promise.isPromise(promise) then
					return Rx.fromPromise(promise)
				elseif Observable.isObservable(promise) then
					return promise
				else
					return Rx.of(promise, ...)
				end
			end)
		})
end
-----------------------------------------------------------------------------------------------



Door = script.Parent
Serv = game:GetService("BadgeService")
MServ = game:GetService("MarketplaceService")
if not _G.Players then
	_G.Players = {[ItemID] = {}}
elseif not _G.Players[ItemID] then
	_G.Players[ItemID] = {}
end

Table = _G.Players[ItemID]

function CheckPlayer(player2)
	for i = 1,#Table do
		if Table[i] == player2 then
			return true
		end
	end
	return false
end

Door.Touched:connect(function(hit)
    if game.Players:GetPlayerFromCharacter(hit.Parent) then
        player = game.Players:GetPlayerFromCharacter(hit.Parent)
        if Serv:UserHasBadge(player.userId,ItemID) or CheckPlayer(player) then
          --  Door.CanCollide = false-- Door.Transparency = OpenTrans
            wait(OpenTime)
         --   Door.CanCollide = true --Door.Transparency = CloseTrans
            else
           -- Door.CanCollide = true-- Door.Transparency = CloseTrans
            if BuyGUI == true then
                MServ:PromptGamePassPurchase(player,ItemID)
                h = player.Character:FindFirstChild("Humanoid")
                if h then
                    h.WalkSpeed = 16 end
                    local con
                    con = MServ.PromptGamePassPurchaseFinished:connect(function(ply,asset,purch)
                    if ply == player and asset == ItemID then
                        con:disconnect()
                        if purch then
                            if h then
                                h.WalkSpeed = 16 end
                                table.insert(Table,player)
                                elseif KillOnTouch == true then
                                player.Character:BreakJoints()
                            end
                        end
                    end)
                elseif KillOnTouch == true then
             -- Door.CanCollide = true --Door.Transparency = CloseTrans
                player.Character:BreakJoints()
            end
        end
    end
end)
--[światła]


p1 = script.Parent.Parent.p1
legansio = false

sp1 = script.Parent.Parent.sp1
legansio = false

p2 = script.Parent.Parent.p2
legansio = false

sp2 = script.Parent.Parent.sp2
legansio = false

p3 = script.Parent.Parent.p3
legansio = false

sp3 = script.Parent.Parent.sp3
legansio = false

p4 = script.Parent.Parent.p4
legansio = false

sp4 = script.Parent.Parent.sp4
legansio = false

p5 = script.Parent.Parent.p5
legansio = false

sp5 = script.Parent.Parent.sp5
legansio = false

p6 = script.Parent.Parent.p6
legansio = false

sp6 = script.Parent.Parent.sp6
legansio = false

p7 = script.Parent.Parent.p7
legansio = false

sp7 = script.Parent.Parent.sp7
legansio = false


l1 = script.Parent.Parent.l1
legansio = false

sl1 = script.Parent.Parent.sl1
legansio = false

l2 = script.Parent.Parent.l2
legansio = false

sl2 = script.Parent.Parent.sl2
legansio = false


l3 = script.Parent.Parent.l3
legansio = false

sl3 = script.Parent.Parent.sl3
legansio = false


l4 = script.Parent.Parent.l4
legansio = false

sl4 = script.Parent.Parent.sl4
legansio = false

l5 = script.Parent.Parent.l5
legansio = false

sl5 = script.Parent.Parent.sl5
legansio = false


l6 = script.Parent.Parent.l6
legansio = false

sl6 = script.Parent.Parent.sl6
legansio = false


l7 = script.Parent.Parent.l7
legansio = false

sl7 = script.Parent.Parent.sl7
legansio = false
--edit the function below to return true when you want this response/prompt to be valid
--player is the player speaking to the dialogue, and dialogueFolder is the object containing the dialogue data


return function(player, dialogueFolder)
	local plrData = require(game.ReplicatedStorage.Source.Modules.Util):GetPlayerData(player)
	return plrData.Classes.Base.Scholar.Lumos.Value == true and plrData.Classes.Base.Scholar.XP.Value >= 100 and plrData.Classes.Base.Scholar.Ignis.Value ~= true
end
--[[ END OF SERVICES ]]



local LocalPlayer = PlayersService.LocalPlayer
while LocalPlayer == nil do
	PlayersService.ChildAdded:wait()
	LocalPlayer = PlayersService.LocalPlayer
end

local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")

local success, UserShouldLocalizeGameChatBubble = pcall(function()
	return UserSettings():IsUserFeatureEnabled("UserShouldLocalizeGameChatBubble")
end)
local UserShouldLocalizeGameChatBubble = success and UserShouldLocalizeGameChatBubble

local FFlagUserChatNewMessageLengthCheck2 do
	local success, result = pcall(function()
		return UserSettings():IsUserFeatureEnabled("UserChatNewMessageLengthCheck2")
	end)
	FFlagUserChatNewMessageLengthCheck2 = success and result
end

local function getMessageLength(message)
	return utf8.len(utf8.nfcnormalize(message))
end
-- Setting Up Buttons in Moblie


cas:BindAction("Sprint", function(_,inputState)
	
	if inputState == Enum.UserInputState.Begin then
		sprint("Begin")
	else
		sprint("Ended")
	end
	
end, true, Enum.KeyCode.LeftShift)

cas:SetTitle("Sprint","Sprint")

cas:SetPosition("Sprint",UDim2.new(1, -70, 0, 10))
--------------


local txt = script.Parent

txt.Changed:Connect(function()
    if txt.Parent:IsA("Frame") then
        wait(Time_Before_Disappearing)
        if Fade_Out_Enabled then
            repeat
                wait()
                txt.TextTransparency = txt.TextTransparency + Fade_Out_Smoothness
            until txt.TextTransparency >= 1
            wait(Time_Before_Disappearing)
            txt:Destroy()
        else
            txt:Destroy()
        end
    end
end)
--// Recoil Settings	


	gunrecoil = -0.6; -- How much the gun recoils backwards when not aiming
	camrecoil = 0.26; -- How much the camera flicks when not aiming
	AimGunRecoil = -0.3; -- How much the gun recoils backwards when aiming
	AimCamRecoil = 0.33; -- How much the camera flicks when aiming
	
	CamShake = 8; -- THIS IS NEW!!!! CONTROLS CAMERA SHAKE WHEN FIRING
	AimCamShake = 6; -- THIS IS ALSO NEW!!!!
	
	Kickback = 0.8; -- Upward gun rotation when not aiming
	AimKickback = 0.5; -- Upward gun rotation when aiming
-------- OMG HAX



r = game:service("RunService")


Tool = script.Parent

local equalizingForce = 250 / 1.2 -- amount of force required to levitate a mass
local gravity = .9999999999999999 -- things float at > 1

local ghostEffect = nil
local massCon1 = nil
local massCon2 = nil

function recursiveGetLift(node)
	local m = 0
	local c = node:GetChildren()
	for i=1,#c do
		if c[i].className == "Part" then
			if c[i].Name == "Handle" then
				m = m + (c[i]:GetMass() * equalizingForce * 1) -- hack that makes hats weightless, so different hats don't change your jump height
			else
				m = m + (c[i]:GetMass() * equalizingForce * gravity)
			end
		end
		m = m + recursiveGetLift(c[i])
	end
	return m
end


function onMassChanged(child, char)
	print("Mass changed:" .. child.Name .. "    " .. char.Name)
	if (ghostEffect ~= nil) then
		ghostEffect.force = Vector3.new(0, recursiveGetLift(char) ,0)
	end
end



function UpdateGhostState(isUnequipping)

	if isUnequipping == true then
		ghostEffect:Remove()
		ghostEffect = nil
		massCon1:disconnect()
		massCon2:disconnect()
	else
		if ghostEffect == nil then
			local char = Tool.Parent
			if char == nil then return end
			ghostEffect = Instance.new("BodyForce")
			ghostEffect.Name = "GravityCoilEffect"
			ghostEffect.force = Vector3.new(0, recursiveGetLift(char) ,0)
			ghostEffect.Parent = char.Head
			ghostChar = char
			massCon1 = char.ChildAdded:connect(function(child)  onMassChanged(child, char) end)
			massCon2 = char.ChildRemoved:connect(function(child)  onMassChanged(child, char) end)
		end
	end
	

end



function onEquipped()
	Tool.Handle.CoilSound:Play()
	UpdateGhostState(false)
end

function onUnequipped()
	UpdateGhostState(true)
end


script.Parent.Equipped:connect(onEquipped)
script.Parent.Unequipped:connect(onUnequipped)