Cannot give data to multiple players

there is 1 ServerScript in the game, which is the one I posted in the beginning.
image

Add another script and just put a print(“This script is running”)

that works ofc. you understand that the serverscript is working right?

Then whats wrong with your giving data to multiple player script. When a player is added, that plr becomes the player that was added

Yes… but as I said the LocalScripts trigger on both players for some reason.

Hey there, I would be glad to help, but it appears that the issue you are having does not originate from the code snippet you have provided, but rather the part of the game that modifies these values.

You mention that the players can play on behalf of the player that joined first?
Could you show us the code that does this?

1 Like

Show your local scripts FULLY

This is the first type. I duplicated and edited it (yes I know that the variables should be x,y,z so I can edit the duplicates faster/easier)

grass = script.Parent.Parent:WaitForChild("vals").Grass

local soul = script.Parent.Parent:WaitForChild("leaderstats").Soul

local dirtBtn = game.Workspace.dirtButton

local soulGui = game.Players.LocalPlayer.PlayerGui:WaitForChild("currency").currencyHolder.Soul.amount

local dirt = script.Parent.Parent:WaitForChild("vals").Dirt

local dirtGui = game.Players.LocalPlayer.PlayerGui:WaitForChild("currency").currencyHolder.Dirt.amount

local holder = dirtBtn.GUI.text

local holder2 = dirtBtn.GUI2.text

local req1 = script.Parent.Parent:WaitForChild("reqs").req1

local giv1 = script.Parent.Parent:WaitForChild("givs").giv1

local sfx = game.SoundService.buttonSound

req1.Value = 5

giv1.Value = 1 * (grass.Value+1) 

holder.Text = "Cost: "..req1.Value.." Soul"
holder2.Text = "Gives: "..giv1.Value.." Dirt"

local ready = true

dirtBtn.Touched:Connect(function()
	
	if soul.Value >= req1.Value then
		
	sfx:Play()
	soul.Value -= req1.Value
	giv1.Value = 1 * (grass.Value+1)
	dirt.Value += giv1.Value
	
	req1.Value = 5 + (dirt.Value * 2)
	
		if ready == true then
		
			ready = false

				ready = true
				wait(0.3)
			
		end
	end
end)

This is the second type

local x = script.Parent.Parent:WaitForChild("givs").giv1

local abbreviations = {
	"K", -- 4 digits
	"M", -- 7 digits
	"B", -- 10 digits
	"T", -- 13 digits
	"QD", -- 16 digits
	"QT", -- 19 digits
	"SXT", -- 22 digits
	"SEPT", -- 25 digits
	"OCT", -- 28 digits
	"NON", -- 31 digits
	"DEA", -- 34 digits
	"DEB", -- 37 digits
	"DEC", -- 40 digits
}

local function Abbreviate(x, decimals)
	
	local x = script.Parent.Parent:WaitForChild("givs").giv1
	
	if decimals == nil then decimals = 0 end
	local visible = nil
	local suffix = nil
	if x.Value < 1000 then
		visible = x.Value * math.pow(10, decimals)
		suffix = ""
	else
		local digits = math.floor(math.log10(x.Value)) + 1
		local index = math.min(#abbreviations, math.floor((digits - 1) / 3))
		visible = x.Value / math.pow(10, index * 3 - decimals)
		suffix = abbreviations[index] .. "+"
	end
	local front = visible / math.pow(10, decimals)
	local back = visible % math.pow(10, decimals)

	if decimals > 0 then
		return string.format("%i.%0." .. tostring(decimals) .. "i%s", front, back, suffix)
	else
		return string.format("%i%s", front, suffix)
	end
end

x.Changed:Connect(function()
	local holder = game.Workspace.dirtButton.GUI2.text
	
	if x.Value > 1000 then
		holder.Text = "Gives: "..Abbreviate(69420, 1).." Dirt"
		
	else
		holder.Text = "Gives: "..x.Value.." Dirt"
	end

end)

The third, fourth and fifth script types seems to work (music and colour changes locally)

local soul = script.Parent.Parent:WaitForChild("leaderstats").Soul
local dirt = script.Parent.Parent:WaitForChild("vals").Dirt
local req1 = script.Parent.Parent:WaitForChild("reqs").req1
local dirtBtn = game.Workspace.dirtButton
local holder = dirtBtn.GUI.text

soul.Changed:Connect(function()

	if soul.Value >= req1.Value then
		
		dirtBtn.Color = Color3.fromRGB(255, 134, 21)
		dirtBtn.Transparency = 0.3
		holder.TextColor3 = Color3.fromRGB(38, 255, 0)
	else
		holder.TextColor3 = Color3.fromRGB(255, 0, 0)
		dirtBtn.Color = Color3.fromRGB(106, 57, 9)
		dirtBtn.Transparency = 0
	end
end)	
local onGui = script.Parent.Parent.PlayerGui:WaitForChild("sound").musicHolder.on
local offGui = script.Parent.Parent.PlayerGui:WaitForChild("sound").musicHolder.off
local hitbox = script.Parent.Parent.PlayerGui:WaitForChild("sound").musicHolder.TextButton
local song1 = game.SoundService.song1
local song2 = game.SoundService.song2
local song3 = game.SoundService.song3
local song4 = game.SoundService.song4


hitbox.Activated:Connect(function()

	if onGui.Visible == true then
		onGui.Visible = false
		offGui.Visible = true
		song1.Volume = 0
		song2.Volume = 0
		song3.Volume = 0
		song4.Volume = 0
		
	else
		offGui.Visible = false
		onGui.Visible = true
		song1.Volume = 0.55
		song2.Volume = 0.4
		song3.Volume = 0.5
		song4.Volume = 0.5

	end
end)
local song1 = game.SoundService.song1
local song2 = game.SoundService.song2
local song3 = game.SoundService.song3
local song4 = game.SoundService.song4

while true do
	song1:Play()
	wait(301.583)
	song2:Play()
	wait(143.666)
	song3:Play()
	wait(30.377)
	song4:Play()
	wait(165.041)
end```

Alright, I seem to understand what the issue is. Since these are all local scripts, they run once individually on all clients, however, on your event connections, such as dirtBtn.Touched:Connect(function() in the first script, you don’t check to make sure that the person who touched the part is the local player, this means that each player’s button is pressed, whenever anyone steps on the button, regardless of who it was.

This isn’t really a hard fix, but I strongly recommend you rework this entire system. When you change variables on the client like this, not only does it not replicate across the server, so other players cannot see the change that are made to your progress, but it may also pose a security risk later in development, as exploiters will be able to cheat through the entire game.

What you can do instead, is create the variables on the server like you do in the original script your provided in this thread, then also on the server, connect the events as you already are.
The thing about events is that they can pass variables, the .Touched event that you are using also passes variables. This specific event passes the part that has touched whatever you bind the event to, in this case the button, so if a player steps on the button, you can expect the passed variables to be the player’s leg. This means that you can do something like this:

local sfx = game.SoundService.buttonSound
local dirtBtn = game.Workspace.dirtButton
dirtBtn.Touched:Connect(function(Part)
    local Player = game.Players:GetPlayerFromCharacter(Part.Parent) -- Here you find the player object from the character, as you know that any part of the player's character will be a direct child of the character model.
    if Player then
        -- Here you wanna check if the player actually exists before continuing
        -- This is incase a part that isn't a player touches the button
        
        -- You would then proceed to adjust all the variables you want here.
        -- Keep in mind that since this is on the server, you have to find the location of the values in here, so that you ensure you always find the values specific to the player that hit the button.
        -- Since you have the player object, this can be done by doing something like:
        local soul = Player:WaitForChild("leaderstats").Soul
        local req1 = Player:WaitForChild("reqs").req1
        local giv1 = Player:WaitForChild("givs").giv1
        local dirt = Player:WaitForChild("vals").Dirt

        if soul.Value >= req1.Value then
            sfx:Play()
	    soul.Value -= req1.Value
	    giv1.Value = 1 * (grass.Value+1)
	    dirt.Value += giv1.Value

            req1.Value = 5 + (dirt.Value * 2)

            if ready == true then
                ready = false
                task.wait(0.3) -- I recommend you in general use task.wait() instead of wait() as it is more accurate
                ready = true
            end
        end
    end
end)

It looks to me like you are taking on a project a bit too hard for your current level. I recommend you experiment around a bit more, since it looks like you have a bit to go, although you are not far off from being able to make a great game.

I hope this helps.

1 Like

This whole game is for practice (so I don’t mind if it’s unplayble in the end).
But the things I wanted to do were: Datastore, RemoteEvents, functioning general system.
Unfortunately reworking the system seems like a lot of work (for me), but on the other hand if I went ahead and made RemoteEvents / datastore in the current system, it probably won’t be the same methods as if I did it on the reworked (and better) system.

What do you think: Should I rework it, or do RemoteEvents/Datastore instantly?

If you do RemoteEvents and Datastore now, there are 2 possible outcomes.

  1. The game doesn’t work
  2. The game is so exploitable that exploiters have full control over their own stats

Neither of these are desirable, so I strongly recommend you rework it now.

Thank you for the help. Should I message you about potential problems with creating the new system? Considering you would have better context.

Feel free to message me if you need help, although I can’t promise I will answer immediately.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.