Hello, I am working on a simple game that requires a datastore to save only one value–problem is I can’t even get that to work.
This is the entirety of my save/leaderboard script, you can ignore the autosave stuff.
local save = game:GetService("DataStoreService"):GetDataStore("Points")
local event = game.ReplicatedStorage.SaveData --remote event
local players = game.Players:GetPlayers()
---------
-- Save will be in the format: Player_USERID , points
---------
function saveInt(player, score)
if player.UserId > 0 then
save:SetAsync("Player_" .. tostring(player.UserID), score)
end
end
function loadInt(player, stat)
if player.UserId > 0 then
stat.Value = save:GetAsync("Player_" .. tostring(player.UserId))
end
end
function playerAdded(plr)
local stats = Instance.new('IntValue', plr)
stats.Name = "leaderstats"
local Points = Instance.new("IntValue", stats)
Points.Name = "Points"
local tPoints = Instance.new("IntValue", stats)
tPoints.Name = "Total Points"
--plr:WaitForDataReady()
Points = 0
loadInt(plr, tPoints, "Total Points")
end
function playerRemoving(name)
local plr = players[name]
local stats = plr:FindFirstChild("leaderstats")
if stats ~= nil then
saveInt(plr, stats.tPoints.Value)
end
end
game.Players.PlayerAdded:Connect(playerAdded)
game.Players.PlayerRemoving:Connect(playerRemoving)
--event.OnServerEvent:Connect(playerRemoving) --reuse player removing for autosave
Also, is there a better way to insert code rather than going line by line adding spaces?
The only possible problem I can see is that I didn’t use all the pcall network stuff (which I have yet to learn).
Your issue is there. PlayerRemoving doesn’t return a string, it returns a reference to the player who left. Make sure to change that to this:
function playerRemoving(plr)
local stats = plr:FindFirstChild("leaderstats")
if stats ~= nil then
saveInt(plr, stats.tPoints.Value)
end
end
Just change that and you should be good.
Another problematic thing is you’re doing this:
When you do :GetPlayers(), it doesn’t update when a new player is added, it returns a static array of the players at the time of that function being called.
You have to do :GetPlayers() every time a new player joins to get an updating array. Don’t do that, because there’s no use for doing that in this case
I feel like I should also mention that if you were to use :GetPlayers(), you couldn’t do local plr = players[name] because they keys are numerical, not strings. Keys are the part you use brackets / . to get
-- :GetPlayers()
local players = {[1] = game.Players.Player1, [2] = game.Players.Player2} -- You can't do players[player.Name], the keys are numbers.
-- game.Players
local players = game.Players -- returns an instance
-- instance keys are organized by the name of the object and it's properties
-- look at the explorer to see how it's organized
I’m pretty sure that the explorer sorts them for the sake of convenience but the engine actually recognises GetChildren arrays based on the order of which they were added in. The same goes for GetPlayers, GetTeams, so on; organisation isn’t implicit. You’d have to do a test to confirm this.