How do I make a loop run an extra time when something happens

This is my code right now:

for i = 1, numberofzombs, 1 do
	if #badspawners == 1 then
		for i=1, #badspawners do
			badspawners[i]:Destroy()
		end
	numberofzombs += 1
	end
end

It’s supposed to make 5 parts in total, check if a part is in a bad position with :GetPartsInPart which gives me the “badspawners” table, if it is then delete it and, to compensate for the lost part, add one more cycle to the loop, which will add another part, check if it’s in a bad position etc. But this doesn’t work for some reason, it creates a random amount of parts every time.

You can’t change arguments of a for loop while its looping. Instead use a while loop:

while numberofzombs > 0 do
    numberofzombs -= 1
    if #badspawners == 1 then
		for i=1, #badspawners do
			badspawners[i]:Destroy()
		end
	    numberofzombs += 1
	end
end
1 Like

Try doing it this way >

-- (Given a X spawn, check if Y Zombie is in a bad (X) spawn)?
local function IsBadSpawner(Spawn, Zombie)
    -- Implement your custom logic here
end

type GeneratedZombie = {
    Spawn: Part,
    Character: Model,
}

type Zombies = {GeneratedZombie}
type ZombiesWithBadSpawn = {GeneratedZombie?}

-- Generates X amount of Zombies and returns an table of normal Zombies and Zombies with bad spawns
-- Doesnt correct bad spawners

local function Generate(Amount: number): (Zombies, ZombiesWithBadSpawn)
    assert(Amount > 1, 'Cannot generate Zombies with amounts below 1')
    local Zombies = {}
    local BadSpawners = {}

    for i = 1, Amount do
        local ThisSpawn
        local ThisZombie 

        -- Implement your custom logic about zombie generation here

        if IsBadSpawner(ThisSpawn, ThisZombie) then
            BadSpawners[#BadSpawners+1] = {
                Character = ThisZombie,
                Spawn = ThisSpawn,
            }

            continue
        end

        Zombies[#Zombies+1] = {
            Character = ThisZombie,
            Spawn = ThisSpawn,
        }
    end

    return Zombies, BadSpawners
end

    
-- Generates zombies and corrects zombies with bad spawns.
local function GenerateSafely(Amount: number): Zombies 
    local Zombies, BadSpawners = Generate(Amount)

    while #BadSpawners > 0 do
        local Good, Bad = Generate(1)

        if #Bad == 1 then
            task.wait(0.01)
            continue
        end

        Zombies[#Zombies+1] = Good[1]
    end

    return Zombies
end

local function PlaceZombie(Zombie: GeneratedZombie)
    Zombie.Character:PivotTo(Zombie.Spawn.CFrame)

    -- Additional logic? Pathfinding etc idk
end

local function PlaceZombies(Zombies: Zombies)
    for _, ThisZombie in pairs(Zombies) do
        PlaceZombie(ThisZombie)
    end
end

-- Generation example:
local Zombies = GenerateSafely(10)
PlaceZombies(Zombies)
1 Like

I tried this. Worked great at first but then didn’t want to work again.
robloxapp-20230920-2338212.wmv (1.8 MB)
Here’s the full script:

local player = game.Players.LocalPlayer
local char = player.Character
local UIS = game:GetService("UserInputService")
local rs = game:GetService("ReplicatedStorage")
local area = rs.SummonDead.Area
local cleaner = rs.SummonDead.Cleaner
local zombie = rs.SummonDead.Zombie
local spawner = rs.SummonDead.Spawner

----Settings----

local keybind = Enum.KeyCode.G
local cooldown = 5
local numberofzombs = 5

----------------

UIS.InputBegan:Connect(function(input,gameprocessed)
	if gameprocessed then return end
	if input.KeyCode == keybind and char then

		local charPP = char.PrimaryPart
		local newarea = area:Clone()
		newarea.Parent = game.Workspace
		newarea.Position = charPP.Position
		newarea.Orientation = Vector3.new(0, 0, -90)
		
		local newcleaner = cleaner:Clone()
		newcleaner.Parent = game.Workspace
		newcleaner.Position = newarea.Position
		newcleaner.Orientation = newarea.Orientation

		local areaX = newarea.Size.Y/3
		local areaY = newarea.Position.Y
		local areaZ = newarea.Size.Z/3
		
		local bodyparts = char:GetChildren()

		while numberofzombs > 0 do
			numberofzombs -= 1
			
			local spawns = Vector3.new(math.random(-areaX, areaX), 0, math.random(-areaZ, areaZ))
			local newspawner = spawner:Clone()
			newspawner.Parent = game.Workspace
			newspawner.Orientation = Vector3.new(0, math.random(-180, 180), 0)
			newspawner.Position = newarea.Position + spawns -- ADJUST Y WITH RAYCAST
			local params = OverlapParams.new()
			params.FilterType = Enum.RaycastFilterType.Exclude
			params.FilterDescendantsInstances = {bodyparts, newarea}
			local badspawners = workspace:GetPartsInPart(	newcleaner, params)
			print(badspawners)
			if #badspawners == 1 then
				for i=1, #badspawners do
					badspawners[i]:Destroy()
				end
				numberofzombs += 1
			end
		end
		--newcleaner:Destroy()
		--newarea:Destroy() 
	end
end)

I don’t get why it stopped working after the first try

In the code numberofzombs is lowering to 0, so after the first loop it will be at 0 meaning next loop cant start. You can use a new variable instead of lowering that number:

local index = 0

while index < numberofzombs do
    index += 1
    if #badspawners == 1 then
		for i=1, #badspawners do
			badspawners[i]:Destroy()
		end
	    numberofzombs += 1
	end
end

Keep in mind that if you don’t reset numberofzombs every new loop will just start with increased numberofzombs, to fix that you have to either reset numberofzombs to original value or don’t increase it value in the loop, and instead lower index:
numberofzombs += 1 to index -= 1

I was stuck on this for too long and I learned a bit more. Thank you.

I tried to do this but I failed to implement it. Sorry I’m kinda new at scripting.

1 Like

Reach me out for any problems you have then. I’ll be here to help.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.