How to make awards like top 100, top 10,000 and everyone else (like RB Battles)

Hello, I’m trying to make a final battle system like RB Battles. And I want to add top 100, top 10,000 awards and award for others. I don’t know what should I do.

I did some search on devforums and on youtube. I was thinking to use MessagingService and a globabl saving data on ServerStorage. But I have some worries about this. I don’t want publish with bugs and I don’t know what to do.

Here is some my worries:

-When someone won the final battle and a new server created at the same time. Can MessegingService send message to this server immediately?

-When a player won the final battle it sends every server a message and every server adds +1 value on number value in ServerStorage. Is that true? Can this cause bugs?

-What should data store type should I use GetDataStore or GetOrderedDataStore or GetGlobalDataStore. Because there are a lot of final battles and a lot of number values in ServerStorage

By the way Im trying to make a data store that can stores every final battles data with differently. So I can reset one of final battles data when it has bugs or something. But I don’t know how to make this.

I heard something called DataStore2 but I don’t know is that helpful to reach my goal. I did some search for it but i didn’t understand.

Here is my code for increase value of NumberValues on ServerStorage. I don’t know is this neccesary.

local MessagingService = game:GetService("MessagingService")
local Battles = game:GetService("ServerStorage").Battles

MessagingService:SubscribeAsync("SomeoneDidBattle", function(whichbattle)
	Battles:FindFirstChild(whichbattle).Value += 1
end)
1 Like

Make a data store with how many people have won the game. Which updates every time someone wins. Then just check if the amount is greater than 100 and less than 10,000 or less than 100

1 Like

Thank you but Is there a better way than use MessagingService to change the global data in every servers? Because I have a worry about it. For example what if someone won and a new server opened at the same time, I’m not sure but maybe MessagingService can’t send data and this new server’s global value may lower than others.

Set it in a datastore as I suggested then because that would update even for a new server

I’m not familiar with the RB battles system. Could you elaborate a bit more on it?

Usually for a ‘top 100’ global leaderboard, you can use OrderedDatastores.

you need to place it in data store and data stores are kinda hard to do

I’m not the OP, but I played in RBB which was an event on roblox. What they are attempting to make is a system where the first X amount of people get rewarded a Perk. The event used this for UGC items and badges. For example RB battles had a golden crown and a Normal crown. The first 10,000 people to do the challenge got the golden and Normal crown. Everyone else after the first 10,000 people just got a Normal crown.


Here are My own Recommendations.

Don’t use messaging service for this.

Unlike other services on the Platform. MessagingService is not guaranteed to fire and is a best effort! Roblox recommends when using MessagingService to account for it’s Errors.

Also Messaging Service Has a TON of limitations Which Include:
Limit Maximum
Size of message 1kB
Messages sent per game server 150 + 60 * (number of players in this game server) per minute
Messages received per topic (10 + 20 * number of servers) per minute
Messages received for entire game (100 + 50 * number of servers) per minute
Subscriptions allowed per game server 5 + 2 * (number of players in this game server)

Rather I would Recommend Using Datastores and UpdateAsync()

When you need reward the perk: Use UpdateAsync on a Datastore that as an IntValue of how many people have won. Then decide what perks they should get by comparing the old data. Then add +1 to the old data. UpdateAsync reads the data before updating it, so other servers shouldn’t rewrite it (Better then :SetAsync in this case)

(Optional if you were displaying it somewhere): When you need To View how many have been rewarded: Use :GetAsync() to read how many people have won the value if you ever need it instead of UpdateAsync() as we don’t want to add a new winner


Hope this helps! Let me know if you have questions

1 Like

Creating a final battle system with awards and leaderboard functionality can be a complex task, but it’s definitely achievable. Here are some considerations and suggestions to help you implement this system:

MessagingService and Server Communication:

  1. MessagingService: Using MessagingService to communicate between servers is a good idea. It allows different servers to communicate events and updates to each other without directly knowing about each other.
  2. Server Timing: When a new server is created, it should be able to subscribe to the necessary MessagingService channels to receive updates from other servers. This should be done as soon as the server starts.

Data Storage:

  1. DataStore Type: For storing battle data and player scores, you should consider using a DataStore. The choice between GetDataStore, GetOrderedDataStore, or GetGlobalDataStore depends on your specific needs. If you want to track leaderboards and player scores, GetOrderedDataStore is suitable. If you want a general data storage solution, GetDataStore can work.
  2. DataStore2: DataStore2 is a popular third-party module that simplifies data storage and management. It can be helpful for your project as it provides more features and better error handling than the default Roblox DataStore.
  3. Differentiate Final Battles: To store data for different final battles separately, you can use a naming convention or unique identifiers for each battle. For example, you could use "FinalBattle_August2023" as a unique identifier for a specific final battle’s data.

Handling Awards and Leaderboards:

  1. Awards: For awarding players based on their performance in the final battles, you can use DataStore to track player scores. When a player participates and completes a battle, update their score in the DataStore. Periodically, you can sort the scores and award the top players based on your criteria.
  2. Leaderboards: Use GetOrderedDataStore to create leaderboards. Periodically, retrieve player scores from the DataStore, sort them, and display the leaderboard in-game.

Incrementing Value in ServerStorage:

Your code for incrementing values in ServerStorage looks correct for its purpose. However, keep in mind that you need to ensure that your messaging system works reliably and handles possible race conditions. In a high-traffic environment, you might need additional logic to prevent data inconsistencies.

In conclusion, while implementing a complex final battle system with awards and leaderboards can be challenging, a well-structured approach involving MessagingService and DataStore will help you achieve your goals. Consider using DataStore2 for enhanced data storage capabilities, and plan your server communication and data storage strategies carefully to ensure a robust and bug-free implementation.

2 Likes

Thank you. Also I have one more question. Should I use OrderedDataStore to store everyone’s ranking datas on a data? What happens if I store over thousands of people’s data on a ordered data store?

Or should I store a data for how many people beat the final battle and everyone’s data on their own keys? I mean there is a data on ServerStorage for how many people beat that final battle and there is a value in player for what is player’s rank on that final battle.

By the way also one of my goal is every player can see what their rank on that final battle

Which one is good idea?

Use a normal datastore to do this. You will want to store this data. You could use OrderedDataStore but then your limited your in options as you wouldn’t be able to add other values like how long the player took the challenge. And what play they got.

Use One server key, and add people to it. Save the UserID and Rank when someone finishes by using :UpdateAsync, to compare who finished last.

Now what you could do if the player will only know their rank as you mentioned it was a goal of yours. If they will only see their own rank, use one datastore, and store UserUnique Keys - “player.UserId…’-Userkey’” within that datastore that will store their Number and own data about the challenge, and then make one long list with a key like “FullList-ServerKey” for the big list. I mention this as it would be annoying, hard, and take a while to index the players position in a list with more then 1,000 different people

1 Like

Thank you again. By the way sorry for late response, I was trying to think how can I make this. And I was planning to make this system.

Also I made a layout for datas to save them. I will use normal data stores.

And also there are different several final battles in game. And I will make different key for every final battle. Should I do that is this good idea? Or should I use :GetDataStore() with other values to make different several final battles? I don’t know which one is better.

Also I’m planning to make a machine to type player name and see what is players rank in that final battle (same thing with ranks like type rank and see who is first or who is second etc…)

To do that I made a layout to save datas for each key. It is an table looks like this in this script, the example table named exampleData:

local DataStoreService = game:GetService("DataStoreService")
local Data = DataStoreService:GetDataStore("BattlesData")
local Battles = game:GetService("ServerStorage"):WaitForChild("Battles")

function load()
	
	for i, v in pairs(Battles:GetChildren()) do
		local key = v:FindFirstChild("DataKey").Value
		local data = Data:GetAsync(key)
	end
		
end

local exampleData = {
	["BeatenCount"] = 0,
	["AttemptedUniqueAccounts"] = 0,
	["TotalAttempts"] = 0,
	
	["AttemptedAccounts"] = {
		["1"] = "Player1234",
		["2"] = "Player5555"
	}
	
	["List"] = {
		["1"] = {
			["Name"] = "Player1234"
			-- Maybe i will add more info for players, for now thhere is only player name.
		},
		["2"] = {
			["Name"] = "Player5555"
		}
	}	
}

To make player finder machine I am planning to make a for loop but will be there this for loop will use :GetAsync() a lot of times to find. I heard somewhere when a script use this a lot of the data store may break. Is that true? If this is true what do you suggest to do something like this?

The set up I mentioned about is a tad different. Let me show you what I mean.

Every player (if you went my method) would have a set up like this:


--The following Player is what *could* be OfficialPogCats Data (Me)

local ExampleOfficialPogCatList =  {
["AttemptsAtBattle1"] = 5, --Idk what you store, this is an example
["WinsAtBattle1"] = 2,
["Battle1Rank"] = 1, --This is stored in both Player and Server Datastore below as the "Position" in where they finished. 
["AttemptsAtBattle2"] = 7, 
["WinsAtBattle2"] = 1,
["Battle2Rank"] = 3821,
}

--My User Id is 648942781 so My key in this example to load this data is 648942781-BattleKey



--The following Player is what *could* be Rumixist Data

local ExampleRumixistList =  {
["AttemptsAtBattle1"] = 25, --Idk what you store, this is an example
["WinsAtBattle1"] = 10,
["Battle1Rank"] = 2, --This is stored in both Player and Server Datastore below as the "Position" in where they finished.
["AttemptsAtBattle2"] = 54, 
["WinsAtBattle2"] = 21
["Battle2Rank"] = 3,
}

--Your User Id is 852327832 so your key in this example to load this data is 852327832-BattleKey

The Above is how I would set up something like this. That way when the Player wants to search other people, You only have to do something like this:

local PlayerByName = "OfficialPogCat" 
local UserID = game.Players:GetUserIdFromNameAsync(PlayerByName)
local Datastore = game:GetService("DataStoreService"):GetDataStore("BattleData") 

 local PlayerSearchData = Datastore:GetAsync(UserID.."-BattleKey") --Ideally you want to pcall this and do more fancy things. This is an example however. 

if PlayerSearchData ~= nil then 
  --Do whatever you want here
else 
   print("Player Data is Nil... ") 
end

Note: For a system like this you want to make sure that the Player is a Real person, and you also want to add cooldowns to searching. They don’t have to be huge, but if the player spam clicks the button you are going to go above the limits of the Reading data. So make sure you have a cooldown and that before you request to the server to search a person, you make sure the person is real.

Now this doesn’t fix the original problem of the post, which is why we have a Second version Which we can store for the server usage. (Aka this is the one that you would use UpdateAsync() on, and this is the one that you would use for Top 100 award etc. ) An example of the Set up is like this:

local BattleOneExample = {
["Stats"] = {  --I guess if you want stats you can.
["Battle1Attempts"] = 173931,
["Battle1Wins"] = 5621,} 

["PlayerRanks"] = {
[1] = 648942781, --First Number being the Position they won. Second one being their UserID
[2] = 852327832,
...
}
 }

--For example, This key will be ServerBattle1-Key

Now, when we need to Update this data (add another person to the Rank List) we will Do this:

local Datastore = game:GetService("DataStoreService"):GetDataStore("BattleData") 

Datastore:UpdateAsync("ServerBattle1-Key", function(OldData) 
--Do magic here of changing position
end) --Ideally you want to pcall this and do more fancy things. This is an example however. 

I know I just threw out a ton of information for you! So let me know if you have questions! But this is what I would do if I were you in setting up this.


P.S : I know I didn’t directly answer a lot of your questions. Use different keys. Search By rank should use the Server Data, Rank search by Name/ UserId should be done by Personal Data. You should Prevent as many :GetAsync() calls as you can. There is datastore limits and so you need to follow the limits. What I would do is have the Server store the Main Battles list and change it every 15-30 minutes. Then I would have player limits, so a player can only search 3-5 players per minute to get their personal data. (Once they search 3-5 players, there is a cooldown until the next minute happens. It should be a short wait anyways as they would see to view 3-5 players before it)

1 Like

Thank you. I started to make this system like this. If I have any questions on this project, can I ask them here? Because it will probably take two or three months to finish this because I will be busy when school starts.

1 Like

Personally I would not. If you have an issue on datastores specifically then maybe. If you make new posts other people can pitch in and they don’t have to read this long line of chat to get an understanding.

1 Like