User Leveling System

I've already asked this before, but I just wanna encode this again with a new leveling format. What I want to do is that, the user will gain exp and once they leveled up, their previous experience will be added to their current exp.

So, to put it in a Scenario it goes like this: User1 is on a Level 1 with an exp_needed of 1000 to reach level 2. He gained an exp of 1000, so he is now on level 2 with a current_exp of 1000 and an exp needed of 1,400. Or if User1 gained an exp of 1,100 he is on level 2 with a current_exp of 1,100 and 1,400 exp needed. And so on, depending on the algorithm. But I get a result of -900/1,400 if the user gains 1,100 exp.

Here is the code below:

while($user->curr_exp >=$user->exp_needed){
$user->curr_exp -= ($user->exp_needed) + $user->prev_exp;$user->prev_exp = $user->exp_needed; if($user->level <= 19){
$user->exp_needed =$user->prev_exp * 1.4;
}
elseif($user->level >= 20 &&$user->level <= 39){
$user->exp_needed =$user->prev_exp * 1.1;
}
elseif($user->level >= 40 &&$user->level <= 59){
$user->exp_needed =$user->prev_exp * 1.05;
}
elseif($user->level >= 60 &&$user->level <= 79){
$user->exp_needed =$user->prev_exp * 1.04;
}
elseif($user->level >= 80 &&$user->level <= 99){
$user->exp_needed =$user->prev_exp * 1.03;
}
elseif($user->level == 100){$user->exp_needed = $user->exp_needed * 0; }$user->level += 1;
$user->save(); }  Any ideas how to deal with this? Thanks. • What exactly does store each of your variables? – trollingchar May 16 '19 at 6:10 • curr_exp is the exp of the user, exp_needed is the exp needed to reach next level, previous exp is the exp from their previous levels – John Carlo May 16 '19 at 6:37 2 Answers I think your levelling system in unnecessarily complicated because it makes the levelling's thresholds dependent on the player's current exp. First, I propose to set fixed levelling thresholds, that you decide beforehand. For example, the first 20 levels need 1000 exp, 1400 exp, 1960 exp ... and so on. You can save them on an array for example. Now suppose the player is at level 1, with 100 exp, and needs 900 exp to get to level 2. He gains 1000 exp, and now he is at 1100 exp, so it's promoted to level 2. The threshold for achieving level 3 is set to 1400, for example. You can proceed in two ways: 1. Keep his current exp to 1100, so now he will need only an additional 1300 to get to 1000+1400=2400 exp. 2. Reset his exp to 0, and now he needs to reach 1400 exp to get to level 3. The second solution has the disadvantage that you lose track of the actual total exp the player made because you are throwing away any additional exp he gained when levelling up. For that, you can use a second variable curr_total_exp which is never reset. • Technically you don't lose Total Exp. You can reconstruct it from the players level. This assumes you aren't interested in keeping xp once the player caps out though. Either way works though. – user2927848 May 16 '19 at 20:16 • @user2927848: But if you adjust the level requirements in a later patch, this does make a difference because you can't reverse engineer it anymore. It depends what you want to happen when said patch hits: should the player retain the level they had achieved pre-patch, or should their level be recalculated (this can be positive or negative, so it's not a matter of one option being objectively worse than the other). – Flater Jun 17 '19 at 11:19 100 level is max so we add a check to prevent infinite loop. while ($user->curr_exp >= $user->exp_needed &&$user->level < 100) {


Subtract only XP needed to level-up:

    $user->curr_exp -=$user->exp_needed;


Add XP from this level to previous XP:

    $user->prev_exp +=$user->exp_needed;

if ($user->level < 20) {$user->exp_needed = $user->prev_exp * 1.4; }  if level less then 20 we don't need to check if it's greater or equal because we have else  elseif ($user->level < 40) {
$user->exp_needed *= 1.1; } elseif ($user->level < 60) {
$user->exp_needed *= 1.05; } elseif ($user->level < 80) {
$user->exp_needed *= 1.04; } elseif ($user->level < 100) {
$user->exp_needed *= 1.03; } else {$user->exp_needed = 0;
}
$user->level += 1;$user->save();
}


We do not modify exp_needed based on prev_exp because we want a predictable exponential sequence:
1000, 1400, 1960, 2744...