Jetpack breaking on teleport?

Greetings developers, recently I made a custom jetpack for my game and I have a problem with it. If you are flying and anyone uses something to teleport you [for example teleport command, or cuffs] your rotation breaks. Resetting the camera didn’t work and turning autorotate again didn’t work.

image

Local script

local HoldingZ = false
local HoldingX = false
local tapX = false

local fuel = 1

local flyevent = game.ReplicatedStorage.Remotes.Fly
local Stopfly = game.ReplicatedStorage.Remotes.Stopfly

local BodyVelocity = script:WaitForChild("BodyVelocity"):Clone()
BodyVelocity.Name = "jetpackVEL"
local v3 = script.BodyGyro:Clone()
v3.Name = "jetpackGYR"
local Character = script.Parent
local Humanoid = Character:FindFirstChild("Humanoid") or Character:WaitForChild("Humanoid")
BodyVelocity.Parent = Character
v3.Parent = Character
local Core = Character:WaitForChild("HumanoidRootPart")
local Mouse = game.Players.LocalPlayer:GetMouse()

local Camera = game.Workspace.CurrentCamera
local Flymoving = script.Flymoving
local TweenService = game:GetService("TweenService")
local UIS = game:GetService("UserInputService")
local Flying = false
local stopAnims = {"walk","run","idle","fall","jump"}
local debounce = false
local UI = game.Players.LocalPlayer.PlayerGui.FuelGui
local plr = game.Players.LocalPlayer
plr.PlayerGui:WaitForChild("FuelGui").BarBG.Visible = true


function cardinalConvert(dir)
	local angle = math.atan2(dir.X, -dir.Z)
	local quarterTurn = math.pi / 2
	angle = -math.round(angle / quarterTurn) * quarterTurn

	local newX = -math.sin(angle)
	local newZ = -math.cos(angle)
	if math.abs(newX) <= 1e-10 then newX = 0 end
	if math.abs(newZ) <= 1e-10 then newZ = 0 end
	return Vector3.new(newX, 0, newZ)
end

function disableAnims()
	wait()
	if Flying == false then return end
	for _,anim in pairs(Humanoid:GetPlayingAnimationTracks()) do
		if table.find(stopAnims, anim.Name) then
			anim:Stop()
		end
	end
end

function checkAnims()
	wait()
	if Flying == false then return end
	for _,anim in pairs(Humanoid:GetPlayingAnimationTracks()) do
		if table.find(stopAnims, anim.Name) then
			return anim
		end
	end
end

function Zed()
	HoldingZ = true
	if fuel >= 0.2 and plr:WaitForChild("CuffedBy").Value == "NA" and Humanoid.PlatformStand == false and debounce == false then
		if Flying == false then
			local target = Vector3.new(0, Core.CFrame.Position.Y + 25, 0)
			BodyVelocity.Velocity = BodyVelocity.Velocity:Lerp(target, 0.15)
			Flying = true
			flyevent:FireServer()
			if Character:FindFirstChild("HumanoidRootPart") then
				Humanoid:SetStateEnabled(Enum.HumanoidStateType.Running, false)
				Humanoid:SetStateEnabled(Enum.HumanoidStateType.Climbing, false)
				Humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
				Humanoid:SetStateEnabled(Enum.HumanoidStateType.Freefall, false)
				Humanoid:ChangeState(6)
				BodyVelocity.Parent = Character.HumanoidRootPart
				v3.Parent = Character.HumanoidRootPart
			end
			repeat disableAnims() until checkAnims() == nil
		end
	end
end

function MainX()
	Flying = false
	Stopfly:FireServer()
	Flymoving.Value = false
	Humanoid:SetStateEnabled(Enum.HumanoidStateType.Running, true)
	Humanoid:SetStateEnabled(Enum.HumanoidStateType.Climbing, true)
	Humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, true)
	Humanoid:SetStateEnabled(Enum.HumanoidStateType.Freefall, true)
	Humanoid:ChangeState(8)
	BodyVelocity.Parent = Character
	v3.Parent = Character
end

Humanoid.Died:Connect(function()
	MainX()
	BodyVelocity:Destroy()
	v3:Destroy()
	script:Destroy()
end)

game:GetService("RunService").RenderStepped:Connect(function()
	if script.Parent == Character then
		if Flying == true then
			Humanoid:ChangeState(6)
			
			if Humanoid.MoveDirection == Vector3.new(0, 0, 0) then
				Flymoving.Value = false
			else
				Flymoving.Value = true
			end
			
			v3.CFrame = CFrame.new(Core.CFrame.p, Core.CFrame.p + Vector3.new(Camera.CFrame.LookVector.X,0,Camera.CFrame.LookVector.Z))
			local dir = cardinalConvert(Humanoid.MoveDirection)
			if dir == Vector3.new(-1, 0, 0) or Vector3.new(1, 0, 0) then
				BodyVelocity.Velocity = BodyVelocity.Velocity:Lerp(Humanoid.MoveDirection * 30, 0.3)
			elseif dir == Vector3.new(0, 0, 1) or Vector3.new(0, 0, -1) then
				BodyVelocity.Velocity = BodyVelocity.Velocity:Lerp(Humanoid.MoveDirection * 25, 0.3)
			end
			
		else
			v3.CFrame = CFrame.new(0,0,0)
		end
		
		if Humanoid.PlatformStand == true then
			MainX()
		end
		
		if plr:WaitForChild("CuffedBy").Value ~= "NA" then
			MainX()
		end
	end
end)

UIS.InputBegan:Connect(function(key, gameProcessed)
	if gameProcessed then return end
	if key.KeyCode == Enum.KeyCode.Z then
		Zed()
	elseif key.KeyCode == Enum.KeyCode.X then
		HoldingX = true
		if tapX then
			MainX()
		else
			tapX = true
			wait(0.3)
			tapX = false
		end
	end
end)

if UIS.TouchEnabled == true then
	local ui = plr.PlayerGui:FindFirstChild("MobileButtons")
	if ui then
		for i,v in pairs(ui:WaitForChild("Jetpack"):GetChildren()) do
			v.Visible = true
		end
		local Up = ui.Jetpack.Up
		local Down = ui.Jetpack.Down
		
		Up.MouseButton1Down:Connect(function()
			Zed()
		end)
		
		Up.MouseButton1Up:Connect(function()
			HoldingZ = false
		end)
		
		Down.MouseButton1Down:Connect(function()
			HoldingX = true
			if tapX then
				MainX()
			else
				tapX = true
				wait(0.3)
				tapX = false
			end
		end)

		Down.MouseButton1Up:Connect(function()
			HoldingX = false
		end)
	end
end

UIS.InputEnded:Connect(function(key, gameProcessed)
	if gameProcessed then return end
	if key.KeyCode == Enum.KeyCode.Z then
		HoldingZ = false
		BodyVelocity.Velocity = Vector3.new(BodyVelocity.Velocity.X, 0, BodyVelocity.Velocity.Z)
	elseif key.KeyCode == Enum.KeyCode.X then
		HoldingX = false
		BodyVelocity.Velocity = Vector3.new(BodyVelocity.Velocity.X, 0, BodyVelocity.Velocity.Z)
	end
end)

function castRay(x, z)
	local Origin = Vector3.new(x, 80, z)
	local stop = Vector3.new(x, -100, z)
	local dir = (stop - Origin)
	local rayPar = RaycastParams.new()
	rayPar.FilterType = Enum.RaycastFilterType.Whitelist
	rayPar.IgnoreWater = true
	rayPar.FilterDescendantsInstances = {Character}
	local result = workspace:Raycast(Origin, dir, rayPar)
	return result
end

while true do
	wait()
	local result = castRay(Core.CFrame.X, Core.CFrame.Z)
	if HoldingZ and Flying then
		if result ~= nil then
			BodyVelocity.Velocity += Vector3.new(0,15,0)
		end
	end
	
	if result == nil then
		BodyVelocity.Velocity -= Vector3.new(0,5,0)
	end
	
	if HoldingX and Flying then
		if Humanoid.FloorMaterial == Enum.Material.Air then
			BodyVelocity.Velocity -= Vector3.new(0,15,0)
		else
			MainX()
		end
	end
	
	if Flying then
		fuel = fuel - 0.001
		local size = game.Players.LocalPlayer.PlayerGui.FuelGui.BarBG.FuelBar
		size:TweenSize(UDim2.new(fuel, 0, 1, 0), "InOut", "Linear", 0.03)

		if fuel <= 0.001 then
			MainX()
		end
	end

	if not Flying and fuel < 1 then
		fuel = fuel + 0.001
		local size = game.Players.LocalPlayer.PlayerGui.FuelGui.BarBG.FuelBar
		size:TweenSize(UDim2.new(fuel, 0, 1, 0), "InOut", "Linear", 0.03)
	end
end

Character server script:

local RS = game:GetService("RunService")
local FlyValue = script.Parent:WaitForChild("Flying")

--
local runService = game:GetService("RunService")

local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local m6d = nil
local originalM6dC0 = nil
local axis = 0.2

local lowerTorso = character.LowerTorso
m6d = lowerTorso.Root

originalM6dC0 = m6d.C0

function checkAxis(dir)
	if dir > axis then
		return "bigger"
	elseif dir < -axis then
		return "smaller"
	end
end

runService.Heartbeat:Connect(function(dt)
	if FlyValue.Value == true then
		local direction = humanoidRootPart.CFrame:VectorToObjectSpace(humanoid.MoveDirection)
		
		
		local x = direction.X
		
		
		local state = checkAxis(x)
		if state == "bigger" then
			x = axis
		elseif state == "smaller" then
			x = -axis
		end
		
		
		
		local z = direction.Z
		
		
		
		local state2 = checkAxis(z)
		if state2 == "bigger" then
			z = axis
		elseif state2 == "smaller" then
			z = -axis
		end
		
		
		local angles = nil
		angles = {z, 0, -x}
		
		m6d.C0 = m6d.C0:Lerp(originalM6dC0*CFrame.Angles(unpack(angles)), 0.1)
	else
		m6d.C0 = m6d.C0:Lerp(originalM6dC0, 0.1)
	end
end)

ServerScriptService server script:

local flyevent = game.ReplicatedStorage.Remotes.Fly
local stopfly = game.ReplicatedStorage.Remotes.Stopfly

flyevent.OnServerEvent:Connect(function(plr)
		local Char = plr.Character
		local Jetpack = Char.Jetpack
		local Jetpackscriptlocal = Char.JetpackScript
		local flyValue = Char.Flying

		local fire1 = Jetpack.Handle.Fire1.Particle
		local fire2 = Jetpack.Handle.Fire2.Particle
		local sound = Jetpack.Handle.Sound

		fire1.Enabled = true
		fire2.Enabled = true
		flyValue.Value = true
		sound:Play()
end)

stopfly.OnServerEvent:Connect(function(plr)
	local Char = plr.Character
	local Jetpack = Char.Jetpack
	local Jetpackscriptlocal = Char.JetpackScript
	local flyValue = Char.Flying

	local fire1 = Jetpack.Handle.Fire1.Particle
	local fire2 = Jetpack.Handle.Fire2.Particle
	local sound = Jetpack.Handle.Sound

	fire1.Enabled = false
	fire2.Enabled = false
	flyValue.Value = false
	sound:Stop()
end)

I just realized I set the name for velocity and gyro on the client side but that shouldn’t be a problem.

If your rotation breaks when a player gets teleported, the reason might be that you are persistently keeping the original rotation of the jetpack when it was first initialized, and then continuously referring to this state during flight. When the player gets teleported, the rotation context changes abruptly, which might cause unexpected behavior.

You could potentially solve this problem by always updating the base rotation (or the equivalent rotation variable in your script) every time the player gets teleported or cuffs are used.

Moreover, it is important to note that your script makes references to the HumanoidRootPart, which might not be there after teleportation. It is a good practice to make sure the references to important objects are up-to-date after the teleportation.

If you’re using a teleportation function provided by Roblox (like TeleportService), you might be able to use the Teleport event in order to reset the rotation and other relevant parameters.

Lastly, don’t forget to handle all edge cases that might arise when you teleport a player. This includes ensuring the player is not flying at the time of teleportation, and if they are, stop flying properly before teleporting.

If you could provide more details about how you are implementing the teleportation and how exactly the rotation “breaks”, I could give you more specific advice.

The advice given above is generic because without seeing the full context of your game or the teleportation/cuffing code it is hard to give a perfect answer. Hope it helps! :slight_smile:

Maybe use jetpack main storage as accesory, soo jetpack accesory will be the tool that you use in your game

You need to disable BodyVelocity and BodyGyro on the jetpack but since they’re made on client you can’t do anything really besides firing client.

Well thanks for your time, this really helped!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.