Jailbreak train platform system?

No need for an apology I appreciate the response and I’ll take your advice.

I’ve seen tyridge77’s system in use and it works well albeit its some extra steps

2 Likes

Hey, sorry for necroposting but I feel like this is the best time to do this.

So I’ve got this issue with your script because I have a plane model that has multiple parts. However, the plane model doesn’t have one static part (RaftPart) so it’s teleporting me around like crazy.

Shown here:
https://i.gyazo.com/f607b2e739cb9bb0065ff3fd591dcb1f.mp4

Here’s my code (It’s modified to suit my needs):

local Players = game:GetService("Players")
local player = game.Players.LocalPlayer
local RunService = game:GetService('RunService')

local LastTrainCFrame

local Function
local Function2


Function = RunService.Heartbeat:Connect(function()
	local RootPart = player.Character.HumanoidRootPart
	local Ignore = player.Character
	local ray = Ray.new(RootPart.CFrame.p, Vector3.new(0,-500,0))
	local Hit, Position, Normal, Material = workspace:FindPartOnRay(ray,Ignore)
	if Hit and Hit:IsDescendantOf(workspace.Planes) then
		local Train = Hit
		if not LastTrainCFrame then
			LastTrainCFrame = Train.CFrame
		end
		local TrainCF = Train.CFrame 
		local Rel = TrainCF * LastTrainCFrame:inverse()
		LastTrainCFrame = Train.CFrame
		RootPart.CFrame = Rel * RootPart.CFrame
	else
		LastTrainCFrame = nil
	end
	
	if not Function2 then
		Function2 = player.Character.Humanoid.Died:Connect(function()
			Function:Disconnect()
			Function2:Disconnect()
		end)
	end
end)

Any idea on how to fix this? (btw it’s late for me so i will be going to bed after posting this)

3 Likes

To switch static parts you have to convert Rel from the local space of the old Train part into the new Train part.

4 Likes

Hi, I just tried to apply this with a ship, with a whitelist for the ray.

If I don’t move on the ship while the ship is moving, I start sliding towards the front. Any way to fix this?

Here is my code:

local Players = game:GetService("Players")
local player = game.Players.LocalPlayer
local RunService = game:GetService('RunService')

local LastTrainCFrame

local Function
local Function2


Function = RunService.Heartbeat:Connect(function()
	
	local RootPart = player.Character.Torso
	
	local ray = Ray.new(RootPart.CFrame.p,Vector3.new(0,-50,0))
	
	local WhiteList = {workspace.Orion["Cruiser Kappa"]["Cruiser Kappa"].Ship.MovingPart}
	
	local Hit, Position, Normal, Material = workspace:FindPartOnRayWithWhitelist(ray,WhiteList)
	
	if Hit and Hit.Name == "MovingPart" then
		
		local Train = Hit
		if LastTrainCFrame == nil then
			LastTrainCFrame = Train.CFrame
		end
		local TrainCF = Train.CFrame 
		
		local Rel = TrainCF * LastTrainCFrame:inverse()
		
		LastTrainCFrame = Train.CFrame
		
		RootPart.CFrame = Rel * RootPart.CFrame
		
	else
		LastTrainCFrame = nil
		
	end
	
	Function2 = player.Character.Humanoid.Died:Connect(function()
		Function:Disconnect()
		Function2:Disconnect()
	end)
	
end)
1 Like

For easier solution I would recommend using BodyMovers so Roblox will take care of physics.

A topic from back in May deals with the same behavior, except the issue wasn’t the same.

1 Like

This topic is really old and I remember when it first was posted.
But this is a ModuleScript that I used for making a Roundabout that you would see at a Playground

It should give you a general idea of how to make it.

Only works on LocalScripts.

local module = {}

local Collection = game:GetService("CollectionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer
local Map = workspace:WaitForChild("Map")
local Infrastructure = Map:WaitForChild("Infrastructure")
local Folder = Infrastructure:WaitForChild("Roundabouts")
local Camera = workspace.CurrentCamera
local Ignore = {}

local function ExitRoundabout(Roundabout)
	warn("Exited")
end

local function EnterRoundabout(Roundabout)
	warn("Entered")
end

local CFrameSpinners = {}
local Roundabouts = {}

function module.Init()
	local DownVector = Vector3.new(0, -1, 0)
	local newRay = Ray.new
	local FindPartOnRay = workspace.FindPartOnRay
	local FindPartOnRayWithIgnoreList = workspace.FindPartOnRayWithIgnoreList
	local function fpor(start, direction, distance, IgnoreModel, WhitelistFolder)
		local attempt = 0
		local hit, pos, origin, material = nil, start, -direction, nil
		while distance > 0 and attempt < 10 do
			local ray = newRay(start, direction * distance)
			hit, pos, origin, material = FindPartOnRay(workspace, ray, IgnoreModel, false, true)
			local d = (start - pos).Magnitude
			if hit and (hit:IsDescendantOf(WhitelistFolder) or hit.CanCollide) then
				return hit, pos, origin, material
			end
			start = pos
			distance = distance - d
			attempt = attempt + 1
		end
		return hit, pos, origin, material
	end
	local LastRoundabout
	local lt = tick()
	local function Heartbeat()
		local t = tick()
		local dt = t - lt
		lt = t
		local RoundaboutModel, Spinner, SpinnerCf, RootPart
		local Character = LocalPlayer.Character
		if Character then
			local Humanoid = Character:FindFirstChild("Humanoid")
			if Humanoid then
				RootPart = Humanoid.RootPart
				if RootPart then
					RoundaboutModel = fpor(RootPart.Position, DownVector, 10, Character, Folder)
					if RoundaboutModel and not RoundaboutModel:IsDescendantOf(Folder) then
						RoundaboutModel = nil
					end
				end
			end
		end
		if not RoundaboutModel then
			if LastRoundabout then
				ExitRoundabout(LastRoundabout)--Exited LastRoundabout
			end
			LastRoundabout = nil
		end
		local ClosestDist, ClosestRoundabout = 500, nil
		for i,Roundabout in pairs(Roundabouts) do
			local TSpinner = Roundabout:FindFirstChild("Spinner")
			if RootPart then
				if TSpinner then
					local Dist = (RootPart.Position - TSpinner.Position).Magnitude
					if ClosestDist >= Dist then
						ClosestDist = Dist
						ClosestRoundabout = Roundabout
					end
					if CFrameSpinners[TSpinner] == nil then
						CFrameSpinners[TSpinner] = TSpinner.CFrame
					end
				end
			end
			if RoundaboutModel and RoundaboutModel:IsDescendantOf(Roundabout) then
				Spinner = TSpinner
				SpinnerCf = CFrameSpinners[TSpinner]
				if not LastRoundabout then
					EnterRoundabout(Roundabout)--Entered
				elseif LastRoundabout ~= Roundabout then
					ExitRoundabout(LastRoundabout)--Exited LastRoundabout
					EnterRoundabout(Roundabout)--Entered Roundabout
				end
				LastRoundabout = Roundabout
			else
				CFrameSpinners[TSpinner] = TSpinner.CFrame
			end
		end
		if Spinner then
			local NewCF = Spinner.CFrame
			if CFrameSpinners[Spinner] == nil then
				CFrameSpinners[Spinner] = NewCF
			end
			SpinnerCf = CFrameSpinners[Spinner]
			local Relative = NewCF * SpinnerCf:Inverse()
			RootPart.CFrame = Relative * RootPart.CFrame
			local CamRel = Camera.CFrame:ToObjectSpace(Camera.Focus)
			Camera.CFrame = Camera.CFrame * CamRel * (Relative - Relative.p) * CamRel:Inverse()
			CFrameSpinners[Spinner] = Spinner.CFrame
		end
	end
	RunService.Heartbeat:Connect(Heartbeat)
	local function RoundaboutAdded(Model)
		table.insert(Roundabouts,Model)
	end
	local function RoundaboutRemoved(Model)
		for index,value in pairs(Roundabouts) do
			if value == Model then
				table.remove(Roundabouts,index)
			end
		end
	end
	for _, Model in next, Collection:GetTagged("Roundabout") do
		RoundaboutAdded(Model)
	end
	Collection:GetInstanceAddedSignal("Roundabout"):Connect(RoundaboutAdded)
	Collection:GetInstanceRemovedSignal("Roundabout"):Connect(RoundaboutRemoved)
end

return module

It doesn’t work even when my vehicle floor is named “RaftTop”

Are you sure you are setting it up correctly? Worked fine for me a few weeks ago and I doubt it changed.

Yeah I put the script in StarterPlayer > StarterPlayerScripts and I used the script as a local script. It worked once but the second time I tried didn’t work

You have to make sure that your cframing your vehicle. And make sure to whitelist only that raft top part for the ray, so it wont get blocked by others. lol okkkk

Basically what it is. when you jump you go back according to roblox physics.But how they fixed this is the speed the player goes back.means if he jump he goes back by 15 studs.They added a script which pushes the player 15 studs front exactly when the player jumps.so -15 + 15 = 0
so they player stays at the spot and dosen’t move back.

2 Likes

Hey, so I am very new to scripting and I was wondering if you put the script in the part that you stand on?

No. You put it in starter character scripts.

1 Like

Did you ever figure this out?
Having similar issues

just wondering, How do you do that?

I’m having similar issues as well. Did he ever respond to you?

Nope, I’m still searching and experimenting as well

If you find anything can you let me know please? I’m browsing through so many posts and trying different things and I’ve yet to find anything :confused:

Hey, I took a look at the thread. I looked at what worked best for me. However there were some bugs with the LastPartCFrame not being reset, so I fixed it. Here is the code optimized to work with the new Raycasting method too.

Update: it can also check for HumanoidStateTypes

--[[
SETUP
1. Make a LocalScript
2. Put it inside of StarterCharacterScripts
3. Make a folder in workspace and call it "MovingObjects"
4. Put all your moving objects in that folder
5. OPTIONAL, the CheckStates variable will set the CFrame if the character's HumanoidState is not Jumping and not swimming 
]]
--BrahGames 07-27-2021 rewritten https://devforum.roblox.com/t/jailbreak-train-platform-system/236339
local Players = game:GetService("Players")
local player = game.Players.LocalPlayer
local RunService = game:GetService('RunService')

local CheckStates = true
local LastPartCFrame
local LastPart
local Function
local Function2
function CFrameLogic(Raycast, CFramePart)
	--------------------------------------------------------------- MOVE PLAYER TO NEW POSITON FROM OLD POSITION
	if Raycast.Instance ~= LastPart then
		LastPart = Raycast.Instance
		LastPartCFrame = nil
	end
	local Train = Raycast.Instance
	if LastPartCFrame == nil then -- If no LastTrainCFrame exists, make one!
		LastPartCFrame = Train.CFrame -- This is updated later.
	end
	local TrainCF = Train.CFrame
	local Rel = TrainCF * LastPartCFrame:inverse()
	LastPartCFrame = Train.CFrame -- Updated here.
	CFramePart.CFrame = Rel * CFramePart.CFrame -- Set the player's CFrame
	--print("set")
end
Function = RunService.Heartbeat:Connect(function()
	--------------------------------------------------------------- CHECK PLATFORM BELOW
	-- Build a "RaycastParams" object
	local MovingObjects = workspace.MovingObjects --Make a folder and put all moving objects into it and call the folder "MovingObjects"
	local HumanoidRootPart = player.Character.HumanoidRootPart
	local humanoid = player.Character.Humanoid
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
	raycastParams.FilterDescendantsInstances = {MovingObjects}
	raycastParams.IgnoreWater = true

	-- Cast the ray
	local Hit = workspace:Raycast(HumanoidRootPart.CFrame.p, Vector3.new(0,-50,0), raycastParams) --Casts a ray facing down
	--------------------------------------------------------------------------------------------
	if Hit and Hit.Instance:IsDescendantOf(MovingObjects) then -- Check if the ray hits and if it hits an object inside of MovingObjects
		if CheckStates then -- check if the character is jumping
			if humanoid:GetState() == Enum.HumanoidStateType.RunningNoPhysics or humanoid:GetState() == Enum.HumanoidStateType.Running or humanoid:GetState() == Enum.HumanoidStateType.Landed or humanoid:GetState() == Enum.HumanoidStateType.PlatformStanding or humanoid:GetState() == Enum.HumanoidStateType.Seated or humanoid:GetState() == Enum.HumanoidStateType.GettingUp or humanoid:GetState() == Enum.HumanoidStateType.None or humanoid:GetState() == Enum.HumanoidStateType.Physics or humanoid:GetState() == Enum.HumanoidStateType.Ragdoll or humanoid:GetState() == Enum.HumanoidStateType.Dead then
				CFrameLogic(Hit, HumanoidRootPart)
			else
				LastPartCFrame = nil -- Clear the value when the player gets off.
			end
		else
			CFrameLogic(Hit, HumanoidRootPart)
		end
	else
		LastPartCFrame = nil -- Clear the value when the player gets off.
	end
end)
Function2 = player.Character.Humanoid.Died:Connect(function()
	Function:Disconnect() -- Stop memory leaks
	Function2:Disconnect() -- Stop memory leaks
end)
23 Likes