I’m making a levelling system, and the way it works is rather simple:
Level 1 needs 100 EXP to level up, Level 2 needs 120 EXP to level up, Level 3 needs 140 EXP to level up, and so on. Basically adding an extra 20 EXP requirement each time.
Doing this is easy, but it gets complicated when you earn more exp than you need to level up, (e.g, earning 5000 exp but needing 160 to level up.
I’m trying to implement the same system as stated at the start but for when you are earning more EXP than you need. I have created a function made for this to show how many times the player should level up as shown:
function getUpgradeAmount(player)
local playerData = module.playerData[player]
local exp = playerData.Experience
local UpgradeAmount = 0
repeat
-- MaxExperience is just the current amount of exp needed to level up
exp -= playerData.MaxExperience + UpgradeAmount*20
if exp < 0 then
exp += playerData.MaxExperience + UpgradeAmount*20
break
end
UpgradeAmount += 1
until 1>2
return UpgradeAmount
end
My problem isn’t that this doesn’t work, it’s that it is EXTREMELY performance costly when you have to add higher experience amounts. An example of this is if you want to add for example 1,000,000,000,000 exp, this means the loop would have to run many times, and would be exhausted.
I’m trying to create this same function but without the use of any loops, so that its only math that is needed, and can be done within less than 4 lines of code (not specifically), which would be instant.
I get that this problem is likely unique, and is difficult to solve, but any help would be appreciated. Many Thanks.
I dont really think its gonna be performance expensive. Every time the loop runs the players earns a level, this means that if it were not performant then the player would level millions of times which to be honest they shouldnt be called levels at that point.
It might be expensive for the 1 trillion but when is the player even even getting 1 billion in the game? I doubt they would get that much exp at once.
You actually don’t need a repeart or whatever, what you can just do is, get a Value that is an Instance and basically implent Changed or PropertyChandSignal. In there you do just checks, it will go automatically. So like if you remove from 5000 -160, it goes to 4840. Since it changed it goes again, so -180. You understand?
You can’t just do math, as you need to add 20 to its exp which is not possible on a fixed line. Math in a programming language can’t be changed without a loop? Even though, no it will not exhaust. Just a put a wait, I don’t know where you got that from, but this isn’t looping all game and even though will not lag you?
You are right, but you brought me to another idea. I just realised that he isn’t using any wait function to let the script rest, that why he thinks it is high perfomance cost which is normally not.
The following function behaves in the exact same way of your old one, but without the loop:
local function getUpgradeAmount(player: Player): number
local playerData = module.playerData[player]
--parameters
local x = 20
local y = playerData.MaxExperience
local z = playerData.Experience
--calculate positive quadratic root
local root = math.sqrt(x*x+4*y*y+8*x*z-4*x*y)/(2*x)-y/x
return math.round(root)
end
The idea is that once I kill an enemy, then that function fires once. But when there is too much EXP, the loop runs too many times and exhausts, however if I put a wait then it would take far too long to level up when you are a higher level.
After a while I basically gave up and decided to change the system to something I’m much more happy with, although I do appreciate the help.
(If you need to know I essentially removed the max exp feature entirely, and instead just made it fixed at 100 per level, that way I don’t have to worry about level scaling)
You can recognize your experience required per level as a simple linear mathematical function: f(x) = 100 + i(x - 1) where x is current experience and i is experience requirement increment, such that i is constant. If you store total experience instead of levels, calculating the current level and remaining experience until the next level will be a constant time operation. If you want to keep track of the level instead of total experience and keep remaining experience in another variable for, you may also do that by getting the inverse of the function f^-1(x) = (x - 100)/i + 1 for calculating total current experience by level in constant time, add the gained experience, and then convert it back using the former function in constant time through composition
With those functions, you may calculate a player’s level in constant time or add to their level in constant time. I only provided the inverse of the total experience function but there is most definitely something better for adding to levels without calculating total experience in the first place, although I recommend saving total experience just to make everything easier
Don’t give up, @mynameisjeb2018, @FastTron’s reply is exactly what you’re looking for. I do the same thing where I only store the total XP that a player has earned which makes everything insanely easier than the alternative. My function is quadratic instead of linear, but that’s only because my levels have different requirements from yours:
Level 1 - Gain 100 XP (100 XP total)
Level 2 - Gain 200 XP (300 XP total)
Level 3 - Gain 300 XP (600 XP total)
Level 4 - Gain 400 XP (1000 XP total)
Code
local PlayerLevel = {
level = function(xp: number) -- The level of a player as a function of xp.
return math.floor(math.sqrt((xp + 12.5) / 50) - .5)
end,
minimumXPForLevel = function(level: number) -- Returns the total xp of a level.
return 50*level^2 + 50*level
end
}