BLOXBUILDS
Discord
Back
OBBY

Skip Stage Button

Paste into ServerScriptService as a Script. Replace PRODUCT_ID with your developer product. Touching a part named SkipStage opens the purchase, and a completed purchase moves the player forward one checkpoint.

-- Paste into ServerScriptService as a Script.
-- Create a developer product and paste its id into PRODUCT_ID.
-- Name the prompt part "SkipStage".
-- Keep only one ProcessReceipt handler in the whole game.

local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")

local PRODUCT_ID = 0

local function getStage(player: Player): IntValue
	local leaderstats = player:FindFirstChild("leaderstats")
	if not leaderstats then
		leaderstats = Instance.new("Folder")
		leaderstats.Name = "leaderstats"
		leaderstats.Parent = player
	end

	local stage = leaderstats:FindFirstChild("Stage")
	if not stage then
		stage = Instance.new("IntValue")
		stage.Name = "Stage"
		stage.Value = 0
		stage.Parent = leaderstats
	end

	return stage :: IntValue
end

local function findCheckpoint(stageNumber: number): BasePart?
	for _, inst in ipairs(workspace:GetDescendants()) do
		if inst:IsA("BasePart") and inst.Name == "Checkpoint" and inst:GetAttribute("Stage") == stageNumber then
			return inst
		end
	end
	return nil
end

local function skipStage(player: Player)
	local stage = getStage(player)
	stage.Value += 1

	local checkpoint = findCheckpoint(stage.Value)
	local character = player.Character
	local root = character and character:FindFirstChild("HumanoidRootPart")
	if checkpoint and root then
		root.CFrame = checkpoint.CFrame + Vector3.new(0, 4, 0)
	end
end

for _, inst in ipairs(workspace:GetDescendants()) do
	if inst:IsA("BasePart") and inst.Name == "SkipStage" then
		inst.Touched:Connect(function(hit)
			local player = Players:GetPlayerFromCharacter(hit.Parent)
			if not player or PRODUCT_ID == 0 then
				return
			end
			MarketplaceService:PromptProductPurchase(player, PRODUCT_ID)
		end)
	end
end

MarketplaceService.ProcessReceipt = function(receipt)
	if receipt.ProductId ~= PRODUCT_ID then
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end

	local player = Players:GetPlayerByUserId(receipt.PlayerId)
	if not player then
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end

	skipStage(player)
	return Enum.ProductPurchaseDecision.PurchaseGranted
end