You can write your topic however you want, but you need to answer these questions:
The game is here:
In early development as you can tell. (As of its unfinished state please do not dislike this is to help understand the problem not get people to play it)
Edit:The problem is every on touch creates A value and every player can use it
Edit: I rewrote the first bit…
What do you want to achieve? I am making A datastore which saves cash but all the leaderstat values are not assaigned to A single player and newones are created evrytime the player joins.
You should only earn money on the grey block. However it is updating my cash value as well because you cannot distinguish them…
Datastore
local DSS = game:GetService("DataStoreService")
local cashData = DSS:GetDataStore("cashDataStore")
game.Players.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = Player
local Cash = Instance.new("IntValue")
Cash.Name = "Cash"
Cash.Parent = leaderstats
Cash.Value = cashData:GetAsync(Player.userId) or 0
game.Players.PlayerRemoving:connect(function(Player)
cashData:SetAsync(Player.userId, Cash.Value)
end)
while true do
wait(60)
pcall(function()
cashData:SetAsync(Player.userId, Cash.Value)
end)
end
end)
end)
game.Players.PlayerRemoving:Connect(function()
end)
and the block script is
local brick = script.Parent
function onTouched(hit)
for i,player in ipairs(game.Players:GetPlayers()) do
if player.Character then
local stat = player:FindFirstChild("leaderstats")
if stat then
player.leaderstats.Cash.Value = player.leaderstats.Cash.Value +1
end
end
end
end
brick.Touched:connect(onTouched)
I have tried using remove functions and using A useerid as A “key” but I did not get it to work. As well as thish, I do not know how to only create one value per person.
At first glance there are a few things you’ll want to consider, may or may not directly address the title:
You’re going to have a lot of these infinite loops per player, all executing in their own thread. Seeing what it does, you just need one per player. So it doesn’t need to be in the .CharacterAdded event (everytime an event is fired, a new thread is created to execute whatever code it has). This may also cause throttling since you’ll have a ton of requests going to datastores.
You’re going to have a lot of these per player as a player’s character respawns. It should just be in player added.
Due to the above, you don’t know which cash object you’re getting when indexing into leaderstats. Ideally you just want one, the one created when the player joins.
Check out the output tab in studio, you’ll get warnings (yellow-ish) there if you’re going past the data store limit.
I have made a debounce using the guide but their are no errors but it appears it does not work I have tried searching for humaniod the Value does not increase at all.
local pressed = false
–Store whether the button is pressed in a local variable
workspace.Button.Touched:Connect(function(hit)
if not pressed then
pressed = true
if hit.parent then
game.player.leaderstats.Cash.Value = game.player.leaderstats.Cash.Value+5
wait(5)
game.player.leaderstats.Cash.Value = game.player.leaderstats.Cash.Value+5
wait(5)
end
pressed=false
Everytime the character respawns/is added, you create a new IntValue which is parented to that character’s player’s leaderstats. So now you see as a player respawns they will have multiple IntValues named “Cash”. You can test this out yourself by looking into the explorer while testing.
So when you do player.leaderstats.Cash.Value... , out of the multiple Cash objects, one is chosen and you might not particularly know which one.
The problem is that a (random?) cash value is updated, and then saved by its thread running the while true save loop, but then another thread with that same code will run and overwrite the recently updated value.
I understand that but am not ware of how to give A userid to A cash value. Script is above
Currently the data saves to the userId but uses any Cash value of any player on the server. I need to figure out how to make the Client only accsess their value and no one elses I thought I could give each value the UserId of the player and make it search for that one but do not know how.
Would this work?
local Cash = Instance.new(“IntValue”)
Cash.Name = “Cash”…“player.userid”
Cash.Parent = leaderstats
Cash.Value = cashData:GetAsync(Player.userId) or 0
local DSS = game:GetService("DataStoreService")
local cashData = DSS:GetDataStore("cashDataStore")
-- Manage data for individual players whenever one joins the server
game.Players.PlayerAdded:Connect(function(Player)
-- Create leaderstats
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = Player
-- Create cash
local Cash = Instance.new("IntValue")
Cash.Name = "Cash"
Cash.Parent = leaderstats
Cash.Value = cashData:GetAsync(Player.UserId) or 0
-- Save when a player leaves
game.Players.PlayerRemoving:connect(function(Player)
cashData:SetAsync(Player.UserId, Cash.Value)
end)
-- Autosave (?)
while Player ~= nil do
wait(60)
pcall(function()
cashData:SetAsync(Player.UserId, Cash.Value) --You had userId, the property is UserId :)
end)
end
end)
And for your bottom script, try this. I added a little cooldown mechanic, so that players can’t get tons of money super fast–they have to wait for cooldownTime seconds before getting money again. The .Touched event can fire dozens of times per second per player, so this is a way of managing how frequently they can get money. Your script was also giving money to all players when anything touched the part; I fixed that so it should only give money to the player that touches it now.
local Players = game:GetService("Players")
local brick = script.Parent
local cooldownTime = 1 -- Set this to the interval in seconds between when players get cash
local onCooldown = {}
function onTouched(hit)
local Character = hit.Parent
if Players:FindFirstChild(Character.Name) ~= nil then
local Player = Players:FindFirstChild(Character.Name)
local UID = Player.UserId
local Stats = Player:WaitForChild("leaderstats")
-- Verify that the user isn't on cash cooldown
if not onCooldown[UID] then
-- Mark player for cooldown
onCooldown[UID] = (Player)
-- Add cash
Player.leaderstats.Cash.Value = Player.leaderstats.Cash.Value +1
-- Wait for cooldown to end, then remove player from cooldown
wait(cooldownTime)
onCooldown[UID] = nil
end
end
end
brick.Touched:connect(onTouched)
Let me know if these work!
EDIT: Also–unless I’m mistaken–Player.UserId is case-sensitive (just like all things), so using Player.userId won’t work.
So does this save directly to the players cash value instead of A random one?
Also player is an unknown global so I put game.player instead. I s that ok @ChefJustice
Edit:
Error:player is not A valid member of Datamodel
That’s fine–my bad for not noticing that! Yes, it should save directly to the player’s UserId.
Edit: what line is that error on?
Edit [2]: nvm; DataModel is the fancy word for game. Where are you getting the datamodel error?
In the money brick script:
game.player.leaderstats.Cash.Value = game.player.leaderstats.Cash.Value + 1
I tried pluralizing players because I read an article on how that fixed the error but it still gave the same output.
Without game it was an unknown global. Should I try defining it.