Need help to fix a stacking while loop

I want to make it so the while loops don’t stack. There is an issue where if the player leaves and re-enters the zone fast enough, the while loop ends up stacking, giving the player twice as much endurance as they should be getting. This issue doesn’t occur if the player leaves the zone for over a second.

[SCRIPT]

game.Players.PlayerAdded:Connect(function(player)

local Char = player.Character or player.CharacterAdded:Wait()
local humanoid = Char:WaitForChild("Humanoid")
local Zone = require(game.ReplicatedStorage.Zone)
local container = script.Parent
local zone = Zone.new(container)
local inZone = false

zone.playerEntered:Connect(function()

	-- Values

	local endurance = player.Endurance
	local endMulti = player.EndMultiplier
	local zoneMulti = player.EndZoneMultiplier
	local realmMulti = player.RealmMultiplier
	local zoneEndurance = player.ZoneEndurance

	-- Script

	inZone = true
	while task.wait(1.5) do
		if inZone == true then
			zoneMulti.Value = 20
			zoneEndurance.Value = 0
			humanoid.Health = humanoid.Health - 50000
			zoneEndurance.Value += endMulti.Value * zoneMulti.Value * realmMulti.Value
			endurance.Value += zoneEndurance.Value
		else
			return
		end	
	end
end)	

zone.playerExited:Connect(function()
	inZone = false
	player.EndZoneMultiplier.Value = 1
end)

end)

Try

inZone = true
while inZone == true do
    wait(1.5)
    --stuff

Seems to work for me and simplifies the code to an extent.

Move the while loop outside of the .playerEntered function

new code

game.Players.PlayerAdded:Connect(function(player)
    local Char = player.Character or player.CharacterAdded:Wait()
    local humanoid = Char:WaitForChild("Humanoid")
    local Zone = require(game.ReplicatedStorage.Zone)
    local container = script.Parent
    local zone = Zone.new(container)
    local inZone = false
    local endurance = player.Endurance
    local endMulti = player.EndMultiplier
    local zoneMulti = player.EndZoneMultiplier
    local realmMulti = player.RealmMultiplier
    local zoneEndurance = player.ZoneEndurance
    
    zone.playerEntered:Connect(function()
        inZone = true
    end)	
    
    zone.playerExited:Connect(function()
        inZone = false
        player.EndZoneMultiplier.Value = 1
    end)

    while task.wait(1.5) do
        if inZone == true then
            zoneMulti.Value = 20
            zoneEndurance.Value = 0
            humanoid.Health = humanoid.Health - 50000
            zoneEndurance.Value += endMulti.Value * zoneMulti.Value * realmMulti.Value
            endurance.Value += zoneEndurance.Value
        else
            return
        end	
    end
end)
1 Like

Hey matty, thanks for solving the question I had. After plugging in the new script I found that a different error started occurring. When multiple players enter the zone the entire script breaks and the script dosent know which humanoid send the damage to. Is there a way to make sure that the character and humanoid are linked with the corresponding character?

[SCRIPT]

local Zone = require(game.ReplicatedStorage.Zone)
local container = script.Parent
local zone = Zone.new(container)
local inZone = false

zone.playerEntered:Connect(function(player)
	inZone = true
	player.EndZoneMultiplier.Value = 900
end)	

zone.playerExited:Connect(function(player)
	inZone = false
	player.EndZoneMultiplier.Value = 1
end)

game.Players.PlayerAdded:Connect(function(player)
	local Char = player.Character or player.CharacterAdded:Wait()
	local humanoid = Char:WaitForChild("Humanoid")
	local endurance = player.Endurance
	local endMulti = player.EndMultiplier
	local zoneMulti = player.EndZoneMultiplier
	local realmMulti = player.RealmMultiplier
	local zoneEndurance = player.ZoneEndurance


	while inZone == true do
		zoneEndurance.Value = 0
		humanoid.Health = humanoid.Health - 10 * 24000000000
		task.wait(1.5)
		zoneEndurance.Value += endMulti.Value * zoneMulti.Value * realmMulti.Value
		endurance.Value += zoneEndurance.Value
	end
end)

Hey, sorry for the late reply — perhaps you could try changing the inZone variable to a dictionary; the key being a player, the value being whether or not they’re in the zone

You could go about this by changing local inZone = false to local inZone = {}, and adding the player to the dictionary upon joining; then, when a player enters the zone, you could change the value in the dictionary: i.e: inZone[player] = true

For the while inZone == true loop, you could just change this condition to while inZone[player] == true

You can then add a PlayerRemoving event to remove the player from the inZone dictionary

updated code:

local Zone = require(game.ReplicatedStorage.Zone)
local container = script.Parent
local zone = Zone.new(container)
local inZone = {}

zone.playerEntered:Connect(function(player)
	inZone[player] = true
	player.EndZoneMultiplier.Value = 900
end)	

zone.playerExited:Connect(function(player)
	inZone[player] = false
	player.EndZoneMultiplier.Value = 1
end)

game.Players.PlayerAdded:Connect(function(player)
	local Char = player.Character or player.CharacterAdded:Wait()
	local humanoid = Char:WaitForChild("Humanoid")
	local endurance = player.Endurance
	local endMulti = player.EndMultiplier
	local zoneMulti = player.EndZoneMultiplier
	local realmMulti = player.RealmMultiplier
	local zoneEndurance = player.ZoneEndurance
	inZone[player] = false

	while inZone[player] == true do
		zoneEndurance.Value = 0
		humanoid.Health = humanoid.Health - 10 * 24000000000
		task.wait(1.5)
		zoneEndurance.Value += endMulti.Value * zoneMulti.Value * realmMulti.Value
		endurance.Value += zoneEndurance.Value
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	inZone[player] = nil
end)