Need help with making tower defense wave

Hello there,

I am making a tower defense game but I have a problem with making the wave system work. The scripts work perfectly but the wave is not. It will spawn the first wave and keep doing it without waiting until the wave ends. Please help :slight_smile:

heres the codes:

GameLogic script:

local Round = require(script.Round)

local map = workspace:WaitForChild("Map")
local waypoints = map:WaitForChild("Waypoints")

for i=1, 3 do
	print("starting wave")
	if i < 3 then
		Round.spawnEnemy(map, "Zombie", 2 * i)
	elseif i == 3 then
		Round.spawnEnemy(map, "Zombie", 4)
		wait(3)
		Round.spawnEnemy(map, "Zombie", 3)
	elseif i > 3 then
		Round.spawnEnemy(map, "Zombie", 2 * i)
	end
	print("game over")
	task.wait(5)
end

Round module script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")

local events = ReplicatedStorage.Events
local enemies = ServerStorage.Enemies

local Round = {}

function Round.patrol(map, enemy)
	local humanoid = enemy:WaitForChild("Humanoid")
	local waypoints = map.Waypoints
	
	for i=1, #waypoints:GetChildren() do
		humanoid:MoveTo(waypoints[i].Position)
		humanoid.MoveToFinished:Wait()
	end
	
	enemy:Destroy()
end

function Round.spawnEnemy(map, name, quantity)
	local exist = enemies:FindFirstChild(name)
	
	if exist then
		for i=1, quantity do
			task.wait(2)
			local enemy = exist:Clone()
			enemy.HumanoidRootPart.CFrame = map.Spawn.CFrame
			enemy.Parent = workspace.Enemies
			
			-- setup enemy data
			local humanoid = enemy.Humanoid
			local enemyData = require(enemies.EnemyData)
			humanoid.MaxHealth = enemyData[name]["Health"]
			humanoid.WalkSpeed = enemyData[name]["Speed"]
			
			-- move enemy
			coroutine.wrap(Round.patrol)(map, enemy)
		end
	else
		warn(name, "does not exist")
	end
end

return Round

I appreciate all your responses :slight_smile:

2 Likes

Hello there!

So first of all the issue is that you are not giving a value to increment by each time in the for loop.
so basically you have to give it 3 values not 2, the 3rd value is the amount it increments by each time which in this case would be 1.

I also see that you are really using a bad practice way to do the Waves. Me myself is also currently working on a Tower Defense Game. I am using a module containing all of the Waves.

The way i store my Waves in the Module is Tables as waves and it will loop through them. Each Wave has stuff like Rewards and other stuff. It also has another Table inside containing all of the Enemies, each is a Table Containing the Enemies name nothing else, then you might be wondering why i am having 1 singular value and putting it in a Table instead of letting it stand alone. Well, that is because in Tables you cannot have any Values that are the same, though we want Lots of values that are the same, since if we wanna spawn 3 Zombies there is gonna be 3 of the same Values already there, that is why they are in tables because then they will not count as the same Values. Now how do we do delays? To make delays we do another value inside of the Enemies Table, but instead of: {[β€œName”] = Zombie}, we do {[β€œDelay”] = 1} for example.

Now the way to handle and use this in the Main Script that you call GameLogic Script. The way i would do it if i was you would be like this:

local WavesModule = require(ReplicatedStorage.Modules.WavesModule)

for index, WaveTable in pairs(WavesModule.Waves) do
    for i = 1, #WaveTable.Enemies, 1 do
        local List = WaveTable.Enemies[i]
        
        if list.Name then
            Round.spawnEnemy(map, "Zombie", 1)
        elseif List.Delay then
            task.wait(list.Delay)
        end
    end
    
    -- if you wanna do anything here this will run each time a wave is finished!
end

-- if you wanna do anything here this will run when every wave is done and they have won!

If this was helpfull please tell me, i would always like to help again :smiley:

Kind Regards, The_IntoDev.

1 Like