[Fixed] Stat incrementing multiple times at once, need a fix

Note: This problem has, rather, evolved into a different one and has been narrowed down. When you see the periods next to the word “skip” you can skip to the rest of the thread.

… start here …

I’m adding quests to my game. It’s a lot of code so I’ll just give some background info on it:

  • There are three dictionaries: One handles the messages the player sees; one handles the maximum values needed for each quest (e.g. in a phrase like “win the game 3 times”, the value would be 3); and the last one handles what the rewards are, as they are arbitrary numbers and are not meant to be calculated by an algorithm.
  • The player has values like QuestProgress and some others that are basically just there so that they can be referenced and utilized throughout the game.
  • When all the necessary data has been collected, a RemoteEvent is fired to the client to show them all the necessary information.

The last thing I should add to this description is that I have a script called RoundHandler. It basically uses a while true do loop since I have a round-based game, and it handles all the stuff, e.g. teleporting players and all the other stuff.

… skip …

I haven’t had many issues with it… until today. One of my quests is called “Play 3 rounds”. So what I did is I added a value to the player called PlayedThisRound, and basically if the player is not nil, has been teleported to the game, and is not marked as AFK, it will mark PlayedThisRound.Value to true. Otherwise it stays false. At the end of each round, if PlayedThisRound.Value == true then I run the following code: QuestProgress.Value = QuestProgress.Value + 1. I know this is a lot of information to take in, so I also copied + pasted a piece of my script in the RoundHandler script, which is in ServerScriptService:

for _, player in ipairs(game.Players:GetPlayers()) do
	if player.PlayedThisRound.Value == true then
		player.TimesPlayed.Value = player.TimesPlayed.Value + 1
		if player.QuestNum.Value == 1 then
			player.QuestProgress.Value = player.QuestProgress.Value + 1
	player.PlayedThisRound.Value = false

I have tried removing the first wait() statement but all it did was make the value not increment at all, and obviously that would be changing the issue instead of fixing it. It generally increments by 10, so after completing a single round I’ll see that the progress bar says 10 / 3. Of course it’s supposed to say 1 / 3. I know it’s not a client issue because I have played the rounds and checked the QuestProgress value, and it reflects the same values the client-side is showing.

I have had this issue take many forms before, and unfortunately none have been fixed. This time it’s more prominent and I feel like it would really defeat the purpose of quests if they could be completed in one go. Please help, I really want to continue working on quests but this has been really problematic. All advice will be appreciated! :smiley:

Don’t have much time but you should change ipairs to pairs ipairs returns just the index value.

1 Like

Code above isn’t the problem. And the functionality shouldn’t be affected by the wait() statements. For any convenience, this is the code drawn out explaining the process.

  • First lua’s ipairs function is called, passing in the player list which returns an iterative function that loops through all players. The use of ipairs and pairs should not make a difference here, since :GetPlayers() always returns an array. This also only loops through every player once.
    • In the loop we check if PlayedThis round is true, and increment the value by one and doing the following.
      • We check if questNum is equal to 1, incrementing that if it is and executing the wait:
        • Now this wait() statement delays the control flow by about 1/40 of a second. The above code has already ran, so it shouldn’t affect incrementing values. But it will delay the checks for all later iterations through the player list.

Now getting into how you might debug this. First you have to look at the context in which this code block is run. If it’s in an event listener, its possible you have 10 connections all firing on the same event. Or 1 connection firing from 10 simulatenous events.

The only issue is that there’s no event listeners in the entire script; all it really does is fire different events. All of the code is incased in a while true do loop that takes about 45 seconds to a minute for each run-through. I could paste the entire script as a response if you would like, but the code I pasted is the only stuff relevant to my situation.

Edit: I’ve tried many solutions but all they’re doing is either not incrementing the progress at all or incrementing it WAY too much. This still hasn’t been solved.

Which one of your values is doing this? I have encountered this issue before and in order to solve it I just moved over the incrementing to a function. Give this a shot and let me know.


function change(stat,ivalue)
stat.Value = stat.Value + ivalue

change(player.QuestProgress.Value, 1)
change(player.TimesPlayed.Value, 1)

1 Like

Unfortunately it didn’t work.

This is the function I created:

function increment(stat, numberToAdd)
   stat = stat + numberToAdd

And this is my updated code that actually (is supposed to increment the value):

for _, player in ipairs(game.Players:GetPlayers()) do
		if player.PlayedThisRound.Value == true then
			increment(player.TimesPlayed.Value, 1)
			if player.QuestNum.Value == 1 then
				increment(player.QuestProgress.Value, 1)
		player.PlayedThisRound.Value = false

At first I thought it would work but it still won’t. This issue’s been frustrating me for days now :angry:


It’s incrementing TimesPlayed but not QuestProgress, it just stays at zero.

Edit 2:

I’ve made sure during the run-through that QuestNum stayed at 1, and it has.

Edit 3:

I’ve even added print() statements and it still won’t work as intended. I even attached a screenshot here:

When it says “Should increment xyz” that means it was printed right before the increment() function was used. When it says “increment function has been accessed” that means the print() statement at the beginning of the function has been run.

Screen Shot 2020-06-27 at 5.01.00 PM

Edit 4:

I really shouldn’t have had to make these many edits, but here I am. I’ve tried going about with a more aggressive method that forces it to increment itself, using the following code for the increment() function:

local function increment(stat, numberToAdd)
	print("Increment function has been accessed")
	local oldValue = stat.Value
	while stat.Value < oldValue + numberToAdd do
		stat.Value = stat.Value + 1
	print("The old value is " .. oldValue .. ", the number to add was " .. numberToAdd .. ", and the current value is " .. stat.Value)

As you might see I also added another print() statement to see what this thing’s logic really is. This is what I’m seeing in the output (the first set of statements has to do with TimesPlayed; the second one has to do with QuestProgress):

So now I’m concluding that it’s adding the value but then it just reverts back to zero right afterwards. Does anyone have any input as to why this is happening? I have no code that ever set it to zero. I even used cmd + shift + f (I have a Mac) to view all references of QuestProgress, and the only time it is ever set to zero is when a specific RemoteEvent is fired marking the quest complete. But I even used a print() statement to tell me when that event is fired, and nothing came in the output section relevant to that. I’m honestly extremely confused.

Yeah, go ahead and show more of the script. The code you pasted is definitely the most relevant, but it doesn’t have errors in it. The problem is probably with some type of control flow; what I meant about event listeners was just one example of this.
So in this situation the code it’s encased in is also important and should be able to solve the problem.

You also don’t need an incrementing function. Think about it. How is:

x.Value = x.Value + 1

different than

function increment(x, val)
   x.Value = x.Vaue +val
increment(x, val)

I looked through all my code and it turns out that there was a piece of code I had that read the following:

	player = plr

repeat wait() until player

local leaderstats = player.leaderstats
local gold = leaderstats and leaderstats.Gold
local diamonds = leaderstats and leaderstats.Diamonds

while true do
	if player.QuestNum.Value == 7 or 3 then
        -- These quests say to have a certain amount of gold at one time
		player.QuestProgress.Value = gold.Value
	if player.QuestNum.Value == 8 then
        -- This quest says to get a certain amount of diamonds at once
		player.QuestProgress.Value = diamonds.Value

So I temporarily disabled the script to see what would happen, and it all of a sudden worked. What I’m confused about is why it’s running when QuestNum’s value is clearly not 3, 7, or 8. So I guess the problem has “evolved” into this, so to speak. But now that QuestProgress is working, does anyone know why this wasn’t?

Edit: It was because I tried to shorten up the if statement but instead messed it up. More specifically, this line:

if player.QuestNum.Value == 7 or 3 then (...) end

I had to edit it to look like this:

if player.QuestNum.Value == 7 or player.QuestNum.Value == 3 then (...) end

For whatever reason, when I used or 3 I guess it was asking studio if 3 was something else than what I was thinking. Thanks for everyone’s help, though, because you all helped me narrow down the issue!