Level system help (script)

Hello, I’m making my first level system, I’d like to have your opinion on the following script. When I add exp to a player, I check in a loop the amount of exp and evolve the level of the player until the exp is below the next level, in case of a big exp gain it allow the player to gain several level directly and not break the level system. I’d like to know if this is a good way to do it.

Second question , does add 100exp to reach new level seem to be a normal elevation system ?
(lvl 1-100xp , level2-200xp , level3-300xp, etc…)

--PLAYER FINISH A STAGE I GIVE HIM NEW XP ON SERVER
local currentExp = plr.Tout.currentExp
local plrLevel = plr.Tout.plrLevel
currentExp.Value = currentExp.Value + 200
plr.Tout.totalExp.Value = 	plr.Tout.totalExp.Value + 200

local loop = true
while loop do	
	local xpNeeded = plrLevel.Value*100
	if currentExp.Value < xpNeeded then
		loop = false
	else
		currentExp.Value -= xpNeeded
		plrLevel.Value+=1
	end
	task.wait()
end

Any help is apprecied thank you !

Sorry, I can’t help you for the first question but for the second question I suggest to create levels that are more difficult to rich like : Level 1 > 100xp / Level 2 > 250xp …

2 Likes

well the first thing i noticed is the way you’re looping

while true do	
	  local xpNeeded = plrLevel.Value*100
	if currentExp.Value < xpNeeded then
		break -- you can break a loop by doing 'break'
	else
		currentExp.Value -= xpNeeded
		plrLevel.Value+=1
	end
	task.wait()
end
local currentExp = plr.Tout.currentExp
local plrLevel = plr.Tout.plrLevel
-- a += b is the same as a = a + b, but shorter
currentExp.Value += 200
plr.Tout.totalExp.Value += 200

also instead of looping you could just do .Changed or :GetPropertyChangedSignal to update the value everytime it’s changed instead of looping constantly

currentExp:GetPropertyChangedSignal("Value"):Connect(function()
  local xpNeeded = plrLevel.Value * 100
  if currentExp.Value >= xpNeeded then
    currentExp.Value -= xpNeeded
    plrLevel.Value += 1 -- just noticed you already know what += does
  end
end)

making the xpNeeded get multiplied by 100 is fine but it’s better to make it harder to levelup the higher you go, like what @Pokejoueur_ytb suggested
level 1: 100xp
level 2: 250xp
level 3: 500xp
etc

2 Likes

Hi , yes my bad i don’t know why i didn’t do += 200, fatigue maybe lol, thanks for the correction.

I’m breaking the loop with loop = false, I deduced that this would be a better practice because it might be less “aggressive” for the server, knowing that this function is used regularly by the server, and gives the same result as break (maybe a microsecond delay).
I’ll think about modifying it.

The last function you send won’t be able to correct this problem, because if I suddenly give 2000 exp to the player when he’s level 1, he should be at level 5, for example, except that with this script this will only add 1 level to the player and therefore break the player’s level system (which will be corrected when the player joins, as I’ve added a safety feature). Also i prefer not to add unnecessary function to the server, as i can handle the level system without it

oh i see what you mean

currentExp:GetPropertyChangedSignal("Value"):Connect(function()
  local xpNeeded = plrLevel.Value * 100
  if currentExp.Value >= xpNeeded then
    repeat
      currentExp.Value -= xpNeeded
      plrLevel.Value += 1
    until currentExp.Value < xpNeeded
  end
end)
1 Like

Thanks , so it’s like exactly my script but with a repeat loop instead of a while loop. I can consider that i did a normal way

i would say the normal way is doing :GetPropertyChangedSignal("Value") instead of a while loop

I kinda disagree for my case i don’t need this extra function (that give extra work to the server) as i can handle the level system without it. But you’re may be true about the repeat that would be better than a while loop, i don’t know what’s the best for performance (as you may have noticed, all my scripts are organized around performance, to optimize it as much as possible)

looping constantly in the background just for a player’s level is the extra work

you only want to update the level when it’s being changed

local xpNeeded = plrLevel.Value*100
if currentExp >= xpNeeded then
	currentExp.Value -= xpNeeded
	plrLevel.Value+=1
	local NewxpNeeded = plrLevel.Value*100
	if currentExp.Value >= NewxpNeeded then
		repeat
			currentExp.Value -= NewxpNeeded
			plrLevel.Value+=1
			NewxpNeeded = plrLevel.Value*100
			task.wait()
		until currentExp.Value < NewxpNeeded
	end
end		

This seem like the best way to do it, thanks for you help

is this inside of a function or something?

this wouldn’t work by itself

yes it’s in a function when player receive exp

local ShouldStopRound = false
rs.ClientEvents.EndingTower.OnServerEvent:Connect(function(plr)
	local char = plr.Character
	if char and table.find(plrWin, plr.Name) == nil then	
		table.insert(plrWin, plr.Name)
		time_wait_before_loop = time_wait_before_loop / 2
		rs.Value.TimeMulti.Value = #plrWin *2
		rs.ClientEvents.Multiplicateur:FireAllClients()	
		
		local currentExp = plr.Tout.currentExp
		local plrLevel = plr.Tout.plrLevel
		currentExp.Value += 200
		plr.Tout.totalExp.Value += 200
		
		local xpNeeded = plrLevel.Value*100
		if currentExp >= xpNeeded then
			currentExp.Value -= xpNeeded
			plrLevel.Value+=1
			local NewxpNeeded = plrLevel.Value*100
			if currentExp.Value >= NewxpNeeded then
				repeat
					currentExp.Value -= NewxpNeeded
					plrLevel.Value+=1
					NewxpNeeded = plrLevel.Value*100
					task.wait()
				until currentExp.Value < NewxpNeeded
			end
		end
		
		if #plrWin == #Players:GetPlayers() then
			ShouldStopRound = true
		end
	else
		rs.ClientEvents.EndingTower:FireClient(plr)
		plr.Tout.ExploitCheck.Value += 1 
		if plr.Tout.ExploitCheck.Value >= 5 then
			plr:Kick('Hi , the server has some issue, it may be a latency or an exploit, in that second case please do not exploit in this game by respect to the other players') 
		end
	end
end)
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.