Quick donation board - Monetize in a snap!

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

Thank you for suggesting my plugin! :slight_smile:

2 Likes

This was described in an earlier post.

Hi, awesome system - only recommendation, add themes!

A way I did this with a system I made (FoodMate) was have a folder with UI gradients with different names, add in default ones and the customer can make their own ones if they like, and basically put a stringValue in each component to copy the UI gradient into named “ThemePart” and whenever you startup the system it detects the theme selected (possibly just another config thing) and finds all “ThemePart”'s and then just clones in the selected UI gradient.

I know this would be the most annoying suggestion and I also made it a lot more complicated than it needed to be because you can script it without me spoonfeeding it to u lmfao

The ONLY semi issue I found was when I added multiple boards, the congratulations notification appeared on all of them and I had to manually press dismiss on each and every board. Possibly just add a bindable function somewhere that will auto hide them all when you dismiss one notification.

1 Like

Dont mind the background music was listening to some heavy base boost’d stuff…

@twinqle, this is what i’ve made of your donation lb. (Just added a lil effect ;))

3 Likes

hey man how can i use my already created datastore has all my players donations already in it . i wanna use your board instead but mine at the moment only called the datastore by its name “datastorenamehere” in this format ty

Hey for some reason when i have this board in my game, other developer product functions breaks and doesn’t work! Help!

Looks amazing. One question, how do I make a thing where like if the player donated any amount of Robux, in the chat it says “(user) donated (rbx amnt), thank you!”?

how do I expand it for extra developer products

Just listen for any purchase prompt events, it can be done in a different script.