[Loop] Script only works in studio, refuses in-game

Been experiencning this incredibly annoying issue recently and I simply have no clue on how to fix it.
I’ve switched the code to seperate scripts (incase it was messing with the modules also loaded in the core), switched the way it works and modified a lot on it just in general. Spent at least 4-5 hours just figuring out what the hell is happening.

This is an EXP giver. Every 300 seconds (5 minutes) it’s meant to give out EXP to everyone in the server.
It succeeds but doesn’t at the same time.

This script works on playtest, even testing with multiple people (local server) but when I join the actual game, the script runs once or twice before ending up not giving any errors or printing out. It also completely stops giving EXP and responding. It doesn’t do this in play testing, even though I’m doing it with multiple people.

I would show you an error or anything, but it simply does not provide me with one.
This is the code down below: (praying you can help me)

I’ve had to hide a bit of the code as it leaks information which I litterally cannot share, but replaced it and noted it in the script as to where I did this

XP AWARDER SCRIPT:


local ServerModules = game.ServerStorage.Modules
local GroupManager  = require(game.ReplicatedStorage.Modules.GroupManager)

local DatastoreManager = require(ServerModules.DatastoreManager)


function rankUser(UserId, RoleId)	
	game:GetService("HttpService"):GetAsync("----") -- Link hidden due to privacy
end

function LevelAdjustmentRanking(plr, levelvalue)
	if levelvalue >= 5 and levelvalue < 10 then
		if plr:GetRankInGroup(GroupManager.Group) < GroupManager["Experienced Production Crew"] and plr:GetRankInGroup(GroupManager.Group) ~= GroupManager["Noted community member"]  then
			rankUser(plr.UserId, GroupManager["Experienced Production Crew"])
		end
	elseif levelvalue >= 10 and levelvalue < 20 then
		if plr:GetRankInGroup(GroupManager.Group) < GroupManager["Senior Production Crew"] and plr:GetRankInGroup(GroupManager.Group) ~= GroupManager["Noted community member"]   then
			rankUser(plr.UserId, GroupManager["Senior Production Crew"])
		end
	elseif levelvalue == 20 then
		if plr:GetRankInGroup(GroupManager.Group) < GroupManager["Lead Production Crew"] and plr:GetRankInGroup(GroupManager.Group) ~= GroupManager["Noted community member"]  then
			rankUser(plr.UserId, GroupManager["Lead Production Crew"])
		end
	end
end



while true do		
	wait(300) -- aware I should be using task.wait, but I'm still unsure on differences.
	
	print("Starting giving session")
	local AmountOfPlayers = #game:GetService("Players"):GetChildren()
	local AmountOfPlayersLeft = #game:GetService("Players"):GetChildren()
	for i, plr in pairs(game:GetService("Players"):GetPlayers()) do
		
		AmountOfPlayersLeft = AmountOfPlayersLeft - 1
		
		warn(i, "/" .. AmountOfPlayers .. " (AmountOfPlayersLeft: " .. AmountOfPlayersLeft .. ") --------------")
		
		local Parent = plr.Parent or plr.AncestryChanged:Wait()
		
		print(plr.Name .. " - Parent loaded, user is not NIL.")
		
		if plr:GetRankInGroup(GroupManager.Group) == GroupManager.Suspended then print("THIS USER WAS SUSPENDED, ONTO THE NEXT ONE") return end
		if plr:GetRankInGroup(GroupManager.Group) < GroupManager["Junior Production Crew"] then print("THIS USER WAS NOT STAFF, ONTO THE NEXT ONE") return end
		
		
		local plrdata = plr:WaitForChild("playerData")
		local Level = plrdata.Level
		local Coins = plrdata.Coins
		local EXP = plrdata.EXP
		
		print(Level.Value, Coins.Value, EXP.Value)
		

		if Level.Value < 20 then
			print("UNDER LVL 20")
			local EXPToNextLevel = GroupManager.Levels[Level.Value + 1]
			print("EXP TO NEV LEVEL: " .. EXPToNextLevel)
			
				if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(plr.UserId, 9472139) or game:GetService("MarketplaceService"):UserOwnsGamePassAsync(plr.UserId, 5752438) then
					Coins.Value += 5 
					EXP.Value += 15
					game.ReplicatedStorage.Remotes.NotifyHandler:FireClient(plr, "REWARDS:  +5 coins, +15 EXP", Color3.fromRGB(170,23,178), "rbxassetid://6658761720")
					warn("ADDING 15 XP TO " .. plr.Name .. " (PREMIUM) ")
				else
					EXP.Value += 10 
					game.ReplicatedStorage.Remotes.NotifyHandler:FireClient(plr, "REWARDS: +10 EXP", Color3.fromRGB(170,23,178), "rbxassetid://6658761720")
					warn("ADDING 10 XP TO " .. plr.Name .. " (NO PREMIUM) ")
				end

			
				print(EXP.Value, EXPToNextLevel)
				if EXP.Value >= EXPToNextLevel then
					local ExtraEXP = (EXP.Value - EXPToNextLevel)
					game.ReplicatedStorage.Remotes.NotifyHandler:FireClient(plr, "LEVEL UP!..", Color3.fromRGB(170,23,178), "rbxassetid://9819455786")

					EXP.Value = (0 + ExtraEXP)
					Level.Value += 1
					Coins.Value += 25

					warn("LEVELED UP " .. plr.Name)
					if Level.Value == 5 or Level.Value == 10 or Level.Value == 20 then
						LevelAdjustmentRanking(plr, Level.Value)
						game.ReplicatedStorage.Remotes.RankUpHandler:FireClient(plr)
					end
				end
		end

	end
end

I don’t deem it neccesary for the other modules to be seen, but if you deem that it will help a bit then request and I shall deliver.

:pray: Thank you!

1 Like

task.wait() will provide a method to space the amount of time you run the code contained in the loop. wait() allows you to put internal waits inside without the loop without having to finish an iteration. They both have their place.

There is no difference in these values:

	local AmountOfPlayers = #game:GetService("Players"):GetChildren()
	local AmountOfPlayersLeft = #game:GetService("Players"):GetChildren()

Unless you check it before the wait(300) i.e.

	local AmountOfPlayers = #game:GetService("Players"):GetChildren();
	wait(300);
	local AmountOfPlayersLeft = #game:GetService("Players"):GetChildren()

Okay so those 2 values are a way I used in “debugging”.
One of them is for the overall players the loop is taking when it commits a session, whilst the other one subtracts itself by 1 when per. person. this shows me in the logs how many people in total it is doing, and how many people are left.

Why is he using #game instead of game?

Okay a better way to set a counter is to get the value once and then assign it to another variable,i.e.

	local AmountOfPlayers = #game:GetService("Players"):GetChildren()
	local AmountOfPlayersLeft = AmountOfPlayers;

It makes code easier to understand that way.

1 Like

It has GetChildren() at the end so will return a table

1 Like

Oh ok thanks charrrrrrrrrrrrrrrrrr

You are returning under both of these conditions, that will break the loop, you should use continue end when either of these conditions fail.

if plr:GetRankInGroup(GroupManager.Group) == GroupManager.Suspended then print("THIS USER WAS SUSPENDED, ONTO THE NEXT ONE") return end
if plr:GetRankInGroup(GroupManager.Group) < GroupManager["Junior Production Crew"] then print("THIS USER WAS NOT STAFF, ONTO THE NEXT ONE") return end
1 Like

I seriously did not know this, I thought it only stopped that singular if statement-. I will publish this update out now, and come back to it in a bit. If this does end up working and fixing everything, then thank you so much <3.

1 Like

FYI: The continue end will return you back to this line, with the index and value on the next pair.

for i, plr in pairs(game:GetService("Players"):GetPlayers()) do

1 Like