Code itself works fine, well, as far as i am aware of.
I just want someone to check if there is anything i can improve on and what i could add to make it fail-proof.
local PhysicsService = game:GetService("PhysicsService")
PhysicsService:RegisterCollisionGroup("Character")
PhysicsService:RegisterCollisionGroup("OwnerStage")
PhysicsService:CollisionGroupSetCollidable("Character", "OwnerStage", true)
local serverScriptService = game:GetService("ServerScriptService")
local replicatedStorage = game:GetService("ReplicatedStorage")
local players = game:GetService("Players")
local DataService = require(serverScriptService.Services.DataService)
local Manager = require(serverScriptService.Services.DataService.Data)
local Plots = workspace.Obby.Platforms
local Debounce = false
local function setCharacterCollisionGroup(descendant)
if descendant:IsA("BasePart") and descendant.Parent:IsA("Character") then
descendant.CollisionGroup = "Character"
end
end
-- Gets a replica of the players profile
local function playerReplica(player, plot)
DataService:GetReplica(player):andThen(function(playerDataReplica)
local playerStage = playerDataReplica.Data.Stage
local currentStage = replicatedStorage.obbyStages.DCO:FindFirstChild(playerStage)
if currentStage then
local clonedStage = currentStage:Clone()
clonedStage.Name = "ClonedStage"
clonedStage:PivotTo(plot.Platform:FindFirstChild("StartPart").CFrame)
clonedStage.Parent = plot.Platform.Stage
end
end)
end
-- Finds the smallest available plot
local function findSmallestPlot()
local smallestPlot = nil
local smallestPlotNumber = math.huge
for _, plot in ipairs(Plots:GetChildren()) do
if plot:GetAttribute("Taken") then continue end
local plotNumber = tonumber(plot.Name)
if plotNumber and plotNumber < smallestPlotNumber then
smallestPlot = plot
smallestPlotNumber = plotNumber
end
end
return smallestPlot
end
-- Assigns a plot to a player and spawns their stage
local function assignPlotToPlayer(player, plot)
plot:SetAttribute("Taken", true)
plot:SetAttribute("Owner", player.UserId)
playerReplica(player, plot)
end
-- Spawns a player on their assigned plot and sets up collision groups
local function spawnPlayerOnPlot(player, plot)
player.CharacterAdded:Connect(function(character)
character:PivotTo(plot.Platform.StartPosition.CFrame * CFrame.new(0, 3, 0))
for _, descendant in character:GetDescendants() do
setCharacterCollisionGroup(descendant)
end
character.DescendantAdded:Connect(setCharacterCollisionGroup)
end)
end
-- Removes a player from their plot and cleans up
local function removePlayerFromPlot(player)
for _, plot in Plots:GetChildren() do
if plot:GetAttribute("Owner") == player.UserId then
plot:SetAttribute("Taken", nil)
plot:SetAttribute("Owner", nil)
for _, child in plot.Platform.Stage:GetChildren() do
if child.Name == "ClonedStage" then
child:Destroy()
break
end
end
print("Plot has been removed from " .. player.Name .. "!") -- On release verwijderen
end
end
end
local function stageChanged(player, plot)
for _, child in plot.Platform.Stage:GetChildren() do
if child.Name == "ClonedStage" then
child:Destroy()
break
end
end
playerReplica(player, plot)
end
local function placePlayerBack(player, plot)
player.Character:PivotTo(plot.Platform.StartPosition.CFrame * CFrame.new(0, 3, 0))
end
local function handleStageObject(player, plot)
local stageFolder = plot:WaitForChild("Platform").Stage
local currentConnection
stageFolder.ChildAdded:Connect(function(instance)
print(instance.Name .. " has been identified")
if instance.Name == "ClonedStage" then
local endPosition = instance:FindFirstChild("EndPosition")
if endPosition then
if currentConnection then
currentConnection:Disconnect()
end
currentConnection = endPosition.Touched:Connect(function(hit)
local hitPlayer = players:GetPlayerFromCharacter(hit.Parent)
if not hitPlayer then return end
if plot:GetAttribute("Owner") == hitPlayer.UserId then
if Debounce then return end
Debounce = true
local profile = Manager.Profiles[player]
if not profile then return end
local leaderstatStage = player:WaitForChild("leaderstats").Stage
profile.Data.Stage += 1
leaderstatStage.Value = profile.Data.Stage
placePlayerBack(player, plot)
stageChanged(player, plot)
task.wait(0.5)
Debounce = false
end
end)
end
end
end)
end
-- Main logic
players.PlayerAdded:Connect(function(player)
local plot = findSmallestPlot()
if plot then
assignPlotToPlayer(player, plot)
spawnPlayerOnPlot(player, plot)
handleStageObject(player, plot)
end
player.CharacterRemoving:Connect(function(Character)
task.defer(Character.Destroy, Character)
end)
end)
players.PlayerRemoving:Connect(function(player)
removePlayerFromPlot(player)
task.defer(player.Destroy, player)
end)