# 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.