erm, I could see that, and yes the leaderstats are still included in players, it is created before the if statement.
if the PlayerAdded event is working half the time, i suggest reading this post:
It isnât working at all, I would try ChildAdded but Iâm not sure about that instance.
Well by the looks of it you might be asking for something before its even loaded, pcall (to check if there was success) could be used to detect if its got the data, though Iâm not a complete expert on pcall, it could be a sort of backup solution in case it fails.
hm, have you tried turning the PlayerAdded function into a local function?
local function playerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local MusclarCash = Instance.new("NumberValue")
MusclarCash.Parent = leaderstats
MusclarCash.Name = "MusclarCash"
local Strength = Instance.new("NumberValue")
Strength.Parent = leaderstats
Strength.Name = "Strength"
local Rebirths = Instance.new("NumberValue")
Rebirths.Parent = leaderstats
Rebirths.Name = "Rebirths"
local debounce = Instance.new("BoolValue")
debounce.Parent = player
debounce.Name = "Debounce"
if player.leaderstats.MusclarCash.Value >= 10000 then
game.Workspace.GymDoor.CanCollide = false
game.Workspace.GymDoor.Anchored = true
else
game.Workspace.GymDoor.CanCollide = true
end
local key = "user-"..player.UserId
local storedItems = DService:GetAsync(key)
if storedItems then
MusclarCash.Value = storedItems[1]
Strength.Value = storedItems[2]
Rebirths.Value = storedItems[3]
else
local items = {MusclarCash.Value, Strength.Value, Rebirths.Value}
DService:SetAsync(key, items)
end
end)
game.Players.PlayerAdded:Connect(function(player)
spawn(function() playerAdded(player) end) -- playerAdded is the local function and the parameter inside it is the player
end) -- spawn could possibly fix your issue
There are few errors in your latest script:
- You are checking if
MusclarCash
âs Value is greater than 10k before even loading player data from the DataStore, so it will be 0 by Default (I believe.) So what you should do instead is load the data first and then run your check.
I made the small change on this script here:
local DService = game:GetService("DataStoreService"):GetDataStore("Game")
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local MusclarCash = Instance.new("NumberValue")
MusclarCash.Parent = leaderstats
MusclarCash.Name = "MusclarCash"
local Strength = Instance.new("NumberValue")
Strength.Parent = leaderstats
Strength.Name = "Strength"
local Rebirths = Instance.new("NumberValue")
Rebirths.Parent = leaderstats
Rebirths.Name = "Rebirths"
local debounce = Instance.new("BoolValue")
debounce.Parent = player
debounce.Name = "Debounce"
local key = "user-"..player.UserId
local storedItems = DService:GetAsync(key)
if storedItems then
MusclarCash.Value = storedItems[1]
Strength.Value = storedItems[2]
Rebirths.Value = storedItems[3]
else
local items = {MusclarCash.Value, Strength.Value, Rebirths.Value}
DService:SetAsync(key, items)
end
--Moved this if statement down here:
if player.leaderstats.MusclarCash.Value >= 10000 then
game.Workspace.GymDoor.CanCollide = false
game.Workspace.GymDoor.Anchored = true
else
game.Workspace.GymDoor.CanCollide = true
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local items = {player.leaderstats.MusclarCash.Value, player.leaderstats.Strength.Value, player.leaderstats.Rebirths.Value}
local key = "user-"..player.UserId
DService:SetAsync(key, items)
end)
Mm. So what youâre encountering is a race condition. The code you put forth is running ahead of leaderstats being created which results in the error because leaderstats doesnât exist to that code yet: additionally, LocalScripts donât run in the workspace if you were hoping to locally disable collisions with your special door. Doing it from the server would enable the room for everyone if someone with sufficient cash joined.
When working with PlayerAdded, I always recommend storing it in a function which you later have listen to PlayerAdded as well as run for any players who were in the game before the script finished connecting to PlayerAdded. As for creating leaderstats, you should avoid parenting the folder until youâve created and parented the other stats values as well.
You can manage your door with a LocalScript in PlayerScripts which will change the collision based on the current cash and then remove the collision handler from the data loading script.
local Player = game:GetService("Players").LocalPlayer
-- We can assume MuscularCash exists when leaderstats does
local Leaderstats = Player:WaitForChild("leaderstats")
local MuscularCash = Leaderstats.MuscularCash
local GymDoor = workspace:WaitForChild("GymDoor")
local CASH_FOR_GYM = 10000
local function valueChanged(newValue)
GymDoor.CanCollide = (newValue >= CASH_FOR_GYM)
end
MuscularCash.Changed:Connect(valueChanged)
valueChanged(MuscularCash.Value)
And your server script requires a few changes as well, particularly in the realm not only of the way you handle your PlayerAdded function but also how youâre managing your DataStores as well. Always remember to use pcall when working with DataStores so you can account for service failures.
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local PlayerData = DataStoreService:GetDataStore("Game")
-- These should not be saved if encountered during saving
local SESSION_VALUES = {"Debounce"}
-- We don't want to overwrite and cause data loss if DataStoreService is down
local shouldNotSave = {}
-- Handy utility function to serialise player data for saving
local function folderToDictionary(folder)
local dictionary = {}
for _, stat in ipairs(folder:GetChildren()) do
if not table.find(SESSION_VALUES, stat.Name) then
if stat:IsA("Folder") then
dictionary[stat.Name] = folderToDictionary(stat)
else
dictionary[stat.Name] = stat.Value
end
end
end
return dictionary
end
local function playerAdded(player)
local playerKey = "user-" .. player.UserId
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
local muscularCash = Instance.new("IntValue")
muscularCash.Name = "MuscularCash"
muscularCash.Parent = leaderstats -- Never parent first!
local strength = Instance.new("IntValue")
strength.Name = "Strength"
strength.Parent = leaderstats
local rebirths = Instance.new("IntValue")
rebirths.Name = "Rebirths"
rebirths.Parent = leaderstats
local debounce = Instance.new("BoolValue")
debounce.Name = "Debounce"
debounce.Parent = player
-- No need to save data if the player has none, catch it in PlayerRemoving
local success, data = pcall(PlayerData.GetAsync, PlayerData, playerKey)
if success then
if data then
for key, value in pairs(data) do
local stat = leaderstats:FindFirstChild(key)
if stat then
stat.Value = value
end
end
end
else
shouldNotSave[player] = true
warn("Data could not be loaded for key " .. playerKey .. " - " .. data)
end
leaderstats.Parent = player
end
local function playerRemoving(player)
local playerKey = "user-" .. player.UserId
local leaderstats = player:FindFirstChild("leaderstats")
-- Done this way to account for failed loads and to make data
-- easier to browse: for example, via a plugin, or code.
if leaderstats and not shouldNotSave[player] then
local data = folderToDictionary(leaderstats)
local success, result = pcall(PlayerData.SetAsync, PlayerData, playerKey, data)
if not success then
warn("Failed to save for key " .. playerKey .. " - " .. result)
end
end
shouldNotSave[player] = nil
end
Players.PlayerAdded:Connect(playerAdded)
Players.PlayerRemoving:Connect(playerRemoving)
for _, player in ipairs(Players:GetPlayers()) do
playerAdded(player)
end
This is the exact problem!
It was printing I didnât have enough because my data didnât load!