Tower Defense Round System

Im currently making a tower defense round system and I’m not sure what to use to start waves. My first thought was to use a bool value that turns true for a second and switching back to false, then a script has the propertychanged signal on that value and if the bool value turns true it will call a different function to start the round based on the current wave.

Is there a better or efficient way of doing this? Please let me know :grin:

it really depends on the cirumstances. if you can for some reason only trigger the start round by using the client, use a RemoteEvent (make sure it’s safe towards exploiters). however, I really don’t see any problem in just creating a function to start the first wave, then the second, etc.

by the way, I only ever recommend using NumberValues if you want other scripts to know what wave it is

1 Like

I recommend one script that handles the round related stuff, no need for values at all.
In the script you can wait a bit before starting the first wave and then just handle all the others waves from there.

task.wait(30)

wave_one()
task.wait(60)
wave_two()

and it would be clever to implement a module script for the waves like this:

local Wave = {}
Wave.__index = Wave

function Wave.New() end

return Wave
1 Like

Everything about wave starting is server sided, There are only remote events for skip wave and for starting the game (ready). I’m only trying to find some more efficient ways to start waves. When I mean efficient I mean by doesn’t consume too much power and easy to update since i will be copy pasting a single place and just changing the health and models of the units for each world.

What about skipping? From what I know there isn’t anything in lua that can instantly skip a wait function? (From what I know). And I haven’t learned OOP yet :sweat_smile:

that is a great point. here’s what I’ve came up with:

again, I recommend using functions for each wave, but instead of doing a simple task.wait() function, I would honestly do a “for i = 1, [length of wave] do”. example:

wave1()

for i = 1, 60 do
	if [wave had skipped] == true then break end

	task.wait(1)
end)

wave2()

you may also put the for loop inside the function to make it easier to look at.
(OR make the for loop its own separate function)

hope this helps!

1 Like

oh yeah and I must give credit that using a Module Script for waves is a smart and good move

1 Like

This is a nice and easy way to do it. If you wanted it to be a bit more advanced and “faster”, you could do something like this:

local start_unix = tick()
local skip = false
local duration = 20 -- seconds

while ((tick() - start_unix < duration) and not skip) do
	task.wait()
end

It’s a bit complex but it does essentially the same thing as the version @melvinpetersen posted!

Speaking of OOP, if you had a wave object it could handle the skipping on its own without any other scripts having to do it! I really recommend looking into OOP since it would make your life much easier.

There is a great post by magnalite explaining everything you need to know here^

1 Like

By the way, coroutines allow for something like “stopping a wait”:

local function wave_one()
	print("test1")
	task.wait(2)
	print("test2")
end

local current_wave = coroutine.create(wave_one)

coroutine.resume(current_wave)
print("test3")

The Output will be:
test1
test3
test2

(because coroutines run async**)

They can be stopped like this:
coroutine.close(current_wave)

The Output will be:
test1
test3

because the function was stopped before test2 could be printed!
Hope this helped!

let me know if you’ve solved the problem!

1 Like

I’ve decided on using this type of timer, tho there is a small problem. If you skip at the start of a second, the wave wont be skipped until that second has ended. This isn’t that big of a problem but it just looks really bad in my opinion. Since PropertyChangedGetSignal cant break loops, I Don’t really know how to fix this.

well, as for that one, I recommend listening to @Nico_Nic77 on this one. he provided some information on using the tick() function.

1 Like

I personally would not use a loop that handles the waves, instead, you should look into task.spawn, coroutine.create, coroutine.wrap, tick / os.time and definetly OOP for your project!

I also explained how @melvinpetersen’s timer wont be as fast as the one suggested by me in my second response.

What do you mean by that? the break keyword will break out of loops and stops their further execution? What do you need the PropertyChangedGetSignal for?

I cannot emphasize how good it would be to learn about OOP and the above named basic functions like task.spawn for your project.

If you have further questions regarding the functions or OOP feel free to post here!

Here is how I did it a while back in an old tower defense game:

function RoundModule.Start()
	local Map = RoundModule.LoadMap()
	Info.GameRunning.Value = true

	task.wait(1)
	
	for i = 3, 1, -1 do
		Info.Message.Value = `Starting in {i}...`
		task.wait(1)
	end

	for Wave = 1, Info.MaxWaves.Value do
		Info.Wave.Value = Wave
		Info.Message.Value = ""

		RoundModule.GetWave(Wave, Map) -- spawn mobs

		repeat
			task.wait(0.1)
		until #workspace.Mobs:GetChildren() == 0 or not Info.GameRunning.Value

		if Info.GameRunning.Value then
			if Wave == Info.MaxWaves.Value then
				Info.Message.Value = "VICTORY"
			else
				local Bonus = 100 * math.floor(Wave/2)
				if Wave == 1 then
					Bonus = 100
				end

				for _, Player in PlayerService:GetPlayers() do
					Player.Money.Value += Bonus
				end

				for i = 5, 1, -1 do
					Info.Message.Value = `Starting next wave in {i}...\nBonus: ${Bonus}`
					task.wait(1)
				end
			end
		else
			Info.Message.Value = "GAME OVER"
			break
		end
	end
end

I will be using coroutines in the module that spawns the enemies and I’m currently looking into OOP. What I was confused on was when I skip the wave when the timer is at lets say 59.9 seconds (numbers is going down) which means the game would have to wait another 0.9 seconds to register the skip. This isn’t a problem anymore I’ve already fixed this problem. Thanks.

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