local replicatedStorage = game:GetService("ReplicatedStorage")
local getDataFunction = replicatedStorage:WaitForChild("GetData")
local playerData = {}
local gui = script.Parent
local LevelLabel = gui.Level
local BarBG = gui.BarBG
local Bar = BarBG.Bar
local Exp = BarBG.Exp
function updateLevel()
LevelLabel.Text = "Level "..playerData.Level
Exp.Text = playerData.Exp.."/"..playerData.ExpNeeded
if playerData.Exp >= playerData.ExpNeeded then
playerData.Level += 1
playerData.ExpNeeded = playerData.Level * 250
playerData.Exp = playerData.Exp - playerData.ExpNeeded
end
if playerData.Level == 100 then
playerData.Exp = "Max Level"
else
Bar:TweenSize(UDim2.new((playerData.Exp/playerData.ExpNeeded),0,1,0),"Out","Quint",0.3,true)
end
end
if LevelLabel.Visible == true then
playerData = getDataFunction:InvokeServer()
updateLevel()
end
all data is stored inside a table in datastore script so ignore the empty table at the top but anyways when im getting exp and its value is >= expneeded my level doesnt go up but the exp value will be for example 400/250 instead of increasing the level and exp needed
I wouldn’t recommend putting it in a while loop since you would send a lot of requests to the server which is unnecessary. Instead, you should invoke the server once at the start of the script and then whenever you want to update the level just send a remote event from the server to update the client.
local PlayerData = -- Invoke Server
local function Update(data)
if not PlayerData then return end -- Player data didn't load in time
-- You could yield until there is data by using repeat
end
Update()
-- Sent from the server to update client
RemoteEvent.OnClientEvent:Connect(Update)
It would still be unnecessary since you would still be requesting data for no reason especially if you request when the data hasn’t even changed. It would be better to invoke server once.
local replicatedStorage = game:GetService("ReplicatedStorage")
local getDataFunction = replicatedStorage:WaitForChild("GetData")
local LevelEvent = replicatedStorage.Remotes:WaitForChild("LevelUp")
local playerData = {}
local gui = script.Parent
local LevelLabel = gui.Level
local BarBG = gui.BarBG
local Bar = BarBG.Bar
local Exp = BarBG.Exp
playerData = getDataFunction:InvokeServer()
local function updateLevel()
if not playerData then return end
LevelLabel.Text = "Level "..playerData.Level
Exp.Text = playerData.Exp.."/"..playerData.ExpNeeded
if playerData.Exp >= playerData.ExpNeeded then
playerData.Level += 1
playerData.ExpNeeded = playerData.Level * 250
playerData.Exp = playerData.Exp - playerData.ExpNeeded
end
if playerData.Level == 100 then
playerData.Exp = "Max Level"
else
Bar:TweenSize(UDim2.new((playerData.Exp/playerData.ExpNeeded),0,1,0),"Out","Quint",0.3,true)
end
end
updateLevel()
LevelEvent.OnClientEvent:Connect(updateLevel)
The issue here is not really updating the data since you telling it to update but it’s still using the invoked data from the start of the script. In the remote you should send the updated data and send it through the function.
Also should probably handle it on the server instead of the client, simply use the client as a visual.
local PlayerData = {EXP = 0, LVL = 1}
local XP_NEEDED_PER_LVL= 50
local function GiveEXP(player: Player, amount: number)
PlayerData.EXP += amount
if PlayerData.EXP >= XP_NEEDED_PER_LVL then
PlayerData.LVL += 1
PlayerData.EXP -= XP_NEED_PER_LVL
end
-- Send Remote
RemoteEvent:FireClient(player, PlayerData)
end
Something like this ofc this is a very basic version but this is on the server and it’s pretty simple.
I updated my previous reply with a script on how the server could look, PlayerData would just be how you stored your data so you would need to fit that into your system but that’s a rough idea of how it could work. Hope that helps
I would handle the levels inside a dictionary instead of just a table for each level then check the players level int and see if matches with any of the dictionaries…
So like this for example local levels = { [1] = {1, "Noob"} } -- New level amount and the rank title
To save less data I would personally have an XP module which has all the info about that level like this.
-- XP Module
return {
[1] = { -- Index would be the level
RequiredXP = 500, -- How much XP is required
Title = "Noob" -- Other things like titles
},
}
Now all we have to save is the XP they have so
local Data = {XP = 510}
local PlayerLevel = 1
for Level: number, Info: table in pairs(XPModule) do
if Info.RequiredXP >= Data.XP and Level > PlayerLevel then
PlayerLevel = Level
end
end
Of course, for ease, you can save the level directly but I would still have a module where all the info about that certain level is stored. Every time the xp is updated check that table and see what they get for that level.
Thats exactly how id do it basically, Just I would have the server edit their level and rank and then save it on exit, I just feel like its easier that way
Why are you using too much requests on the server??
This will not send any requests and will detect when xp has changed, if it has changed we check if it’s equal to the requirement xp, if it is then the Player gets their level.
XP:GetPropertyChangedSignal("Value"):Connect(function()
if Player.StatsFolder.XP.Value >= Player.StatsFolder.RequiredXP.Value then
Player.StatsFolder.Level.Value += 1
Player.StatsFolder.XP.Value = 0
Player.StatsFolder.RequiredXP.Value = Player.StatsFolder.Level.Value * 100
end
end)