Quick donation board - Monetize in a snap!

Hey! Is there a free model with the statue? I’m not sure how I would do it myself…

@Bloxxy213_DVL replied to the thread on Apr 30 with his fork of the board which includes a statue.

Hi! I encountered an issue when loading an animation, the character is floating above the ground. Do you have any idea on how to fix the issue?

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?