Looking for feedback on bubble save script

I’ve made a small script that essentially checks if a players character Y position is lower than -50 and it will transport them back to the last safe position. I did this just to mess around with Bézier Curves and I’d really appreciate if I could get some tips with things like formatting my code and making it more efficient! I wont really be using this for anything so I thought it was perfect for asking for critiques.

local character = script.Parent

local plr = game.Players:GetPlayerFromCharacter(character)

local bubble = script.Bubble

local weld = script.Bubble.HRPWeld

local BubbleInflateHeight = -50

local BubbleHeightOffset = 80

local LastSafePos

bubble.Parent = script.Parent.HumanoidRootPart
weld.Part1 = script.Parent.HumanoidRootPart

-- Quadratic Beizer to calculate curve of the path for the bubble

local function FindPointOnBeizer(t,p0,p1,p2)
	return (1-t)^2*p0+2*(1-t)*t*p1+t^2*p2
end

-- Checks for HumanoidRootPart before running every 0.3 seconds to avoid
-- errors when the player dies

while wait(0.3) and character:FindFirstChild("HumanoidRootPart") do

	local RayParams = RaycastParams.new()

	-- Filter out Parts inside the character as the bubble would end up dropping you in the void

	local charparts = {}
	for i,v in pairs(character:GetDescendants()) do
		if v:IsA("Part") or v:IsA("UnionOperation") or v:IsA("MeshPart") then
			table.insert(charparts,#charparts+1,v)
		end
	end
	RayParams.FilterDescendantsInstances = charparts
	RayParams.FilterType = Enum.RaycastFilterType.Blacklist


	local ResultRaycast = workspace:Raycast(character.HumanoidRootPart.Position,-(character.HumanoidRootPart.CFrame.UpVector*10),RayParams)

	if ResultRaycast and ResultRaycast.Instance.CanCollide == true then
		LastSafePos = ResultRaycast.Position + Vector3.new(0,8,0)
	end

	if character.HumanoidRootPart.Position.Y <= BubbleInflateHeight 
		and LastSafePos ~= nil and character.Humanoid.Health ~= 0 then

		character.HumanoidRootPart.Anchored = true
		bubble.Transparency = 0.6
		bubble.Bubble.Transparency = 0
		bubble.Inflate:Play()
		bubble.Moving:Play()

		local Anims = script.Anims:GetChildren()
		local Anim = Anims[math.random(1,#Anims)]
		local Animation = character.Humanoid:LoadAnimation(Anim)
		Animation:Play()

		local StartPoint = character.HumanoidRootPart.Position

		local Midpoint = Vector3.new(
			character.HumanoidRootPart.Position.X,
			LastSafePos.Y+BubbleHeightOffset,
			character.HumanoidRootPart.Position.Z)

		for count = 0,1.01,0.01 do
			wait(0.01)
			if character.HumanoidRootPart then

				local pos = FindPointOnBeizer(count,StartPoint,Midpoint,LastSafePos)

				--Uses CFrame rather than Position due to problems replicating from client to server

				local LookAt = character.HumanoidRootPart.CFrame * CFrame.new(Vector3.new(0,0,-2))

				character.HumanoidRootPart.CFrame = CFrame.lookAt(pos,LookAt.Position)
				character.HumanoidRootPart.Orientation = Vector3.new(0,character.HumanoidRootPart.Orientation.Y,0)
			end
		end

		if character:FindFirstChild("HumanoidRootPart") and character.HumanoidRootPart:FindFirstChild("Bubble") 
			and bubble:FindFirstChild("Bubble") then

			character.HumanoidRootPart.Position = LastSafePos
			Animation:Stop()
			bubble.Moving:Stop()
			bubble.Pop:Play()
			bubble.Transparency = 1
			bubble.Bubble.Transparency = 1

			-- Set all character part's velocity to 0 to prevent flinging/ragdoll

			for i,v in pairs(character:GetDescendants()) do
				if v:IsA("Part") or v:IsA("UnionOperation") or v:IsA("MeshPart") then
					v.Velocity = Vector3.new(0,0,0)
				end
			end
			character.HumanoidRootPart.Anchored = false
		else
			plr:LoadCharacter()
		end
	end
end

Example of what this code does:

2 Likes

It is very awesome, I would just add a landing animation and that’s it.

1 Like