How to make a dono board? or the datastore for it?

Hi devforum readers, can you guys help me with this script? So basically, it’s a donation board that I’m trying to save/create data for. Everything is fine, but how can i simplify it and make it so there’s only one spot on the leaderboard for each player? How can i make it so the data loads when the player joins? How can I fix some parts of this script? Because it feels really jumbled up and not organized. Any tips?
(leaderstats server script)

local players = game:WaitForChild("Players")

local rs = game:GetService("ReplicatedStorage")
local gvRemote = rs:WaitForChild("GiftsValueRemote")
local dss = game:GetService("DataStoreService")



local donatedbase = dss:GetDataStore("DataStore")
local sessionData = {}
local MarketplaceService = game:GetService("MarketplaceService")



local amountValueTransfer = nil

local donoBoughtevt = rs.donoBoughtRemote
local leaderboardUpdater = rs.LeaderboardUpdater

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

	

	local donoGui = player.PlayerGui:WaitForChild("DonoGUI")
	local lbFrame = donoGui.LeaderBoardFrame

	local scrollframe = lbFrame.ScrollingFrame
	local btnholder = lbFrame.Buttonholderframe
	local lbNameFrame = scrollframe.LeaderBoardName
	local amountDonatedText = lbNameFrame.amountDonated
	local amountValue = amountDonatedText.RbxValue
	amountValueTransfer = amountValue.Value
	

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

	local gifts = Instance.new("IntValue")
	local giftsGiven = Instance.new("IntValue")
	local giftsReceived = Instance.new("IntValue")
	gifts.Name =  "Gifts"
	gifts.Value = 0
	giftsGiven.Name = "Gifted"
	giftsReceived.Name = "Received"
	
	gifts.Parent = leaderstats
	giftsGiven.Parent = leaderstats
	giftsReceived.Parent = leaderstats
	
	local success = nil
	local playerData = nil
	local attempt = 1
	repeat
		success, playerData = pcall(function()
			return donatedbase:GetAsync(player.UserId)
		end)

		attempt += 1
		if not success then
			warn(playerData)
			task.wait(3)
		end

	until success or attempt == 5
	if success then
		
		print("Connected to donatedbase")
		if not playerData then
			print("Assigning data")
			playerData = {
				["Donated"] = 0,
				["Gifts"] = 0,
				["Gifted"] = 0,
				["Received"] = 0
			}
	
		end
		sessionData[player.UserId] = playerData
	else
		warn("Unable to get data for:", player.Name)
		player:Kick("Reason: Unable to load your data. Rejoin the game! If this message keeps occurring, let a staff member know in the group wall.")
	end
--donated leaderboard data saving
	donoBoughtevt.Event:Connect(function(plr, value)
		print("Donation bought, here's what was received:", plr, value)
		wait(0.1)
		sessionData[player.UserId].Donated = sessionData[player.UserId].Donated + value
		
		amountValueTransfer = amountValueTransfer + value
		
		amountValue.Value = amountValueTransfer + sessionData[player.UserId].Donated
		leaderboardUpdater:Fire(player.Name, amountValue.Value)
	end)

	
		
	--leaderstats data saving
	gifts.Value = sessionData[player.UserId].Gifts
	giftsReceived.Value = sessionData[player.UserId].Received
	giftsGiven.Value = sessionData[player.UserId].Gifted
	
	gifts.Changed:Connect(function()
		sessionData[player.UserId].Gifts = gifts.Value
	end)
	giftsReceived.Changed:Connect(function()
		sessionData[player.UserId].Gifts = giftsReceived.Value
	end)
	giftsGiven.Changed:Connect(function()
		sessionData[player.UserId].Gifts = giftsGiven.Value
	end)
	
	leaderboardUpdater:Fire(player.Name, sessionData[player.UserId].Donated)
end)

function playerLeaving(player)
	
	if sessionData[player.UserId] then
		local success = nil
		local errorMsg = nil
		local attempt = 1
		repeat
			success, errorMsg = pcall(function()
				donatedbase:SetAsync(player.UserId, sessionData[player.UserId])
			end)
			
			attempt += 1
			
		until success or attempt == 5
		
		if not success then
			warn(errorMsg)
			wait(3)
		end
		if success then
			print("data saved for:", player.Name)
			print("Currently donated:", amountValueTransfer, "All time donated:", sessionData[player.UserId].Donated)
		else
			print("Unable to save data for", player.Name)
		end
	end
end

players.PlayerRemoving:Connect(playerLeaving)

(Donation board updater Server script)

local mps = game:GetService("MarketplaceService")
local rs = game:GetService("ReplicatedStorage")
local dss = game:GetService("DataStoreService")

local robuxTable = {

	{
		ProductPrice = 10, --The price from the Developer Product.
		ProductId = 2662730118 -- The ID from the Developer Product.	
	},
	{
		ProductPrice = 100, --The price from the Developer Product.
		ProductId = 2662730200 -- The ID from the Developer Product.	
	},
	{
		ProductPrice = 1000, --The price from the Developer Product.
		ProductId = 2662730310 -- The ID from the Developer Product.	
	},
	{
		ProductPrice = 2000, --The price from the Developer Product.
		ProductId = 2662730427 -- The ID from the Developer Product.	
	},
	{
		ProductPrice = 3500, --The price from the Developer Product.
		ProductId = 2662730540 -- The ID from the Developer Product.	
	},
	{
		ProductPrice = 10000, --The price from the Developer Product.
		ProductId = 2662730789 -- The ID from the Developer Product.	
	},

}

game.Players.PlayerAdded:Connect(function(plr)
	local donoGui = plr.PlayerGui:WaitForChild("DonoGUI")
	local lbFrame = donoGui.LeaderBoardFrame
	
	local scrollframe = lbFrame.ScrollingFrame
	local btnholder = lbFrame.Buttonholderframe
	local lbNameFrame = scrollframe.LeaderBoardName
	local amountValue = lbNameFrame.amountDonated.RbxValue
	
	local leaderboardUpdater = rs.LeaderboardUpdater
	local donoReqEvent = rs.donoRequest
	local donoBoughtEvent = rs.donoBoughtRemote
	while task.wait() do
		for i = 1, 9, 1 do
			wait(.1)

			local lbFrameClone = lbNameFrame:Clone()
			lbFrameClone.Parent = scrollframe
			lbFrameClone.amountDonated.Text = "Loading..."
			lbFrameClone.rankText.Text = "#" .. i + 1
			lbFrameClone.username.Text = "test" .. i + 1
			lbFrameClone.Name = "Place" .. i

----------------place this somewhere else
			leaderboardUpdater.Event:Connect(function(user, amountDonated)
				print("Leaderboard updater fired!", user, amountDonated)
				lbFrameClone.username.Text = user
				lbFrameClone.amountDonated.Text = "$R" .. amountDonated
				lbFrameClone.amountDonated.RbxValue.Value = amountDonated
			end)
		end
		
		break
	end

		
	donoReqEvent.OnServerEvent:Connect(function(player, productPrice)
		--print("server event fired")
		-- Find the product based on the price
		for _, product in ipairs(robuxTable) do
			if product.ProductPrice == productPrice then
				--print(productPrice)
				donoReqEvent:FireClient(player, product.ProductId)
				mps.ProcessReceipt = function(receiptInfo)
					local player = game.Players:GetPlayerByUserId(receiptInfo.PlayerId)

					if player then
						if receiptInfo.ProductId == product.ProductId then
							-- If the player bought the specific product
							print(player.Name .. " has successfully bought the product!")
							
							amountValue.Value = amountValue.Value + productPrice
							donoBoughtEvent:Fire(player, amountValue.Value)
							-- Return Enum.ProductPurchaseDecision.PurchaseGranted to confirm the purchase
							return Enum.ProductPurchaseDecision.PurchaseGranted
						else
							-- If it's not the product you're checking for, deny it
							return Enum.ProductPurchaseDecision.NotProcessedYet
						end
					end

					return Enum.ProductPurchaseDecision.NotProcessedYet
				end
				break
			end
		end
	end)
	
end)

(what prints)

(How it looks)
image

bump post bc i really need help im stuck and i suck at scripitng-

Can you please clarify whether the leaderboard is meant to only show the top players in the server, or is it meant to show the top players overall?

it is meant to show the top players donated globally

For a global board, you should make use of OrderedDataStores instead of normal datastores.

The documentation has some information that should be helpful

Thanks, I will put this to use. But, any suggestions on the current script other than that?

The event thing on line 58 is flawed, as it updates every single position on the leaderboard, instead of the applicable one.

Instead of trying to update it like that, you should instead just periodically delete the contents of the leaderboard and then reclone everything, using the new placements. (This is easier to do with OrderedDataStore than with your current implementation)

1 Like