Code randomly stops working

Heyy! So I have this code:

local Counter = 0
while task.wait(15) do
	warn("Still running the task.wait 15")
	Counter += 15
	for i,v in pairs(game.Players:GetChildren()) do 
		if v:FindFirstChild("PlayerData") ~= nil and v:FindFirstChild("leaderstats") ~= nil then
			v.PlayerData.Playtime.Value += 15
			if Counter >= 90 then 
				if v.PlayerData:FindFirstChild("XP") ~= nil and v.PlayerData:FindFirstChild("Level") ~= nil then
					if mps:UserOwnsGamePassAsync(v.userId, 189517075) then
						v.PlayerData.XP.Value +=200 
					else
						v.PlayerData.XP.Value +=100 
					end
					if v.PlayerData.XP.Value >= (v.PlayerData.Level.Value) * 100 then
						v.PlayerData.Level.Value += 1
						v.leaderstats.Level.Value = v.PlayerData.Level.Value
						if v.Character then
							if v.Character.Head:FindFirstChild("GroupRank") then
								if v:FindFirstChild("ResetChatTag") then else
									v.Character.Head.GroupRank.Level.Text = "<u>Level "..v.PlayerData.Level.Value.."</u>"
								end
							end
						end
						v.PlayerData.XP.Value = 0
					end
				end
			end
		end
	end
	if Counter >= 90 then Counter = 0 end
end

and sometime it simply stops working. Randomly. Anyon who can see the error out of it?

4 Likes

First off, any errors in the output window?
Next, print the variables checked in every if statement before the if.
For the if counter >= 90 check do this:

print("counter = ",counter)
if counter >= 90 then

This will help you troubleshoot by letting you know what’s going on. If for example counter is nil it’ll tell you that, and then you can troubleshoot the code that sets the counter variable.

3 Likes

I am unable to troubleshoot because this code is from a public roblox game at all and when someone reports it that XP aren’t working and I join, I wouldn’t be able to see it thought because there are many API’s errors in the console log. In addition to that, the code itself seems fine sos I don’t get it why it won’t work.

Clean up your console and fix the errors you know about so the console isn’t filled up with them

2 Likes

We would need to reboot like every single server which we can’t simple. Fixing the code itself would simply solve the problem but there’s insnt any problem. xD

1 Like

I don’t understand a lot of your replies.

We would need to reboot like every single server which we can’t simple You can choose the update Migrate to latest update (I think that’s the term).
From what I understand Roblox will not add new players to old servers so they shut down when all the current players leave.

Fixing the code itself would simply solve the problem but there’s insnt any problem
But there is a problem that we are trying to help you troubleshoot.

In addition to that, the code itself seems fine sos I don’t get it why it won’t work.
But it doesn’t seem fine because it breaks.

I am unable to troubleshoot because this code is from a public roblox game at all and when someone reports it that XP aren’t working and I join, I wouldn’t be able to see it thought because there are many API’s errors in the console log
As @icymanred said, if the console has errors then you need to clean those up. Why can’t you test it in Studio using the Server instead of Locally? The troubleshooting steps we are suggesting are to help you. If you don’t at least try our steps then we are going to get frustrated and we’ll probably stop trying to help you.

1 Like

Is that else really meant to be there? O.o’ Please just invert the condition or at least format it normally, “clever” tricks like that end up biting you later (and anyone trying to help you). I doubt it’d cause the issue you describe so I’ll keep looking for the real cause

1 Like

I rewrote your code to make it actually readable to try and find the bug, but there’s nothing obviously wrong. Oh well, here’s the

rewritten code
local PLAYTIME_UPDATE_PERIOD_SECONDS = 15
local XP_REWARD_PERIOD_SECONDS = 60
local DOUBLE_XP_GAMEPASS_ID = 189517075

--Data access helpers
local function getDataObject(player, key)
	local data = player:FindFirstChild("PlayerData")
	assert(data, `Failed accessing data for {player}!`)
	local valueObject = data:FindFirstChild(key)
	assert(valueObject, `Failed accessing data.{key} for {player}!`)
	return valueObject
end

local function getData(player, key)
	return getDataObject(player, key).Value
end

local function setData(player, key, value)
	getDataObject(player, key).Value = value
end

local function incData(player, key, increment)
	getDataObject(player, key).Value += increment
end

--Display update helper
local function updateLevelDisplay(player)
	local character = player.Character
	local level = getData(player, "Level")
	player.leaderstats.Level.Value = level
	if character then
		if character.Head:FindFirstChild("GroupRank") then
			if player:FindFirstChild("ResetChatTag") then
				character.Head.GroupRank.Level.Text = `<u>Level {level} </u>`
			end
		end
	end
end

--Gameplay helper
local function giveXp(player, amount)
	incData(player, "XP", amount)
	--If enough XP to level up...
	if getData(player, "XP") >= getData(player, "Level") * 100 then
		-- ... exchange all XP for 1 level
		setData(player, "XP", 0)
		incData(player, "Level", 1)
		
		updateLevelDisplay(player)
	end
end

--Playtime update loop
task.spawn(function()
	while task.wait(PLAYTIME_UPDATE_PERIOD_SECONDS) do
		for _, player in game.Players:GetPlayers() do
			incData(player, "Playtime", PLAYTIME_UPDATE_PERIOD_SECONDS)
		end
	end
end)

--XP reward loop
task.spawn(function()
	while task.wait(XP_REWARD_PERIOD_SECONDS) do
		for _, player in game.Players:GetPlayers() do
			if mps:UserOwnsGamePassAsync(player.userId, DOUBLE_XP_GAMEPASS_ID) then
				giveXp(player, 200)
			else
				giveXp(player, 100)
			end
		end
	end
end)

It’s a bit more code but it’s way easier to follow because it doesn’t try to do everything in one huge scope, and a lot of the added lines is just whitespace. You can figure out what the script does just by looking at the two loops at the bottom. It uses abstraction through helper functions to ensure a consistent way of awarding XP that handles all the associated level-up and display logic. Those helpers could be put in a library and reused across your game. And it uses proper variable names and more variables for commonly used things to again make things more readable.

An important difference is that it errors (through asserts) if it tries to do it’s thing before the data objects are ready, which is way better than just doing nothing silently because that would be a problem that you’d have to fix. The only way to discover that the “silently failing” version is broken is players noticing that something is wrong.

3 Likes

Hey, thank you so much for your re-code! The code isn’t from myself because we are a small Dev group and we just wasn’t able to figure out the problem. I will see if this is going, to work. Thank you!

1 Like