I call it "StarterLeaderstats"

so there is for example, StarterPlayerScripts and more,

i
but this is how you make a folder, everything you put inside the folder, will appear on the leaderstats instead of putting every value you need inside a script.

first put a folder inside the serverstorgae called “StarterLeaderstats” (The name does not matter)

and then a script:

local File = game:GetService("ServerStorage"):WaitForChild("StarterLeaderstats")
local StatusValues = File:getChildren()


game.Players.PlayerAdded:Connect(function(plr)
	local leaderstats = Instance.new("Folder",plr)
	leaderstats.Name = "leaderstats"
for _, StatVal in pairs(StatusValues) do
	local Copied = StatVal:Clone()
	Copied.Parent = leaderstats
end
end)

this will make it easier and everytime you want to make a new value in the leaderstats, you only have to create an intvalues inside the folder instead of doing in a script.

i hope it was helpful

1 Like

This doesn’t replicate properly, and can therefore cause flicker on the leaderboard.

Don’t parent leaderstats to the player before you have added all children. This causes unnecessary replication updates and causes the client to see the leaderstats without all values properly parented to it.

Remove the second argument to Instance.new, and only do leaderstats.Parent = plr after you’re done adding its children.

5 Likes

To be honest this seems like a bad idea to implement in a game as this can have many issues as @qwertyexpert mentioned. For if developers are so lazy that they can’t make a simple leader stats folder when a player joins that is more of a developer issue. This whole-systems seems ineffective. But I do like the creative idea and keep up the work.

3 Likes

This is very inefficient and I’ll just make an more optimized version

local pathtoyourleaderstatfolder = pathtostarterleaderstats

game.Players.PlayerAdded:Connect(function(plr)
local leaderstats = Instance.new("Folder")
leaderstats.Parent = plr
leaderstats.Name = "leaderstats"
for _,v in ipairs(pathtoyourleaderstatfolder:GetChildren()) do
v:Clone().Parent = leaderstats
end
end)

This is about as inefficient because it also parents the leaderstats to the player before adding children to it.

Yes

so i should add the content first then parent it?

1 Like

Yes like so

local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
for _,v in ipairs(pathtoyourleaderstatfolder:GetChildren()) do
  v:Clone().Parent = leaderstats
end
leaderstats.Parent = plr
2 Likes

In my opinion, basic leaderstats are really easy to script.

Here’s a script I made that includes a DataStore. All you have to do is create a new IntValue each time you want another leaderstat:

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("DataStoreValues") --Name the DataStore whatever you want

game.Players.PlayerAdded:Connect(function(player)

    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = player

	local Cash = Instance.new('IntValue')
	Cash.Name = "Cash"
	Cash.Value = 0

	local value1Data = Cash

	local s, e = pcall(function()
		value1Data = DataStore:GetAsync(player.UserId.."-Value1") or 0 --check if they have data, if not it'll be "0"
	end)

	if s then
		FlagBucks.Value = value1Data --setting data if its success
	else
		game:GetService("TestService"):Error(e)  --if not success then we error it to the console
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
local s, e = pcall(function()
	DataStore:SetAsync(player.UserId.."-Value1", player.leaderstats.Cash.Value) --setting data
	end)
	if not s then game:GetService("TestService"):Error(e) 
	end
end)
1 Like

Just to add- make sure to use :BindToClose for saving too, I use it for my game

What’s the difference between using BindToClose and the one I provided? I tested mine and it works, so Im curious on how BindToClose could improve it.

If the server shuts down, player removing won’t fire but BindToClose will fire.

Basically, to prevent data loss. It happens mostly when you update and shutdown your game.

1 Like

Is this better?

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("DataStoreValues") --Name the DataStore whatever you want
local RunService = game:GetService("RunService")

game.Players.PlayerAdded:Connect(function(player)

    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = player

	local Cash = Instance.new('IntValue')
	Cash.Name = "Cash"
	Cash.Value = 0

	local value1Data = Cash

	local s, e = pcall(function()
		value1Data = DataStore:GetAsync(player.UserId.."-Value1") or 0 --check if they have data, if not it'll be "0"
	end)

	if s then
		FlagBucks.Value = value1Data --setting data if its success
	else
		game:GetService("TestService"):Error(e)  --if not success then we error it to the console
	end
end)

game:BindToClose(function(player)
if not RunService:IsStudio()
local s, e = pcall(function()
	DataStore:SetAsync(player.UserId.."-Value1", player.leaderstats.Cash.Value) --setting data
	end)
	if not s then game:GetService("TestService"):Error(e) 
	end

       end)
end)
1 Like

Yes.

I just edited my script because I realized that I needed to use

if not RunService:IsStudio()

For the :BindToClose

1 Like

I noticed one thing, you completely switched player removing to BindToClose, you should also add player removing with BindToClose.

1 Like

Is this better?

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("DataStoreValues") --Name the DataStore whatever you want
local RunService = game:GetService("RunService")

local function OnPlayerAdded(player)

    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"
    leaderstats.Parent = player

	local Cash = Instance.new('IntValue')
	Cash.Name = "Cash"
	Cash.Value = 0

	local value1Data = Cash

	local s, e = pcall(function()
		value1Data = DataStore:GetAsync(player.UserId.."-Value1") or 0 --check if they have data, if not it'll be "0"
	end)

	if s then
		FlagBucks.Value = value1Data --setting data if its success
	else
		game:GetService("TestService"):Error(e)  --if not success then we error it to the console
	end
end

local function OnPlayerRemoved(player)
local s, e = pcall(function()
	DataStore:SetAsync(player.UserId.."-Value1", player.leaderstats.Cash.Value) --setting data
end

game:BindToClose(function(player)
if not RunService:IsStudio()
local s, e = pcall(function()
	DataStore:SetAsync(player.UserId.."-Value1", player.leaderstats.Cash.Value) --setting data
	end)
	if not s then game:GetService("TestService"):Error(e) 
	end

       end)
end)

Players.PlayerAdded:Connect(OnPlayerAdded)
Players.PlayerRemoving:Connect(OnPlayerRemoving)

just that you are wrapping the setasync in pcalls and doing nothing if it failed

Oops. I forgot to add that. Let me do it now.

1 Like

i have a question, why do you use testservice:Error instead of error()?

1 Like

I think they’re trying to print an error without stopping the script. task.spawn(error, 'message here') works okay, but it includes the ‘Stack Begin’/‘Stack End’ which I think is what they were trying to avoid.

1 Like