Using Tables and GetPropertyChangedSignalValue

Im trying to make my own level gui (cause i dont want it in the leaderstats). When a play hits 20XP they get to level 2 and then for level 3 its30xp ect.

Heres the script:

theLvlValues = {}

theLvlValues[1] = 20

theLvlValues[2] = 30

local lvl = script.Parent.Parent.Parent:WaitForChild("Level"):WaitForChild("XP")

local lvlNum = script.Parent.Parent.Parent:WaitForChild("Level"):WaitForChild("Lvl")

local lvlDisplay = script.Parent.TextLabel

lvl:GetPropertyChangedSignal("Value"):Connect(function()

if lvl >= theLvlValues[1] then

lvlNum.Value = lvlNum.Value + 1

lvlDisplay.Text = ("Level "..lvlNum.." ")

end

end)

Is this a proper way to use Tables? And i also got an error saying:
`

[15:05:37.544 - Players.iSkepticalBoi.PlayerGui.Level.XP:9: attempt to compare number with userdata]

`

To fix the error, which I assume is from the if-statement, then you change it to:

if lvl.Value >= theLvlValues[1] then

You’re comparing a object to a number, so you need to compare two numbers instead, so you do .Value.

Also, it seems like you want it so it’s 10 X the level value for XP because level 2 x 10 XP is the 20 XP you want so you don’t need to do a table and you can rather have a function to do the work for you.

You can have a variable called XP_Needed and have that be the Level * 10 so that will be what the player needs. You also never want to do this on the client because people, including hackers, can manipulate their levels. You want to have a Server script handling the leveling process and having the Client detect when the level value in the player is changed and to update a TextLabel or animating an XP bar.

I’m not going to code the whole thing for you but this is somewhat how it should be structured.

--[[ Server script creates the IntValue inside the player (so it doesn't become
inside of the leaderstats folder and on the leaderboard gui) and then it detects
when the XP has reached a certain amount (10 * Level value) and then it will increment
the level value by 1. You should also make it carry over the XP (e.g XP 70/100
and you earn 50 XP so it should make you the next level with 20/100 XP) so to do this
you should just do modulus of the XP needed for the next level and add that to the
XP.
--]]

game.Players.PlayerAdded:Connect(function(player)
    local XP_Value = Instance.new('IntValue')
    XP_Value.Name = 'XP_Value'
    XP_Value.Parent = player

    local XP_NEEDED = Instance.new('IntValue')
    XP_NEEDED.Name = 'XP_Needed'
    XP_NEEDED.Parent = player

    local LEVEL = Instance.new('IntValue')
    LEVEL.Name = 'Level'
    LEVEL.Parent = player

    -- do your datastore stuff so if they have data set XP_NEEDED to level * 10

    XP_Value:GetPropertyChangedSignal('Value'):Connect(function()
        if XP_Value.Value >= XP_NEEDED then
         -- do your level stuff here
       end 
    end
end)
--[[ Client script updates the leaderstats when it is changed and changes text/animates
the XP bar
]]-

local player = game:GetService('Players').LocalPlayer
local XP_Value, LVL,Value = player:WaitForChild('XP'), player:WaitForChild('Level')
local XP_Needed = player:WaitForChild('XP_Needed')

XP_Value:GetPropertyChangedSignal('Value'):Connect(function()
    XP_Label.Text = XP_Value.Value .. "/" .. XP_NEEDED
end)
2 Likes

there’s an easier way to determine if a player has enough exp

lvl:GetPropertyChangedSignal("Value"):Connect(function()
    if lvl >= lvlNum*10+10 then
        lvlNum.Value = lvlNum.Value + 1
    end
end)

this ensures that if the exp is at the exp required level e.g. 3 to be the currentlevel which is atm 2 to be 2*10 = 20 + 10 = 30 and so on will it work for other levels. this is just to ease the way you make a level up system. instead of giving solid Exp values use a calculation.

is the second code part suppose to be a local script?

Yes, you should always (in most cases) use local scripts for when you’re dabbling around with the client.

The second code is meant to be in a local script, while the first one is meant to be a server script in ServerScriptService.

I have to identify what XP_Needed per level by using Do Math?

No, you just get the level and multiply it by 10 in your case. NEVER trust the client so you do this on the server in a server script.

When the level is changed in the server script shown above, you make the XP_needed set to the new level value * 10.

i improved it. is this the way to do it?
sorry if im a bother.

--[[ Server script creates the IntValue inside the player (so it doesn't become
inside of the leaderstats folder and on the leaderboard gui) and then it detects
when the XP has reached a certain amount (10 * Level value) and then it will increment
the level value by 1. You should also make it carry over the XP (e.g XP 70/100
and you earn 50 XP so it should make you the next level with 20/100 XP) so to do this
you should just do modulus of the XP needed for the next level and add that to the
XP.
--]]

game.Players.PlayerAdded:Connect(function(player)
    local XP_Value = Instance.new('IntValue')
    XP_Value.Name = 'XP_Value'
    XP_Value.Parent = player
	XP_Value.Value = 0
	
	local TOTAL_XP = Instance.new('IntValue')
	TOTAL_XP.Name = 'Total_XP'
	TOTAL_XP.Parent = player
	TOTAL_XP.Value = 0

    local XP_NEEDED = Instance.new('IntValue')
    XP_NEEDED.Name = 'XP_Needed'
    XP_NEEDED.Parent = player
	XP_NEEDED.Value = 50

    local LEVEL = Instance.new('IntValue')
    LEVEL.Name = 'Level'
    LEVEL.Parent = player
	LEVEL.Value = 1
    -- do your datastore stuff so if they have data set XP_NEEDED to level * 10

    XP_Value:GetPropertyChangedSignal('Value'):Connect(function()
        if XP_Value.Value >= XP_NEEDED then
		TOTAL_XP.Value = XP_Value.Value + TOTAL_XP.Value
         XP_Value.Value = XP_Value.Value - XP_NEEDED
		LEVEL.Value = LEVEL.Value + 1
		 XP_NEEDED.Value = XP_NEEDED.Value * 10								-- do your level stuff here
		      end 
		end)
    end)

Uh, not sure because I can’t really visualize it without testing it.

Try testing it out and seeing if it works as expected.

This is somewhat how it should look (inside the GetPropertyChangedSignal)


local XP_REMAINING

if XP_Value.Value >= XP_NEEDED then
    XP_REMAINING = XP_VALUE.Value % XP_NEEDED.Value
    XP_Value.Value = XP_REMAINING
    LEVEL.Value = LEVEL.Value + 1
    XP_NEEDED.Value = (LEVEL.Value * 10)
end

Getpropertychangedsignal should be in the playersadded function?

Yes just like what you posted above but I made some modifications to it.

The Text Label isnt updating on Join. It just says nil/nil (which what the base text is)

--[[ Client script updates the leaderstats when it is changed and changes text/animates

    the XP bar

    --]]

    local player = game:GetService('Players').LocalPlayer

    local XP_Label = script.Parent.Progress

    local XP_Value, LVL,Value = player:WaitForChild('XP'), player:WaitForChild('Level')

    local XP_Needed = player:WaitForChild('XP_Needed')

    XP_Value:GetPropertyChangedSignal('Value'):Connect(function()

    XP_Label.Text = (""..XP_Value.Value.. "/"..XP_Needed.Value.."")

    end)

Add the code that changes the text outside of the GetPropertyChangedSignal so that updates on initial join and updates when the value changes.

XP_Label.Text = (""..XP_Value.Value.. "/"..XP_Needed.Value.."")

XP_Value:GetPropertyChangedSignal('Value'):Connect(function()
    XP_Label.Text = (""..XP_Value.Value.. "/"..XP_Needed.Value.."")
end)

Weird… it dosent even update the text on join hmmm.

Is it erroring?

It’s probably running before the server script can create the values for XP and XP needed. Try doing :WaitForChild().

local player = game:GetService('Players').LocalPlayer
local XP_Value = player:WaitForChild('XP')

it shows the xp but not remaining or the total.
MainScript:
> game.Players.PlayerAdded:Connect(function(player)

                   local XP_Value = Instance.new('IntValue')
                    XP_Value.Name = 'XP_Value'
                XP_Value.Parent = player
            	XP_Value.Value = 0
        	     	local TOTAL_XP = Instance.new('IntValue')
        	TOTAL_XP.Name = 'Total_XP'
        	TOTAL_XP.Parent = player
        	TOTAL_XP.Value = 0
            local XP_NEEDED = Instance.new('IntValue')
            XP_NEEDED.Name = 'XP_Needed'
            XP_NEEDED.Parent = player
        	XP_NEEDED.Value = 50	

            local LEVEL = Instance.new('IntValue')
            LEVEL.Name = 'Level'
            LEVEL.Parent = player
        	LEVEL.Value = 1
        	
        	local XP_REMAINING = Instance.new('IntValue')
        	XP_REMAINING.Name = 'XP_Remaining'
        	XP_REMAINING.Parent = player
        	XP_REMAINING.Value = 0		
          			-- do your datastore stuff so if they have data set XP_NEEDED to level * 10
        	
            XP_Value:GetPropertyChangedSignal('Value'):Connect(function()
                if XP_Value.Value >= XP_NEEDED.Value then
        		XP_REMAINING = XP_Value.Value % XP_NEEDED.Value
        		TOTAL_XP.Value = XP_Value.Value + TOTAL_XP.Value
                XP_Value.Value = XP_Value.Value - XP_NEEDED.Value
        		LEVEL.Value = LEVEL.Value + 1
        		 XP_NEEDED.Value = (LEVEL.Value *10)							-- do your level stuff here
        		      end 
        		end)
            end)

Local script:

--[[ Client script updates the leaderstats when it is changed and changes text/animates

the XP bar

--]]

    local player = game:GetService('Players').LocalPlayer

    local XP_Label = script.Parent:WaitForChild("Progress")

    local Level = script.Parent:WaitForChild("TextLabel")

    local xpRemain = script.Parent:WaitForChild("RemainingXp")

    local xpTotal = script.Parent:WaitForChild("TotalXp")

    local XP_Value, LVL,Value = player:WaitForChild('XP_Value'), player:WaitForChild('Level')

    local XP_Needed = player:WaitForChild('XP_Needed')

    local XP_Remaining = player:WaitForChild('XP_Remaining')

    local XP_Total = player:WaitForChild('Total_XP')

    XP_Label.Text = (""..XP_Value.Value.. "/"..XP_Needed.Value.."")

    Level.Text = ("Level "..LVL.Value.."")

    xpRemain.Text = (""..XP_Remaining.Value.." XP Left")

    xpTotal.Text = ("Total XP: "..XP_Total.Value.." ")

    XP_Value:GetPropertyChangedSignal('Value'):Connect(function()

    XP_Label.Text = (""..XP_Value.Value.. "/"..XP_Needed.Value.."")

    Level.Text = ("Level "..LVL.Value.."")

    xpRemain.Text = (""..XP_Remaining.Value.." XP Left")

    xpTotal.Text = ("Total XP: "..XP_Total.Value.." ")

    end)

You don’t need the XP remaining because that’s just for the script to use to calculate the remaining XP to add to the next level.

When i put the XP_value to 50 it dosent go to Level 2