Quick donation board - Monetize in a snap!

Roblox is slowly using Animators, and the script still yses the old Humanoid to play animations. I can’t redo the model rn

Hmm, I see. Is there a wiki article I could read to maybe try to make one myself?

Edit: After playing around with different anchored properties, I managed to get the results I was looking for.

Wow! Simple to set up, easy to use, amazing in game. Thank you for this spectacular donation board! Can’t believe you are giving this out for free. :smiley: :+1:

1 Like

Hi there,

The donation board looks very nice and clean, functions properly and has a taste to it, yet is slightly performance draining at some point.

I’d recommend looking into that again.

Do you have any evidence of performance drain caused by it? Perhaps send a screenshot of its script activity?

I’ve used this extensively in my game and have never experienced issues. I can’t imagine you would either–it’s just a loop that sends a request to a datastore and fires all clients once every 60 seconds.

Where are you getting this information from?

1 Like

Hi, sorry I forgot to update you about this.

Please refer to my previous post.

Above, you can see evidence of the memory leak, that did exist.

Here, you can see that I technically found out that the issue was something completely different.

My apology for the inconvenience.

hey i did a custom donation board (changes on UI) + a dancing rig (only one which would make it good and neat)

1 Like

How? I want to make it orange, I tried any way I can think off but the color doesn’t change.
Edit: nevermind I figure it out, sorry.

how do I make the board smaller without it messing up the ui

Wow that’s amazing! I like the UI as its neat and clean. I’ll be sure to use this in my future games, with your credit, of course!

Good job!

1 Like

It doesn’t work, most of the donation doesn’t show up

Is there a way to remove someone from the donation board???
I’ve donated in Studio as a test and it saved it without me wanting it to.

You can remove their key (UserId) from the OrderedDataStore.

How would I go about doing this exactly? I’ve seen something about using the :RemoveAysnc() feature, but I don’t quite know where that goes or how it really works.

I’ve tried something similar to this already and it makes no difference:

Could you post the script you ran?

This is the full Core code (minus the dev products). The key bit is down the very bottom.

local DataStoreService = game:GetService("DataStoreService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")

local gui = script.Donations
local face = Enum.NormalId[GUI_FACE]

local eve = Instance.new("RemoteEvent")
eve.Name = "DonationEvent"
eve.Parent = ReplicatedStorage

local cache = {}

local tmType = Enum.ThumbnailType.HeadShot
local tmSize = Enum.ThumbnailSize.Size420x420

local donations = DataStoreService:GetOrderedDataStore("DONATIONS_" .. DATA_KEY)

if not face then error("Invalid GUI_FACE: " .. GUI_FACE) else gui.Face = face end

local function getName(id)
	for cachedId, name in pairs (cache) do
		if cachedId == id then
			return name
		end
	end
	local success, result = pcall(function()
		return Players:GetNameFromUserIdAsync(id)
	end)
	if success then
		cache[id] = result
		return result
	else
		warn(result .. "\nId: " .. id)
		return "N/A"
	end
end

local function findAmountById(id)
	for _, donationInfo in pairs (DONATION_OPTIONS) do
		if donationInfo.Id == id then
			print(donationInfo.Amount)
			return donationInfo.Amount
		end
	end
	warn("Couldn't find donation amount for product ID " .. id)
	return 0
end

local function clearList(list)
	for _, v in pairs (list:GetChildren()) do
		if v:IsA("Frame") then v:Destroy() end
	end
end

local function updateAllClients(page)
	eve:FireAllClients("update", page)
end

local function updateInternalBoard(updateClientsAfter)
	local sorted = donations:GetSortedAsync(false, math.clamp(DISPLAY_AMOUNT, 0, 250), 1)
	if sorted then
		local page = sorted:GetCurrentPage()
		local clientDataPacket = {}
		clearList(gui.Main.Leaderboard.List)
		for rank, data in ipairs(page) do
			local userId = data.key
			local username = getName(data.key)
			local icon, isReady = Players:GetUserThumbnailAsync(userId, tmType, tmSize)
			local amountDonated = data.value .. " robux"

			local clone = gui.Main.Leaderboard.Template:Clone()
			clone.Icon.Image = icon
			clone.Rank.Text = "#" .. rank
			clone.Robux.Text = amountDonated
			clone.Username.Text = username
			clone.LayoutOrder = rank
			clone.Visible = true
			clone.Parent = gui.Main.Leaderboard.List
			
			table.insert(clientDataPacket, {
				["name"] = username,
				["icon"] = icon,
				["amount"] = amountDonated,
				["rank"] = rank
			})
		end
		
		if updateClientsAfter then
			updateAllClients(clientDataPacket)
		end
	else
		warn("No data available for leaderboard refresh!")
	end
end

local function createButtonsInternal()
	for pos, donationInfo in pairs (DONATION_OPTIONS) do
		local clone = gui.Main.Donate.Template:Clone()

		clone.Id.Value = donationInfo.Id
		clone.Info.Text = "<b>" .. donationInfo.Amount .. "</b> robux"

		clone.Visible = true
		clone.LayoutOrder = pos

		clone.Parent = gui.Main.Donate.List
	end
end

local function processReceipt(receiptInfo) 
	local donatedAmount = findAmountById(receiptInfo.ProductId)
	local id = receiptInfo.PlayerId

	local success, err = pcall(function()
		donations:UpdateAsync(id, function(previousData)
			if previousData then
				return previousData + donatedAmount
			else
				return donatedAmount
			end
		end)
	end)

	local player = Players:GetPlayerByUserId(id)

	if not success then
		if player then
			eve:FireClient(player, "Error", "There was an error processing your purchase. You have not been charged. Error: " .. err)
		end
		warn("Error handling " .. id .. "'s purchase: " .. err)
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end

	if player then
		eve:FireClient(player, "Success", "Thanks for your generous donation!")
	end

	return Enum.ProductPurchaseDecision.PurchaseGranted
end

local function onPlayerAdded(plr)
	local pGui = plr:WaitForChild("PlayerGui", 5)
	if pGui then
		for _, board in pairs (script.Parent:GetChildren()) do
			if board.Name == "Board" then
				local clone = gui:Clone()
				clone.Adornee = board
				clone.Parent = pGui
			end
		end 
		return true
	end
	warn("Couldn't find PlayerGui for " .. plr.Name .. ":" .. plr.UserId)
end

createButtonsInternal()
updateInternalBoard(false)
MarketplaceService.ProcessReceipt = processReceipt

for _, plr in pairs (Players:GetPlayers()) do
	onPlayerAdded(plr)
end
Players.PlayerAdded:Connect(onPlayerAdded)

while true do
	wait(REFRESH_RATE)
	updateInternalBoard(true)
end





local success, removedValue = pcall(function()
	return donations:RemoveAsync("User_336700386")
end)
if success then
	print(removedValue)
end

Where are you getting the “User_” from? And why is it a string?

I saw on a different post that was how it was done…
I’m assuming that is very incorrect.

how to make top player? show npc
like this :

I’ve made donations in studio and I don’t know how to get rid of them without changing the datastore completely and erasing real donations from other users. I’ve tried using SetAsync and UpdateAsync, but I don’t have too much experience in datastores at the moment and to my understanding, it’s not working when I try. How can I get rid of donations without removing all of them?

EDIT: I was able to fix the issue with this amazing datastore plugin. I suggest you check it out, it’s very useful.

1 Like