Do you want it to be monthly or to not be monthly? I’m confused as to what you want here. The leaderboard, by default, is not monthly. For it to be monthly, see the FAQ.
To make it work as a monthly leaderboard u will have to reset the datastore every month, not manually though. u can add a script in it to make it work.
you can maintain multiple datastore to do so, so that you also have a global leaderboard in case u need both.
I did a all time leaderboard on my game
I tried to make copies of a main leaderboard and then copy it to the secondary ones, but when the place is loaded, the secondary boards seem to receive the content very slowly.
This is the single part where I changed the script:
for number,d in pairs(data) do--Loop through our new data
local name = d[1]
local val = d[2]
local image = d[3]
local color = Color3.new(1, 1, 1)--Default color
if number == 1 then
color = Color3.new(1, 0, 0)--1st place color
elseif number == 2 then
color = Color3.new(1, 0.854902, 0.109804)--2nd place color
elseif number == 3 then
color = Color3.fromRGB(255, 158, 21)--3rd place color
end
local new = sample:Clone()--Make a clone of the sample frame
new.Name = name--Set name for better recognition and debugging
new.LayoutOrder = number--UIListLayout uses this to sort in the correct order
new.Image.Image = image--Set the image
new.Image.Place.Text = number--Set the place
new.Image.Place.TextColor3 = color--Set the place color (Gold = 1st)
new.PName.Text = name--Set the username
val = MoneyLib.HandleMoney(val)
new.Value.Text = val--Set the amount of points
new.Value.TextColor3 = color--Set the place color (Gold = 1st)
new.PName.TextColor3 = color--Set the place color (Gold = 1st)
new.Parent = sf--Parent to scrolling frame
--Trying to copy the main leaderboard to the secondary ones
for i, list in pairs(workspace.LeaderBoards.SecondaryLeaderboards:GetChildren()) do
list.CashBoard.Leader.SurfaceGui.ScrollingFrame:Destroy()
local clone = sf:Clone()
clone.Parent = list.CashBoard.Leader.SurfaceGui
end
end
Any ideas on how to make this work? I feel like the lines where I implemented the copying is not the right place, but I couldn’t find where else to make it.
It’s hard to tell when you’ve removed a chunk of the original code and I don’t know how your object hierarchy looks. My best bet would be testing and seeing if it gets created and where.
I didn’t include the rest of the code because it is exactly the same as the original one with the single change made being the addition of the four lines that are copying it. I thought it was reductant to include it.
However, this is the full code of the cash board:
local sg = script.Parent
local sample = script:WaitForChild("Sample") --Our Sample frame
local sf = sg:WaitForChild("ScrollingFrame") --The scrolling frame
local ui = sf:WaitForChild("UI") --The UI list layout
local MoneyLib = require(game:GetService("ReplicatedStorage").MoneyLib)
local dataStoreService = game:GetService("DataStoreService")
--The data store service
local dataStore = dataStoreService:GetOrderedDataStore("CashBoard")
--Get the data store with key "Leaderboard"
wait(10)
while true do
for i,plr in pairs(game.Players:GetChildren()) do--Loop through players
if plr.UserId>0 then--Prevent errors
local w = math.floor(--[[Value that I count for the cash]])
if w then
pcall(function()
--Wrap in a pcall so if Roblox is down, it won't error and break.
dataStore:UpdateAsync(plr.UserId,function(oldVal)
--Set new value
return tonumber(w)
end)
end)
end
end
end
local smallestFirst = false--false = 2 before 1, true = 1 before 2
local numberToShow = 100--Any number between 1-100, how many will be shown
local minValue = 1--Any numbers lower than this will be excluded
local maxValue = 10e30--(10^30), any numbers higher than this will be excluded
local pages = dataStore:GetSortedAsync(smallestFirst, numberToShow, minValue, maxValue)
--Get data
local top = pages:GetCurrentPage()--Get the first page
local data = {}--Store new data
for a,b in ipairs(top) do--Loop through data
local userid = b.key--User id
local points = b.value--Points
local username = "[Failed To Load]"--If it fails, we let them know
local s,e = pcall(function()
username = game.Players:GetNameFromUserIdAsync(userid)--Get username
end)
if not s then--Something went wrong
warn("Error getting name for "..userid..". Error: "..e)
end
local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
--Make a image of them
table.insert(data,{username,points,image})--Put new data in new table
end
ui.Parent = script
sf:ClearAllChildren()--Remove old frames
ui.Parent = sf
for number,d in pairs(data) do--Loop through our new data
local name = d[1]
local val = d[2]
local image = d[3]
local color = Color3.new(1, 1, 1)--Default color
if number == 1 then
color = Color3.new(1, 0, 0)--1st place color
elseif number == 2 then
color = Color3.new(1, 0.854902, 0.109804)--2nd place color
elseif number == 3 then
color = Color3.fromRGB(255, 158, 21)--3rd place color
end
local new = sample:Clone()--Make a clone of the sample frame
new.Name = name--Set name for better recognition and debugging
new.LayoutOrder = number--UIListLayout uses this to sort in the correct order
new.Image.Image = image--Set the image
new.Image.Place.Text = number--Set the place
new.Image.Place.TextColor3 = color--Set the place color (Gold = 1st)
new.PName.Text = name--Set the username
val = MoneyLib.HandleMoney(val)
new.Value.Text = val--Set the amount of points
new.Value.TextColor3 = color--Set the place color (Gold = 1st)
new.PName.TextColor3 = color--Set the place color (Gold = 1st)
new.Parent = sf--Parent to scrolling frame
for i, list in pairs(workspace.LeaderBoards.SecondaryLeaderboards:GetChildren()) do
list.CashBoard.Leader.SurfaceGui.ScrollingFrame:Destroy()
local clone = sf:Clone()
clone.Parent = list.CashBoard.Leader.SurfaceGui
end
end
wait()
sf.CanvasSize = UDim2.new(0,0,0,ui.AbsoluteContentSize.Y)
--Give enough room for the frames to sit in
wait(120)
end
The frames of every player get created, and they parrent correctly to the scrolling frames of the secondary boards. The problem occurs when the server/map is loading. The main 4 boards receive their content instantly, but the secondary ones receive every frame (of every player on the board) very slowly (I think it is one frame for every 10 seconds).
This is the hierarchy:
You’re getting the children of a non-existent (or not shown) TycoonLeaderboards
. Assuming it does exist, and follow the same pattern as the rest of them, you seem to index each child directly with CashBoard
when you’d need to index with Set1
first.
What exactly is your use case? Is there really no errors? If possible, a place file would help.
Also, it is possible that you might be cloning large copies of instances unintentionally, which would explain the loading issues.
Sorry for the confusion, I corrected the name of the model that their children are indexed.
Set1, Set2, Set3 etc are all identical (they contain the same children). So in
for i, list in pairs(workspace.LeaderBoards.SecondaryLeaderboards:GetChildren()) do
list.CashBoard.Leader.SurfaceGui.ScrollingFrame:Destroy()
local clone = sf:Clone()
clone.Parent = list.CashBoard.Leader.SurfaceGui
end
list
is every Set and list.CashBoard
refers to every CashBoard in the set.
My use is that I want to have the main 4 leaderboards copied around the map. So every “Set” is a set of copies of the main leaderboards.
I don’t think I can provide a place file atm, but I can edit a new place to resemble my implementation if it helps.
If you’re cloning it after the layout is finished, you should be fine. If not (like you are now), then you will have issues. Check what is actually cloned to see.
Oops, I should’ve put it after the for
. Now it works, thanks!
Does the leaderboard display on the server only or it only displays cross server?
I haven’t tried but i need to make sure
As the name of this tutorial implies, this leaderboard is global.
Does daily/monthly/yearly leaderboard the points value to 0 every time it reset or it will stays on the same value
Ok for some example, a guy has 3 points for this month. Is it going to reset the points to 0 points for the next month? Or it will stay the value that the guy had last month?
Please read the FAQ or search this topic before asking a question.
This answer requires the context of the FAQ question about daily, monthly, and yearly leaderboards.
This depends how you set the data. Say you want to have a daily wins leaderboard. If after each win, you increment their wins by 1, it will reset, as it will look in a new datastore and not the previous one.
If, however, you just set their data to their total wins, it will not reset. This is because the value never gets reset to zero when the next day starts, so it will just be the same constantly.
is it possible for me to get the minutes in os.time so that i could test this a lot quicker?
local dateTable = os.date("*t", os.time())
local key = "Y:"..dateTable["year"].." M:"..dateTable["month"].." D:"..dateTable["day"]..dateTable["hour"]..dateTable["min"]
print(key)
print(dateTable["min"])
game.Players.PlayerAdded:Connect(function(player)
local value = Instance.new("IntValue")
value.Name = 'Value'
value.Parent = player
local stats = game.DataStoreService:GetDataStore(key)
local data = stats:GetAsync(player.UserId)
if data then
value.Value = data.Tests
end
value.Value = value.Value + 1
while true do
if os.date("*t", os.time())["min"] ~= key then
key = os.date("*t", os.time())
player.Value.Value = 0
print(dateTable["min"])
end
wait(1)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local stats = game.DataStoreService:GetDataStore(key)
local data = stats:SetAsync(player.UserId, {
["Tests"] = player.Value.Value
})
end)
when i print the key it would only show the year, month and days, and the days were weird because it appeared in the hundred thousands
Because you’re adding day + hour + minute, so day 30 at 5:30 would be D: 30530.
Additionally, you don’t need to run a while true loop to reset the key every second, and you should use task.wait instead.
i have a another question, in the script im trying to make daily, what im doing is getting the minute every second then if the script realises the minute has changed, it changes the key to the new date, iis this efficient?
local sg = script.Parent --Surface GUI
local sample = script:WaitForChild("Sample") --Our Sample frame
local sf = sg:WaitForChild("ScrollingFrame") --The scrolling frame
local ui = sf:WaitForChild("UI") --The UI list layout
local dateTable = os.date("*t", os.time())
local key = "Y:"..dateTable["year"].." M:"..dateTable["month"].." D:"..dateTable["day"].." H:"..dateTable["hour"].." I:"..dateTable["min"]
local dataStoreService = game:GetService("DataStoreService")
--The data store service
local dataStore = dataStoreService:GetOrderedDataStore(key)
--Get the data store with key "Leaderboard"
wait(10)
while true do
for i,plr in pairs(game.Players:GetChildren()) do--Loop through players
if plr.UserId>0 then--Prevent errors --PointsService
local w = plr.Value.Value --Get point balance
if w then
pcall(function()
--Wrap in a pcall so if Roblox is down, it won't error and break.
dataStore:UpdateAsync(plr.UserId,function(oldVal)
--Set new value
return tonumber(w)
end)
end)
end
end
end
local smallestFirst = false--false = 2 before 1, true = 1 before 2
local numberToShow = 100--Any number between 1-100, how many will be shown
local minValue = 1--Any numbers lower than this will be excluded
local maxValue = 10e30--(10^30), any numbers higher than this will be excluded
local pages = dataStore:GetSortedAsync(smallestFirst, numberToShow, minValue, maxValue)
--Get data
local top = pages:GetCurrentPage()--Get the first page
local data = {}--Store new data
for a,b in ipairs(top) do--Loop through data
local userid = b.key--User id
local points = b.value--Points
local username = "[Failed To Load]"--If it fails, we let them know
local s,e = pcall(function()
username = game.Players:GetNameFromUserIdAsync(userid)--Get username
end)
if not s then--Something went wrong
warn("Error getting name for "..userid..". Error: "..e)
end
local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
--Make a image of them
table.insert(data,{username,points,image})--Put new data in new table
end
ui.Parent = script
sf:ClearAllChildren()--Remove old frames
ui.Parent = sf
for number,d in pairs(data) do--Loop through our new data
local name = d[1]
local val = d[2]
local image = d[3]
local color = Color3.new(1,1,1)--Default color
if number == 1 then
color = Color3.new(1,1,0)--1st place color
elseif number == 2 then
color = Color3.new(0.9,0.9,0.9)--2nd place color
elseif number == 3 then
color = Color3.fromRGB(166, 112, 0)--3rd place color
end
local new = sample:Clone()--Make a clone of the sample frame
new.Name = name--Set name for better recognition and debugging
new.LayoutOrder = number--UIListLayout uses this to sort in the correct order
new.Image.Image = image--Set the image
new.Image.Place.Text = number--Set the place
new.Image.Place.TextColor3 = color--Set the place color (Gold = 1st)
new.PName.Text = name--Set the username
new.Value.Text = val--Set the amount of points
new.Value.TextColor3 = color--Set the place color (Gold = 1st)
new.PName.TextColor3 = color--Set the place color (Gold = 1st)
new.Parent = sf--Parent to scrolling frame
end
wait()
sf.CanvasSize = UDim2.new(0,0,0,ui.AbsoluteContentSize.Y)
--Give enough room for the frames to sit in
wait(120)
end
while true do
dateTable = os.date("*t", os.time())
print(dateTable["min"])
if dateTable["min"] ~= key[10] then
print(key[10])
key = os.date("*t", os.time())
for i,v in game.Players:GetChildren() do
v.Value.Value = 0
end
print("lower than value")
print(dateTable["min"])
else
end
wait(1)
end
Additionally i would like to know how to get the value of dataTable[“min”] from the variable key because i do not know how
and if your wondering why its minutes instead of days, its becausing im testing it, if it wasnt obvious
one question, why won’t this work? I don’t see anything wrong with it and there are no errors
while true do
local newdateTable = os.date("*t", os.time())
print(newdateTable["min"])
if newdateTable["min"] ~= dateTable["min"] then
key = "Y:"..newdateTable["year"].." M:"..newdateTable["month"].." D:"..newdateTable["day"].." H:"..newdateTable["hour"].." I:"..newdateTable["min"]
min = newdateTable["min"]
for i,v in game.Players:GetChildren() do
v.Value.Value = 0
end
print("lower than value")
print(dateTable["min"])
else
end
wait(1)
end
Where do you set datetable? That will work as long as you update datetable.
the while true updates the dateTable that was defined in the very beginning, my question is why is it not sensing when the newdateTable has a different minute to the original one