Techy's Obby System - All your obby needs in one! [Includes Stage Selector]

I have a couple of questions and a little bit of criticism. First of all; the entire of obby system completely (script-wise) falls apart and breaks if I have another saving system on the leaderstat. Also, there are a lot of errors in the console. Last of all, when will the new version come out?

Due to extreme load of commissions, I couldn’t do much progress on revamped version. I’ll try my best to release it within 2 weeks or so. Or it may take more time. I’ll be revamping all the UIs, making the system work without any kind of problems - also support donation boards.

2 Likes

When players are buying stage skips, nothing happens… what do I do?

That’s probably because of the DataStore request error; I also encountered this error in my game. The system works fine without the Donation board and the admin system. However, when put together, the Skip stage button just does not function anymore; it proceeds to take the Robux but does not skip stage.

image

2 Likes

Yes, Hello. I couldnt reach you on discord wierdly. Im having problems with this. So, You spawn it at the 1 Spawn I would then go to the Fake 1 Spawn making sure im touching in (just in case) And then i’ll reset. then I spawn in the middle of my baseplate not at the spawn. What happenend?

Fake 1 is meant to be fake and doesn’t do anything. Maybe just keep it in lobby, and put the “1” in actual 1st stage.

Hey, I got it working. But There is some buttons that dont work, The Spectate Doesn’t spectate (Sometimes) and the Go to stage doesnt work for me? Fix?

Hey @0Techy, the script doesn’t support donation boards? It’s making my skip stage stop working.

1 Like

Hey @0Techy, my autosave doesn’t work even though the value is checked. Can you help?

Are you sure you enabled all settings from game settings? Read FAQ.

Yea, I turned in on. I tried turning on and off but still won’t work.

there is a UI bug to where when you press ‘go to lobby’ and then die. you get teleported back to the checkpoint you were previously at and the stage number UI doesn’t update. Rather saying 1 instead of ‘whatever number checkpoint was your highest’. Is there a script that I can use to fix that? because I know nothing about scripting to even do that.

video for proof of bug:

hey guys i was wondering if there was a script for my teleporter to tp to your current stage, dm me if you know

Hello, Techy. I am have problems with Techy’s Obby System its 3 Errors and this is scripts where it happend Main(script),Handler(local script).I am need help.First error:
Workspace.Techy’s Obby System.Configurations.Main:321: FireServer can only be called from the client
Second error:
ModuleScript is not a valid member of Folder “Workspace.Techy’s Obby System”
Third error:
Players.i_amnoob33637.PlayerGui.StageTransfer.Handler:40: attempt to index nil with ‘Connect’

Note:I am arleady have enable Studio Access to API Services in Security , Allow Http Requests , i am Move StageTransfer in StarterPlayer then Ungroup and i am Move Stages to workspace then Ungroup and also Techy’s Obby System(folder) put in workspace.
(If you need more scripts ask for more scripts or where models,folders put in).

Main(script):

local settings = require(script.Parent)
local ws = game:GetService("Workspace")
local sss = game:GetService("ServerScriptService")
local sg = game:GetService("StarterGui")
local rst = game:GetService("ReplicatedStorage")
local sp = game:GetService("StarterPlayer")

------
local event = Instance.new("RemoteEvent", rst)
event.Name = "ChangeStageByTechy"
------

local function SavingScript()
	local script = Instance.new('Script', game.ServerScriptService)
	script.Name = "SavingScript"

	local Players = game:GetService("Players")
	local DataStoreService = game:GetService("DataStoreService")
	local SaveDataStore = DataStoreService:GetDataStore(settings.datastoreName)

	local function SavePlayerData(player)
		if settings.dataAutosaves then

			local success,errormsg = pcall(function()

				local SaveData = {}

				for i,stats in pairs(player.leaderstats:GetChildren()) do

					SaveData[stats.Name] = stats.Value
				end	
				SaveDataStore:SetAsync(player.UserId,SaveData)
			end)

			if not success then 
				return errormsg
			end		
		end
	end	


	Players.PlayerAdded:Connect(function(player)

		local Stats = Instance.new("Folder")
		Stats.Name = "leaderstats"
		Stats.Parent = player

		local Stage = Instance.new("StringValue")
		Stage.Name = "Stage"
		Stage.Parent = Stats
		Stage.Value = 1

		local Data = SaveDataStore:GetAsync(player.UserId)

		if Data then 
			print(Data.Stage)

			for i,stats in pairs(Stats:GetChildren()) do

				stats.Value = Data[stats.Name]		
			end	
		elseif not settings.dataAutosaves then
			print("Autosave is Disabled.")

			player.leaderstats.Stage.Value = 1
		end



		player.CharacterAdded:Connect(function(character)

			local Humanoid = character:WaitForChild("Humanoid")
			local Torso = character:WaitForChild("HumanoidRootPart")

			wait()

			if Torso and Humanoid then
				if Stage.Value ~= 0 then

					local StagePart = workspace.Stages:FindFirstChild(Stage.Value)
					character:MoveTo(StagePart.Position)				
				end	
			end	
		end)		
	end)


	Players.PlayerRemoving:Connect(function(player)

		local errormsg = SavePlayerData(player)

		if errormsg then	
			warn(errormsg)		
		end	
	end)

	game:BindToClose(function()
		for i,player in pairs(Players:GetPlayers()) do	

			local errormsg = SavePlayerData(player)
			if errormsg then
				warn(errormsg)
			end			
		end
		wait(2)	
	end)
end
--------

local function StageScript()
	local script = Instance.new('Script', game.ServerScriptService)
	script.Name = "StageScript"

	local Stages = workspace:WaitForChild("Stages")

	for i,Stage in pairs(Stages:GetChildren()) do

		Stage.Touched:Connect(function(touch)

			local humanoid

			if touch.Parent:FindFirstChild("Humanoid") then

				humanoid = touch.Parent.Humanoid
			end

			if touch.Parent and touch.Parent.Parent:FindFirstChild("Humanoid") then

				humanoid = touch.Parent.Parent.Humanoid
			end

			if humanoid then

				local player = game.Players:GetPlayerFromCharacter(humanoid.Parent)

				local PlayerStage = player.leaderstats.Stage.Value

				if tonumber(Stage.Name) == PlayerStage + 1 then

					player.leaderstats.Stage.Value = player.leaderstats.Stage.Value + 1

				elseif tonumber(Stage.Name) > PlayerStage + 1 then

					humanoid.Health = 0
				end
			end
		end)
	end
end

---------------
local function StageTransfer()
	-- This script was fully made by Techyfied
	-- This script was open-sourced
	-- For Tutorial or more info, visit https://devforum.roblox.com/t/785271

	local script = Instance.new('Script', game.ServerScriptService)
	script.Name = "StageTransfer"

	game:GetService("ReplicatedStorage").ChangeStageByTechy.OnServerEvent:Connect(function(player, direction, target)
		local char = game.Workspace:FindFirstChild(player.Name)

		local function teleport()
			local cp = game.Workspace.Stages:FindFirstChild(tostring(player.TeleportedStage.Value))
			local cpp = cp.Position

			char:MoveTo(cpp)
		end


		if direction == "up" then
			--
			player.TeleportedStage.Value = player.TeleportedStage.Value + 1

			if tonumber(player.TeleportedStage.Value) > tonumber(player.leaderstats.Stage.Value) then
				player.TeleportedStage.Value = 1
			end

			teleport()
			--
		elseif direction == "down" then
			player.TeleportedStage.Value = player.TeleportedStage.Value - 1

			if tonumber(player.TeleportedStage.Value) < 1 then
				player.TeleportedStage.Value = player.leaderstats.Stage.Value
			end

			teleport()

		elseif direction == "up2" then
			player.TeleportedStage.Value = player.TeleportedStage.Value + 10

			if tonumber(player.TeleportedStage.Value) > tonumber(player.leaderstats.Stage.Value) then
				player.TeleportedStage.Value = 1
			end

			teleport()
		elseif direction == "down2" then
			player.TeleportedStage.Value = player.TeleportedStage.Value - 10

			if tonumber(player.TeleportedStage.Value) < 1 then
				player.TeleportedStage.Value = player.leaderstats.Stage.Value
			end

			teleport()

		elseif direction == "lobby" then
			player.TeleportedStage.Value = 1		
			teleport()

		elseif direction == "lc" then
			player.TeleportedStage.Value = player.leaderstats.Stage.Value		
			teleport()
		elseif direction == "set" then
			player.TeleportedStage.Value = player.leaderstats.Stage.Value		
			teleport()
		elseif direction == "goto" then
			player.TeleportedStage.Value = target
			teleport()
		end

		if direction == "joined" then
			if settings.dataAutosaves then
				player.TeleportedStage.Value = player.leaderstats.Stage.Value
				teleport()
				print("Moved ".. player.Name.. " to their last stage." )
			end
		elseif direction == "respawned" then
			teleport()
		elseif direction == "respawned2" then
			player.TeleportedStage.Value = player.leaderstats.Stage.Value
		elseif direction == "Resetted" then
			player.leaderstats.Stage.Value = 1
			player.TeleportedStage.Value = 1
			wait(0.1)
			teleport()
		end
	end)

	local Players = game:GetService("Players")

	Players.PlayerAdded:Connect(function(player)
		local tStage = Instance.new("StringValue")
		tStage.Name = "TeleportedStage"
		tStage.Parent = player
		wait(0.5)
		tStage.Value = player.leaderstats.Stage.Value
	end)

	local function onCharacterAdded(character)
		wait(0.1)
		print("CharacterAdded")
		local plr = Players:FindFirstChild(character.Name)
		local tar = game.Workspace.Stages:FindFirstChild(plr.TeleportedStage.Value)
		local tarp = tar.Position

		if tarp then
			wait(0.5)
			character:MoveTo(tarp)
		end
	end

	local function onPlayerAdded(player)
		player.CharacterAdded:Connect(onCharacterAdded)
	end
end


local TextLabel = Instance.new("TextLabel")
TextLabel.Parent = game.StarterGui.StageTransfer
TextLabel.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
TextLabel.BackgroundTransparency = 1.000
TextLabel.Position = UDim2.new(0.00635323999, 0, 0.962151408, 0)
TextLabel.Size = UDim2.new(0.902160108, 0, 0.0378486067, 0)
TextLabel.Font = Enum.Font.FredokaOne
TextLabel.Text = "This game uses <font color=\"#2d3436\">	Techy's Obby System®</font>"
TextLabel.TextColor3 = Color3.fromRGB(99, 110, 114)
TextLabel.RichText = true
TextLabel.TextSize = 12.000
TextLabel.TextStrokeTransparency = 0.100
TextLabel.TextXAlignment = Enum.TextXAlignment.Left

------
local function OnRespawn()
	local script = Instance.new("LocalScript", sp.StarterCharacterScripts)
	script.Name = "OnRespawn"

	local rps = game:GetService("ReplicatedStorage")

	rps.ChangeStageByTechy:FireServer("respawned")
end

local MarketplaceService = game:GetService("MarketplaceService")
local productId = settings.skipStageProductID

MarketplaceService.ProcessReceipt = function(receiptInfo)
	local players = game.Players:GetPlayers()
	local done = 0

	for i=1,#players do
		if players[i].userId == receiptInfo.PlayerId then
			if receiptInfo.ProductId == productId and done == 0 then
				done = 1
				players[i].leaderstats.Stage.Value = players[i].leaderstats.Stage.Value + 1
				players[i].TeleportedStage.Value = players[i].leaderstats.Stage.Value
				players[i].Character:MoveTo(game.Workspace.Stages:FindFirstChild(players[i].TeleportedStage.Value).Position)
				done = 0
			end
		end
	end
	return Enum.ProductPurchaseDecision.PurchaseGranted	
end

if settings.skipStageProductID == 0 then
	game.StarterGui:FindFirstChild("StageTransfer").SkipStage:Destroy()
end
----
coroutine.wrap(SavingScript)()
coroutine.wrap(StageScript)()
coroutine.wrap(StageTransfer)()
coroutine.wrap(OnRespawn)()

Configurations(module script):

--[[

  _____       _        _       ___  _    _           ___         _             
 |_   _|__ __| |_ _  _( )___  / _ \| |__| |__ _  _  / __|_  _ __| |_ ___ _ __  
   | |/ -_) _| ' \ || |/(_-< | (_) | '_ \ '_ \ || | \__ \ || (_-<  _/ -_) '  \ 
   |_|\___\__|_||_\_, | /__/  \___/|_.__/_.__/\_, | |___/\_, /__/\__\___|_|_|_|
                  |__/                        |__/       |__/                  
                  
                         ⚠️ SCROLL DOWN FOR CONFIGURATION ⚠️
                           
This is a open-sourced obby system by Techyfied. Feel free to use it. I would really appreciate if you
add this to your description,
"This game uses Techy's Obby System."

This script connects to all the scripts of this game. It's mainly for configuration. You can see
a description of each options on the same line.

Configure below.

TO-DO: Put "Move To StarterGui" in StarterGui and ungroup. Put "Move To Workspace" in Workspace
       and ungroup. Keep the model in Workspace. Delete  "DeleteMe" if you want. And configure below.
       
FAQ: https://devforum.roblox.com/t/785271/52
INFO: https://devforum.roblox.com/t/785271   

⚠️ TO RESET DATA, SIMPLY CHANGE datastoreName HERE!  Plus this game HAS AUTOSAVE. set 
                    dataAutosaves to true below to turn it on.⚠️
     
]]

local Configuration = {
	
	-- Obby Settings --
	skipStageProductID = 1091229735, -- Replace the number with your skip stage id. If you don't want a skip stage, set the number to 0.
	datastoreName = "MyDatastore_3", -- Put the datastore name. It can be anything. Change it to reset data.
	
	dataAutosaves = true, -- If true, player's stage data will autosave and they will spawn on the last stage when they leave and rejoin.
	deathEffectDisabled = true, -- If true, it will disable health bar, and red screen when a character is damaged.
	mobileShiftlockEnabled = true, -- If true, mobile players will have a togglable shiftlock on their screen.
	-------------------
	
	-- GUI Customization --
	guiCustomized = false, -- If you're editing the variables below, make sure to make it true.
	
	buttonBackgroundColor = Color3.fromRGB(255, 255, 255), -- Background color of the buttons.
	buttonTextColor = Color3.fromRGB(0, 0, 0), -- Text color of the texts on buttons.
	buttonTextFont = Enum.Font.SourceSans, -- Font of the texts on the buttons.
	buttonCornerRadius = UDim.new(0, 8), -- Corner radius of every buttons. 8 is the perfect and set by default.
	
	stageNumberColor = Color3.fromRGB(255, 255, 255), -- Color of the number on the GUI that shows what stage you're currently on.
	stageNumberFont = Enum.Font.FredokaOne,
	
	spectateFramePrimaryColor = Color3.fromRGB(255, 255, 255),
	spectateFrameSecondaryColor = Color3.fromRGB(255, 255, 255),
	spectateFrameTextColor = Color3.fromRGB(0, 0, 0)
	-----------------------
	
}

return Configuration

Handler(local script):

local LocalPlayer = game.Players.LocalPlayer

while wait() do
	if LocalPlayer.leaderstats.Stage ~= nil then
		break
	end
	if LocalPlayer.TeleportedStage ~= nil then
		break
	end
end

local replicatedStorage = game:GetService("ReplicatedStorage")

replicatedStorage.ChangeStageByTechy:FireServer("joined")

script.Parent.p.MouseButton1Click:Connect(function()
	replicatedStorage.ChangeStageByTechy:FireServer("down")
end)

script.Parent.n.MouseButton1Click:Connect(function()
	replicatedStorage.ChangeStageByTechy:FireServer("up")
end)

script.Parent.p2.MouseButton1Click:Connect(function()
	replicatedStorage.ChangeStageByTechy:FireServer("down2")
end)

script.Parent.n2.MouseButton1Click:Connect(function()
	replicatedStorage.ChangeStageByTechy:FireServer("up2")
end)

script.Parent.GoToLobby.MouseButton1Click:Connect(function()
	replicatedStorage.ChangeStageByTechy:FireServer("lobby")
end)

script.Parent.LastCheckpoint.MouseButton1Click:Connect(function()
	replicatedStorage.ChangeStageByTechy:FireServer("lc")
end)

LocalPlayer.TeleportedStage.Value.Changed:Connect(function()
	script.Parent.CurrentStage.Text = LocalPlayer.TeleportedStage.Value
end)
1 Like