I have already set up a datastore module however I’m extremely confused on how to make an xp and leveling system. I want to load in the player’s level by the amount of xp they have but im not sure how to do this.
You will have to make up your own system for calculating what level the player should be, and then just implement that equation. All games do this differently.
For example, the game Runescape implements the following function to calculate the experience needed for a given level to gradually scale up the amount of experience required to reach level 99 (This snippet is written in C)
public int getExperienceForLevel(int level) {
int points = 0;
int output = 0;
for (int lvl = 1; lvl <= level; lvl++) {
points += Math.floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0));
if (lvl >= level) {
return output;
}
output = (int)Math.floor(points / 4);
}
return 0;
}
Just use the player’s total experience as the input to some sort of a formula that returns a corresponding level. Usage of the floor
function, which rounds a number down to its nearest integer, will help greatly. This also avoids unnessecary loops that could cause delays.
Here’s a super simple function that has a linear scaling, meaning that levels are equidistant:
function currentLevel(x)
return math.floor(x / 10) + 1 -- Every level requires an additional 10 XP
end
Note the + 1
term on the end, which ensures the minimum level for our player is always 1, assuming x is positive.
Another, that requires experience at a polynomial rate, meaning that additional levels require more experience:
function currentLevelPolynomial(x)
return math.floor(x^(1/2)) + 1
end
desmos.com is a great website to help you mess around.
I see but im confused on how to implement this into my code:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage.Events
local Manager = {}
Manager.Profiles = {}
function Manager.AdjustLevel(player: Player, amount: number)
local profile = Manager.Profiles[player]
if not profile then return end
profile.Data.Level += amount
player.leaderstats.Level.Value = profile.Data.Level
Remotes.UpdateLevel:FireClient(player, profile.Data.Level)
end
function Manager.AdjustXp(player: Player, amount: number)
local profile = Manager.Profiles[player]
if not profile then return end
profile.Data.Xp += amount
player.leaderstats.Xp.Value = profile.Data.Xp
Remotes.UpdateXp:FireClient(player, profile.Data.Xp)
end
local function GetData(player: Player, directory: string)
local profile = Manager.Profiles[player]
if not profile then return end
return profile.Data[directory]
end
local function GetAllData(player: Player)
local profile = Manager.Profiles[player]
if not profile then return end
return profile.Data
end
Remotes.GetData.OnServerInvoke = GetData
Remotes.GetAllData.OnServerInvoke = GetAllData
local function UpdateCurrency(currency: "Credits" | "Xp", amount: number)
if currency == "Credits" then
Coins.Text = amount
elseif currency == "Xp" then
--LevelsFrame.Fill:TweenSize(UDim2.new(amount/CalculateXp(StateManager:GetData().Level), 0,1, 0))
elseif currency == "Level" then
LevelsFrame.LevelLabel.Text = "Level "..amount
end
end
UpdateCurrency("Credits", StateManager.GetData().Credits)
UpdateCurrency("Level", StateManager.GetData().Level)
UpdateCurrency("Xp", StateManager.GetData().Xp)
Remotes.UpdateCredits.OnClientEvent:Connect(function(amount)
UpdateCurrency("Credits", amount)
end)
Remotes.UpdateLevel.OnClientEvent:Connect(function(amount)
UpdateCurrency("Level", amount)
end)
Remotes.UpdateXp.OnClientEvent:Connect(function(amount)
UpdateCurrency("Xp", amount)
end)
Get the Xp value, run through this algorithm output is Level.
local player = game.Players.LocalPlayer
local currentEXP = 0
local expNeeded = {
100, 200, 400, 800, 1600
}
local function calculateLevel(exp)
local level = 1
while exp >= expNeeded[level] and expNeeded[level] do
exp = exp - expNeeded[level]
level = level + 1
end
return level
end
local function giveEXP(amount)
currentEXP = currentEXP + amount
local currentLevel = calculateLevel(currentEXP)
print("Current Level: " .. currentLevel)
end
giveEXP(300)
Left the print in so you could check it yourself.
And here is a module version named xpl …
-- ServerScript (main script)
local xpl = require(script.xpl)
local level = 0
local Xp = 300
level = xpl.getLevel(Xp)
print(level)
-- ModuleScript inside main script. Script name is xpl.
local expNeeded = {
100, 200, 400, 800, 1600
}
local currentEXP = 0
function calculateLevel(exp)
local level = 1
while exp >= expNeeded[level] and expNeeded[level] do
exp = exp - expNeeded[level]
level = level + 1
end
return level
end
local Module = {}
function Module.getLevel(amount)
currentEXP = currentEXP + amount
return calculateLevel(currentEXP)
end
return Module
I used your code to get started but Im stuck on some issues.
local function CalculateRequiredXp(level)
local xp = (1500 * level / 2) * 3
return xp
end
for i = 1, 100, 1 do
table.insert(XpRequired, CalculateRequiredXp(i))
end
local function CalculateLevel(xp)
local level = 1
while xp >= XpRequired[level] and XpRequired[level] do
xp = xp - XpRequired[level]
level = level + 1
end
return level
end
local function UpdateCurrency(currency: "Credits" | "Xp" | "Level", amount: number)
if currency == "Credits" then
Coins.Text = amount
elseif currency == "Xp" then
local Level = CalculateLevel(amount)
UpdateCurrency("Level", Level)
LevelsFrame.Fill:TweenSize(UDim2.new(amount/XpRequired[StateManager.GetData().Level], 0,1, 0))
elseif currency == "Level" then
LevelsFrame.LevelLabel.Text = "Level "..amount
Remotes.LevelUp:FireServer(amount)
end
end
Line 28 is while xp >= XpRequired[level] and XpRequired[level] do
level can’t be 0, local xpl = require(script.xpl) has to be the name you made the ModuleScript
make sure xp is at least defined
local xp = 0
I have done it a bit differently its all in a local script here but i dont quite understand why this error is happening. Also why are you substracting?