So I’ve been working on a SCP game, and I was wondering how one would make a team based xp/levelling system. Or in other words, support for different levels on different teams with different ranks, and xp that is not universal, as in doing something on one team doesn’t transfer to another. I’ve done some work with xp systems for one team, but never for one with multiple teams, I also don’t have much experience with making ranks, but I’d imagine that wouldn’t be to terribly hard.
If you’ve already got teams down, you’re just going to be doing some simple logic!
Once you’ve got an idea of what the player’s team is, you can use Player:GetRankInGroup to get their rank.
Here’s a couple examples of ways you could go about this.
Basic Code Structure
--// Run from a server script, not a local script
local Players = game:GetService("Players")
local GroupId = 111111
--// Call this function whenever you want to give the player XP
local function AwardXP(Player)
local PlayerRank: number = Player:GetRankInGroup(GroupId)
local PlayerTeam: Team = Player.Team
local XPAmount: number --// We fill this in with the amount of XP you want to give them
--// Actual code goes here
end
You can do whatever you want, this is just the basic framework I was working with, which is scalable to a couple different ways of going about it
Method 1 - Conditionals (not recommended, but showing this for breadth)
--// Run from a server script, not a local script
local Players = game:GetService("Players")
local GroupId = 111111
--// Call this function whenever you want to give the player XP
local function AwardXP(Player)
local PlayerRank: number = Player:GetRankInGroup(GroupId)
local PlayerTeam: Team = Player.Team
local XPAmount: number --// We fill this in with the amount of XP you want to give them
if PlayerTeam.Name == "Team1" then
if PlayerRank == 1 then
XPAmount = 5
elseif PlayerRank == 5 then
XPAmount = 12
elseif PlayerRank == 10 then
XPAmount == 40
end
elseif PlayerTeam.Name == "Team2" then
if PlayerRank == 1 then
XPAmount = 2
elseif PlayerRank == 5 then
XPAmount = 19
elseif PlayerRank == 10 then
XPAmount == 33
end
elseif PlayerTeam.Name == "Team3" then
if PlayerRank == 1 then
XPAmount = 7
elseif PlayerRank == 5 then
XPAmount = 8
elseif PlayerRank == 10 then
XPAmount == 59
end
end
if XPAmount then
--// Then you can do something with the XPAmount (prevents an error from occurring if they don't have a rank associated with the team, in which case XPAmount is never set and remains nil)
else
print("Player does not have a rank associated with the team")
end
end
You see this approach a lot, but it’s really tedious to maintain and update. It’s also a mess. A better approach is method 2 (tables) and this scales with modules.
Method 2 - Tables
--// Run from a server script, not a local script
local Players = game:GetService("Players")
local GroupId = 111111
--// Format goes [TeamName] = {[PlayerRank] = AmountOfXP}, etc.}
local TeamXPSettings = {
["Team1"] = { --// XP settings for Team1
[1] = 5, --// If they have the rank value of 1, they get 5 XP, etc.
[5] = 12,
[10] = 40,
},
["Team2"] = {
[1] = 2, --// If they have the rank value of 1, they get 2 XP, etc.
[5] = 19,
[10] = 33,
},
["Team3"] = {
[1] = 7, --// If they have the rank value of 1, they get 7 XP, etc.
[5] = 8,
[10] = 59,
},
}
--// Call this function whenever you want to give the player XP
local function AwardXP(Player)
local PlayerRank: number = Player:GetRankInGroup(GroupId)
local PlayerTeam: Team = Player.Team
local XPAmount: number = TeamXPSettings[PlayerTeam.Name][PlayerRank]
if XPAmount then
--// Then you can do something with the XPAmount (prevents an error from occurring if they don't have a rank associated with the team, in which case XPAmount is never set and remains nil)
else
print("Player does not have a rank associated with the team")
end
end
As you can see, method 2 is way more clear and easy to maintain. If you wanted to use a modular set-up, it would work basically the same way, since modules are just tables. I won’t get into that here, but that’s a great next step and there are lots of great tutorials on modules on the DevForum.
One thing to note about this approach, is that it’s important that you set up the table completely. As it stands, it’s possible for my function to error if the player is on a team that isn’t registered in TeamXPSettings
because it would try to index the team name, get a nil value (which isn’t inherently problematic), and then attempt to index the nil value (which is problematic and would throw an error). That’s not to say method 2 is worse or riskier, just that it requires attention to detail. You can also always build in a check like
Check
local TeamExists = TeamXPSettings[PlayerTeam.Name]
if TeamExists then
XPAmount = TeamXPSettings[PlayerTeam.Name][PlayerRank]
else
print("Oops - forgot to add a configuration for", PlayerTeam.Name)
end
To preempt a question you might have, you can also make an automated XP system like this
Method 2 automated
--// Run from a server script, not a local script
local Players = game:GetService("Players")
local GroupId = 111111
local WaitTime = 120 --// The time, in seconds, that you want to wait
--// Format goes [TeamName] = {[PlayerRank] = AmountOfXP}, etc.}
local TeamXPSettings = {
["Team1"] = { --// XP settings for Team1
[1] = 5, --// If they have the rank value of 1, they get 5 XP, etc.
[5] = 12,
[10] = 40,
},
["Team2"] = {
[1] = 2, --// If they have the rank value of 1, they get 2 XP, etc.
[5] = 19,
[10] = 33,
},
["Team3"] = {
[1] = 7, --// If they have the rank value of 1, they get 7 XP, etc.
[5] = 8,
[10] = 59,
},
}
--// Call this function whenever you want to give the player XP
local function AwardXP(Player)
local PlayerRank: number = Player:GetRankInGroup(GroupId)
local PlayerTeam: Team = Player.Team
local XPAmount: number = TeamXPSettings[PlayerTeam.Name][PlayerRank]
if XPAmount then
--// Then you can do something with the XPAmount (prevents an error from occurring if they don't have a rank associated with the team, in which case XPAmount is never set and remains nil)
else
print("Player does not have a rank associated with the team")
end
end
--// The function that will give players XP over time
local function HandleXP(Player)
while Players:FindFirstChild(Player) do --// Checks that the Player is still playing
task.wait(WaitTime)
AwardXP(Player)
end
end
--// Handle player xp when players join
Players.PlayerAdded:Connect(function(Player)
HandleXP(Player)
end)
--// Handle player xp for any players who joined before the code runs
for _, Player in pairs (Players:GetPlayers()) do
HandleXP(Player)
end
Hope that clears up how you can start thinking about going about this. This isn’t meant to be an all-inclusive tutorial, but I was aiming to giving you a basic idea of different methods to go about this, visually show why a table-based approach is preferable, and hit on ways to award XP manually and automatically (both just use the AwardXP
function). Sorry in advance if there’s any typos, this was all written on Notepad++.
API references
- Players (this is the service)
- Player (this is the actual player instance)
- Player:GetRankInGroup
- Player.Team
Sorry if I was a bit confusing, when I said ranks I meant each individual team would have different ranks that you could earn (for example, let’s say there’s a researcher team, with the lowest rank being Intern and the highest being Head of Research). I’d still image your could use a system similar to this, no?
Yeah, same idea. You’re just going to need to modify the PlayerRank
variable I was using and the table structure to facilitate that. It’s the same basic concept though!
How would you recommend going about structuring PlayerRank
?
It really just depends on the specifics of your project.
If you are trying to save rank, then just save the value and retrieve it as needed (that’s pretty much just a 1:1 swap for the way PlayerRank
is currently configured).
If you plan to make rank reset each time so that players can grind it out, I would just recommend checking each time you add XP to see if player’s hit some minimum amount of XP, and then adjust their rank accordingly. You could set up a big table for each player and record their rank like
local Table = {
[https_KingPie] = "Rank 1",
[AnotherPlayerName] = "Rank 2",
--// etc
}
Then, just pull their rank out whenever you add XP and give them the amount of XP designated for each rank. Once they hit the minimum amount of XP for the next rank, just adjust their rank ex:
Table[https_KingPie] = "Rank 2"
Hope that clarifies things. I want to avoid being too specific, since a lot will just depend on the nature of your project. If you want to talk in more detail, feel free to hit me up on Discord
Alright, I sent over a friend request so we can hopefully talk a bit more in-depth. Edit: Discord Username is the same as my Roblox one.