Waves
Lesson 4 of 18 in Coddy's Roblox Game: Tower Defense course.
One zombie is not a game. Settings.Waves lists the waves, each a list of enemy names:
Waves = {
{ "Zombie", "Zombie", "Zombie" },
{ "Zombie", "Runner" },
}runWave(list) spawns its enemies one by one, Settings.SpawnGap seconds apart, and then waits until workspace.Enemies is empty, so the next wave starts only when this one is over. Before each wave the players get Settings.WaveBreak seconds to prepare.
The main loop goes through the waves in order: for i, list in Settings.Waves do.
Challenge
Easy- Write
runWave(list): spawn each enemy in the list, waitingSettings.SpawnGapafter each, then wait untilenemieshas no children. - Replace the single spawn with a loop over
Settings.Waves: waitSettings.WaveBreak, then run the wave.
This lesson's world has two short waves. Press Play, then Check.
Try it yourself
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)
local enemies = workspace.Enemies
print("The base can take " .. Settings.BaseHealth .. " hits")
-- The waypoints, in order (they are named 1, 2, 3...)
local waypoints = workspace.Path.Waypoints:GetChildren()
table.sort(waypoints, function(a, b)
return tonumber(a.Name) < tonumber(b.Name)
end)
-- The base's health, as an attribute of the workspace: every client can read it
workspace:SetAttribute("BaseHealth", Settings.BaseHealth)
-- Every player gets Money on the leaderboard
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local money = Instance.new("IntValue")
money.Name = "Money"
money.Value = Settings.StartMoney
money.Parent = leaderstats
end)
-- An enemy reached the base
local function damageBase(amount)
local health = math.max(0, workspace:GetAttribute("BaseHealth") - amount)
workspace:SetAttribute("BaseHealth", health)
end
-- Walk an enemy along the path. MoveTo gives up after 8 seconds and says so
-- (MoveToFinished with false), so a slow enemy is sent again until it arrives.
local function walkPath(enemy)
local humanoid = enemy.Humanoid
for i = 2, #waypoints do
repeat
humanoid:MoveTo(waypoints[i].Position)
until humanoid.MoveToFinished:Wait() or not enemy.Parent
if not enemy.Parent then
return
end
end
-- it reached the base
damageBase(1)
enemy:Destroy()
end
-- A new enemy at the gate, walking the path
local function spawnEnemy(kind)
local enemy = ServerStorage.Enemies[kind]:Clone()
-- dropped in just above the first waypoint
enemy:PivotTo(waypoints[1].CFrame + Vector3.new(0, 5, 0))
enemy.Parent = enemies
task.spawn(walkPath, enemy)
return enemy
end
-- One enemy, for now
spawnEnemy("Zombie")
This lesson includes a short quiz. Start the lesson to answer it and track your progress.