What do you want to achieve? I want to create a “Leveling System”
What is the issue? I tried doing setXP method myself but nothing worked, i don’t want to use a while loop because of performance issues (it also didn’t work as i expect it to).
What solutions have you tried so far? I tried looking for tutorials, and looked at other forum posts but i didn’t see what I was looking for.
“I don’t want the whole script, just the math behind predicting what level a player will achieve with the xp that will be set”
--The types
type class = {
__index: class,
--Base class
addPlayer: (player: Player, level: number, xp: number) -> object,
getPlayer: (player: Player) -> object?,
removePlayer: (player: Player) -> (),
getRequiredXP: (level: number) -> number,
--Object methods
getLevel: (self: object) -> number,
getXP: (self: object) -> number,
setLevel: (self: object, level: number, force: boolean?) -> (),
setXP: (self: object, xp: number) -> (),
}
export type object = typeof(setmetatable({} :: {
owner: Player,
level: number,
xp: number,
}, class :: class))
--THIS IS NOT THE WHOLE SCRIPT (i can post the whole script if anyone wants)
local XP_PER_LEVEL = 180
function class.getRequiredXP(level)
return (( level ^ 2 ) + (XP_PER_LEVEL * level) - (level ^ 2)) + 20
end
function class:setLevel(level, force)
if self.level == level then
return end
if self.level <= level and not force then
warn("Tried setting level below current level (no force)") end
local player = self.owner
local levelsGained = level - self.level
if levelsGained > 1 then
for i = self.level, level, 1 do
if not levelList[i] then continue end
levelList[i](self.owner) --Execute the OnLevelCompleted function
end
local requiredXP = class.getRequiredXP(level)
self.level = level
player:SetAttribute('level', level)
player:SetAttribute('requiredXP', requiredXP)
return
end
if levelList[level] then levelList[level](self.owner) end --Execute the OnLevelCompleted function
local requiredXP = class.getRequiredXP(level)
--Set the variables and attributes
self.level = level
player:SetAttribute('level', level)
player:SetAttribute('requiredXP', requiredXP)
end
function class:setXP(xp)
--This is where i have the problem
end
I believe a loop is required for this as the number of xp can surpass the required amount for numerous next levels. Preformance shouldnt be an issue here, if the amount of xp earned is low, the loop could only run about twice or so. If the xp earned is high, to the point where someone could earn 20 levels for it, I would add a small delay, task.wait(0.05) could be sufficient.
i would really prefer loops but i think this should work we can calculate the new level based on given xp and update it if it’s increased and set the new xp
function class:setXP(xp)
assert(xp >= 0, "Attempted to set negative XP")
local currentLevel = self.level
local currentTotalXP = 0
for i = 1, currentLevel do
currentTotalXP = currentTotalXP + class.getRequiredXP(i)
end
currentTotalXP = currentTotalXP + self.xp
if xp < currentTotalXP then
self.xp = xp - (currentTotalXP - self.xp)
self.owner:SetAttribute('xp', self.xp)
return
end
local newLevel = currentLevel
local newTotalXP = currentTotalXP
while newTotalXP + class.getRequiredXP(newLevel + 1) <= xp do
newLevel = newLevel + 1
newTotalXP = newTotalXP + class.getRequiredXP(newLevel)
end
if newLevel > currentLevel then
self:setLevel(newLevel)
end
self.xp = xp - newTotalXP
self.owner:SetAttribute('xp', self.xp)
end
Note that we can’t really avoid loops but i tried to avoid it as much as possible
Before I start I want to mention Im bad at explaining
If it’s for every new level you would need +100 exp to level up, you could use mx+b = y.
The math: Added Exp * Level + 0
If the exp increased by 100 and you were level 5 it would be 100*5 which is 500 exp required to get to level 6. If you were level 1 you would require 100 exp to reach lvl 2.
The other approach is using exponential functions. Their form: y = s*a^x. Let’s say you wanted the exp needed to be double the previous, it would be like this: 100*2^(lvl-1). If you were lvl 1 it would be 100 exp required but if you were lvl 2 it would be 200.
I highly recommend you do some research on exponential and linear equations because I’m not the best at explaining
Using loops are less of a headache and should not cause performance issues at all for a simple calculation. If you are really trying to avoid loops, considering your getRequiredXP uses a formula to get the required experience only for that level, then you would need to get the summation of your equation.
Anyways, I’m not sure why your formula contains (level ^ 2) ... - (level ^ 2) since both of those will cancel out, so your formula just looks like: REQUIRED_EXPERIENCE = (EXPERIENCE_PER_LEVEL * level) + STARTING_REQUIRED_EXPERIENCE. (substituted 20 for STARTING_REQUIRED_EXPERIENCE)
Your formula contains a constant c (STARTING_REQUIRED_EXPERIENCE) and n^1 (level), the summation formulas are cn and (n^2+n)/2 respectively. Converting your function will become: