Stage value changing for all players

For some reason, this checkpoint doesn’t work, it adds the stat for all players saying all players in the game are on Stage 1. Why is this?

ServerScript inside of ServerScriptService

game.ReplicatedStorage.Stage.OnServerEvent:Connect(function(player)
	player.leaderstats.Stage.Value = player.leaderstats.Stage.Value + 1
	print(player)
end)

ServerScript with RunContext set to Client inside of the CheckPoint:

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local debounce = true
local checkpoint = script.Parent

function onTouched(hit)
	if debounce == true then
		debounce = false
		if hit and hit.Parent and hit.Parent:FindFirstChildOfClass("Humanoid") then
			local checkpointData = ServerStorage:FindFirstChild("CheckpointData")
			if not checkpointData then
				checkpointData = Instance.new("Folder")
				checkpointData.Name = "CheckpointData"
				checkpointData.Parent = ServerStorage
			end
			script.Parent.BrickColor = BrickColor.new("Bright green")
			script.Sound:Play()
			local player = game.Players:GetPlayerFromCharacter(hit.Parent)
			game.ReplicatedStorage.Stage:FireServer(player)
			local userIdString = tostring(player.UserId)
			local checkpointValue = checkpointData:FindFirstChild(userIdString)
			if not checkpointValue then
				checkpointValue = Instance.new("ObjectValue")
				checkpointValue.Name = userIdString
				checkpointValue.Parent = checkpointData

				player.CharacterAdded:connect(function(character)
					wait()
					local storedCheckpoint = ServerStorage.CheckpointData[userIdString].Value
					character:MoveTo(storedCheckpoint.Position + Vector3.new(math.random(-4, 4), 4, math.random(-4, 4)))
				end)
			end

			checkpointValue.Value = checkpoint
		end
	end
end

checkpoint.Touched:Connect(onTouched)
3 Likes

Not sure if this gonna help but when you use FireServer() no need to pass the player as a parameter:

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local debounce = true
local checkpoint = script.Parent

function onTouched(hit)
	if debounce == true then
		debounce = false
		if hit and hit.Parent and hit.Parent:FindFirstChildOfClass("Humanoid") then
			local checkpointData = ServerStorage:FindFirstChild("CheckpointData")
			if not checkpointData then
				checkpointData = Instance.new("Folder")
				checkpointData.Name = "CheckpointData"
				checkpointData.Parent = ServerStorage
			end
			script.Parent.BrickColor = BrickColor.new("Bright green")
			script.Sound:Play()
			local player = game.Players:GetPlayerFromCharacter(hit.Parent)
			game.ReplicatedStorage.Stage:FireServer()
			local userIdString = tostring(player.UserId)
			local checkpointValue = checkpointData:FindFirstChild(userIdString)
			if not checkpointValue then
				checkpointValue = Instance.new("ObjectValue")
				checkpointValue.Name = userIdString
				checkpointValue.Parent = checkpointData

				player.CharacterAdded:connect(function(character)
					wait()
					local storedCheckpoint = ServerStorage.CheckpointData[userIdString].Value
					character:MoveTo(storedCheckpoint.Position + Vector3.new(math.random(-4, 4), 4, math.random(-4, 4)))
				end)
			end

			checkpointValue.Value = checkpoint
		end
	end
end

checkpoint.Touched:Connect(onTouched)
2 Likes

Isn’t :FireServer() unusable in a server script?

2 Likes

But then how do I ensure that the only player that gets the stage stat added is the one that touched the checkpoint?

2 Likes

You can handle everything on the server.

using game.Players:GetPlayerFromCharacter(hit.Parent) you can get the player on server and add the stats there.

2 Likes

So in the serverScript I can just say player.leaderstats.Stage.Value = player.leaderstats.Stage.Value + 1, and it will already be defined?

2 Likes

yes, just make sure you have this:

local player = game.Players:GetPlayerFromCharacter(hit.Parent)
2 Likes
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
game.ReplicatedStorage.Stage.OnServerEvent:Connect(function()
	player.leaderstats.Stage.Value = player.leaderstats.Stage.Value + 1
	print(player)
end)

ServerScriptService.Midget:22: attempt to index nil with 'Parent'

1 Like

I meant to do that in one server script, put those lines inside the OnTouched function.

1 Like
game.ReplicatedStorage.Stage.OnServerEvent:Connect(function()
	player.leaderstats.Stage.Value = player.leaderstats.Stage.Value + 1
	print(player)
end)

ServerScriptService.Midget:24: attempt to index nil with 'leaderstats'
Keep in mind the RunContext of this script is set to Client

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local debounce = true
local checkpoint = script.Parent

function onTouched(hit)
	local player = game.Players:GetPlayerFromCharacter(hit.Parent)
	if debounce == true then
		debounce = false
		if hit and hit.Parent and hit.Parent:FindFirstChildOfClass("Humanoid") then
			local checkpointData = ServerStorage:FindFirstChild("CheckpointData")
			if not checkpointData then
				checkpointData = Instance.new("Folder")
				checkpointData.Name = "CheckpointData"
				checkpointData.Parent = ServerStorage
			end
			script.Parent.BrickColor = BrickColor.new("Bright green")
			script.Sound:Play()
			local player = game.Players:GetPlayerFromCharacter(hit.Parent)
			game.ReplicatedStorage.Stage:FireServer(player)
			local userIdString = tostring(player.UserId)
			local checkpointValue = checkpointData:FindFirstChild(userIdString)
			if not checkpointValue then
				checkpointValue = Instance.new("ObjectValue")
				checkpointValue.Name = userIdString
				checkpointValue.Parent = checkpointData

				player.CharacterAdded:connect(function(character)
					wait()
					local storedCheckpoint = ServerStorage.CheckpointData[userIdString].Value
					character:MoveTo(storedCheckpoint.Position + Vector3.new(math.random(-4, 4), 4, math.random(-4, 4)))
				end)
			end

			checkpointValue.Value = checkpoint
		end
	end
end

checkpoint.Touched:Connect(onTouched)
1 Like

try this:
Checkpoint Script (Client):

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local debounce = true
local checkpoint = script.Parent

function onTouched(hit)
    if debounce then
        debounce = false
        if hit and hit.Parent and hit.Parent:FindFirstChildOfClass("Humanoid") then
            local player = game.Players:GetPlayerFromCharacter(hit.Parent)

            if player then
                -- Update the checkpoint color and sound
                script.Parent.BrickColor = BrickColor.new("Bright green")
                script.Sound:Play()

                -- Fire the server event to update the player's stage
                game.ReplicatedStorage.Stage:FireServer()

                -- Handle checkpoint data storage
                local checkpointData = ServerStorage:FindFirstChild("CheckpointData")
                if not checkpointData then
                    checkpointData = Instance.new("Folder")
                    checkpointData.Name = "CheckpointData"
                    checkpointData.Parent = ServerStorage
                end

                local userIdString = tostring(player.UserId)
                local checkpointValue = checkpointData:FindFirstChild(userIdString)
                if not checkpointValue then
                    checkpointValue = Instance.new("ObjectValue")
                    checkpointValue.Name = userIdString
                    checkpointValue.Parent = checkpointData

                    player.CharacterAdded:Connect(function(character)
                        wait()
                        local storedCheckpoint = checkpointValue.Value
                        character:MoveTo(storedCheckpoint.Position + Vector3.new(math.random(-4, 4), 4, math.random(-4, 4)))
                    end)
                end

                -- Store the checkpoint
                checkpointValue.Value = checkpoint
            end
        end
        -- Reset debounce after a short delay
        wait(1)
        debounce = true
    end
end

checkpoint.Touched:Connect(onTouched)

Server Script (ServerScriptService):

game.ReplicatedStorage.Stage.OnServerEvent:Connect(function(player)
    -- Increment the player's stage only
    if player and player:FindFirstChild("leaderstats") and player.leaderstats:FindFirstChild("Stage") then
        player.leaderstats.Stage.Value = player.leaderstats.Stage.Value + 1
        print(player.Name .. " is now on Stage " .. player.leaderstats.Stage.Value)
    end
end)
1 Like

Try this. (Put inside a server script with RunContext to Legacy):

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local debounce = true
local checkpoint = script.Parent

function onTouched(hit)
	if debounce == true then
		debounce = false
		if hit and hit.Parent and hit.Parent:FindFirstChildOfClass("Humanoid") then
			local checkpointData = ServerStorage:FindFirstChild("CheckpointData")
			if not checkpointData then
				checkpointData = Instance.new("Folder")
				checkpointData.Name = "CheckpointData"
				checkpointData.Parent = ServerStorage
			end
			script.Parent.BrickColor = BrickColor.new("Bright green")
			script.Sound:Play()
			local player = game.Players:GetPlayerFromCharacter(hit.Parent)
			local userIdString = tostring(player.UserId)
			local checkpointValue = checkpointData:FindFirstChild(userIdString)
			if not checkpointValue then
				checkpointValue = Instance.new("ObjectValue")
				checkpointValue.Name = userIdString
				checkpointValue.Parent = checkpointData

				player.CharacterAdded:Connect(function(character)
					wait()
					local storedCheckpoint = ServerStorage.CheckpointData[userIdString].Value
					character:MoveTo(storedCheckpoint.Position + Vector3.new(math.random(-4, 4), 4, math.random(-4, 4)))
				end)
			end

			checkpointValue.Value = checkpoint
			player.leaderstats.Stage.Value = player.leaderstats.Stage.Value + 1
			print(player)
		end
	end
end

checkpoint.Touched:Connect(onTouched)
1 Like

It works but it still adds the stat to both players, same issue as the start

1 Like

It works fine now only adding for one player, but the reason the RunContext was set to Client was so the Checkpoint still remains white and able to be used by another player.

1 Like

Never mind, so if you found the solution mark any response as that so the topic can close.

1 Like

i’ve updated it:
ClientSide Script (Checkpoint Script):

local Players = game:GetService("Players")
local debounce = true
local checkpoint = script.Parent

function onTouched(hit)
    if debounce then
        debounce = false
        if hit and hit.Parent and hit.Parent:FindFirstChildOfClass("Humanoid") then
            local player = Players:GetPlayerFromCharacter(hit.Parent)
            
            if player then
                -- Fire the server event to update the player's stage (no need to pass the checkpoint)
                game.ReplicatedStorage.Stage:FireServer()
                
                -- Change the checkpoint color locally (only this player sees it)
                script.Parent.BrickColor = BrickColor.new("Bright green")
                
                -- Play the sound locally (only this player hears it)
                script.Sound:Play()
            end
        end
        -- Reset debounce after a short delay
        wait(1)
        debounce = true
    end
end

checkpoint.Touched:Connect(onTouched)

Server-Side Script (ServerScriptService):

game.ReplicatedStorage.Stage.OnServerEvent:Connect(function(player)
    -- Make sure the player has leaderstats and the Stage stat
    local leaderstats = player:FindFirstChild("leaderstats")
    local stage = leaderstats and leaderstats:FindFirstChild("Stage")

    if stage then
        -- Only increment the player's own Stage stat
        stage.Value = stage.Value + 1
        print(player.Name .. " is now on Stage " .. stage.Value)
    end
end)
2 Likes
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local checkpoint = script.Parent
local Debounces = {}

function onTouched(hit)
			script.Parent.BrickColor = BrickColor.new("Bright green")
			script.Sound:Play()
end

checkpoint.Touched:Connect(onTouched)

The RunContext of this script is set to Client but it still changes for everyone. What is the best way to change the BrickColor of the part to Green for ONLY the player who touched the checkpoint?

1 Like

Everything works now, except for the changing of the color of the block.

1 Like

Fire a Remote Event to Client and Do the changes there.

2 Likes

Where should I put the client so that it can access the workspace? StarterGUI?

1 Like