How to make an XP and level up system that saves and loads using the XP

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.

3 Likes

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;
    }
1 Like

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.

3 Likes

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.
image

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?

1 Like