I’m using GnomeCode’s Tower Defense Tutorial to make my tower defense game, but I encontered a problem. When I reach max towers, I cant upgrade it. Here’s the code:
local PhysicsService = game:GetService("PhysicsService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local events = ReplicatedStorage:WaitForChild("Events")
local functions = ReplicatedStorage:WaitForChild("Functions")
local animateTowerEvent = events:WaitForChild("AnimateTower")
local spawnTowerFunction = functions:WaitForChild("SpawnTower")
local requestTowerFunction = functions:WaitForChild("RequestTower")
local sellTowerFunction = functions:WaitForChild("SellTower")
local changeTowerTarget = functions:WaitForChild("ChangeTarget")
local players = game:GetService("Players")
local towerCapacity = 15
local tower = {}
function tower.FindTarget(newTower, range, mode)
local bestTarget = nil
local bestWayPoint = nil
local bestDistance = nil
local bestHealth = nil
local map = workspace.Map:FindFirstChildOfClass("Folder")
for i, target in ipairs(workspace.Map:FindFirstChildWhichIsA("Folder").Mob:GetChildren()) do
local distanceToTarget = (target.HumanoidRootPart.Position - newTower.HumanoidRootPart.Position).Magnitude
local distanceToWayPoint = (target.HumanoidRootPart.Position - map.Waypoints[target.MovingTo.Value].Position).Magnitude
if distanceToTarget <= range then
if mode == "Near" then
range = distanceToTarget
bestTarget = target
elseif mode == "First" then
if not bestWayPoint or target.MovingTo.Value > bestWayPoint then
bestWayPoint = target.MovingTo.Value
if not bestDistance or distanceToWayPoint < bestDistance then
bestDistance = distanceToWayPoint
bestTarget = target
end
end
elseif mode == "Last" then
if not bestWayPoint or target.MovingTo.Value < bestWayPoint then
bestWayPoint = target.MovingTo.Value
if not bestDistance or distanceToWayPoint > bestDistance then
bestDistance = distanceToWayPoint
bestTarget = target
end
end
elseif mode == "Strong" then
if not bestHealth or target.Humanoid.Health > bestHealth then
bestHealth = target.Humanoid.Health
bestTarget = target
end
elseif mode == "Weak" then
if not bestHealth or target.Humanoid.Health < bestHealth then
bestHealth = target.Humanoid.Health
bestTarget = target
end
end
end
end
return bestTarget
end
function tower.Attack(newTower, player)
local config = newTower:WaitForChild("Setting")
local Target = tower.FindTarget(newTower, config.Range.Value, config.TargetMode.Value)
if Target and Target:FindFirstChild("Humanoid") and Target.Humanoid.Health >= 0 then
--local targetCFrame = CFrame.lookAt(newTower.HumanoidRootPart.Position, Target.HumanoidRootPart.Position)
--local Vectors = Vector3.new(0, Target.HumanoidRootPart.Orientation.Y, 0)
local targetPos = Vector3.new(Target.HumanoidRootPart.Position.X, newTower.PrimaryPart.Position.Y, Target.HumanoidRootPart.Position.Z)
local targetCFrame = CFrame.lookAt(newTower.PrimaryPart.Position, targetPos)
newTower.PrimaryPart.CFrame = targetCFrame
animateTowerEvent:FireAllClients(newTower, "Attack", Target)
player.Points.Value += config.Damage.Value / math.round(5)
Target.Humanoid:TakeDamage(config.Damage.Value)
player.Hits.Value += 1
task.wait(config.Cooldown.Value)
end
task.wait(.001)
if newTower and newTower.Parent then
tower.Attack(newTower, player)
end
end
function tower.ChangeMode(player, model)
if model and model:FindFirstChild("Setting") then
local targetMode = model.Setting.TargetMode
local modes = {"First", "Last", "Near", "Strong", "Weak"}
local modeIndex = table.find(modes, targetMode.Value)
if modeIndex < #modes then
targetMode.Value = modes[modeIndex + 1]
else
targetMode.Value = modes[1]
end
return true
else
warn("Unable to change mode")
return false
end
end
changeTowerTarget.OnServerInvoke = tower.ChangeMode
function tower.Sell(player, model)
if model and model:FindFirstChild("Setting") then
if model.Setting.Creator.Value == player.Name then
player.PlacedTowers.Value -= 1
player.Points.Value += model.Setting.SellValue.Value
model:Destroy()
return true
end
end
warn("Unable to sell tower")
return false
end
sellTowerFunction.OnServerInvoke = tower.Sell
function tower.Spawn(player, name, cframe, previous)
local allowedToSpawn = tower.CheckSpawn(player, name)
if allowedToSpawn then
local newTower
local oldMode = nil
if previous then
oldMode = previous.Setting.TargetMode.Value
previous:Destroy()
--task.wait(.01)
newTower = ReplicatedStorage.Towers.Upgrades[name]:Clone()
else
newTower = ReplicatedStorage.Towers[name]:Clone()
--task.wait(.01)
player.PlacedTowers.Value += 1
end
local ownerValue = Instance.new("StringValue")
ownerValue.Name = "Creator"
ownerValue.Value = player.Name
ownerValue.Parent = newTower.Setting
local targetMode = Instance.new("StringValue")
targetMode.Name = "TargetMode"
targetMode.Value = oldMode or "First"
targetMode.Parent = newTower.Setting
newTower.HumanoidRootPart.CFrame = cframe
newTower.Parent = workspace.Towers
newTower.HumanoidRootPart:SetNetworkOwner(nil)
--[[newTower.Torso.Owner.ownerText.Text = player.Name
newTower.Torso.Owner.ownerText.Visible = true--]]
--[[local bodyGyro = Instance.new("BodyGyro")
bodyGyro.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)
bodyGyro.D = 0
bodyGyro.CFrame = newTower.HumanoidRootPart.CFrame
bodyGyro.Parent = newTower.HumanoidRootPart]]--
local cframe = Instance.new("CFrameValue")
cframe = Vector3.new(math.huge, math.huge, math.huge)
cframe = newTower.HumanoidRootPart.CFrame
for i, object in ipairs(newTower:GetDescendants()) do
if object:IsA("BasePart") then
PhysicsService:RegisterCollisionGroup(object, "Tower")
object.CollisionGroup = "Tower"
end
end
player.Points.Value -= newTower.Setting.Cost.Value
coroutine.wrap(tower.Attack)(newTower, player)
return newTower
else
warn("Requested tower does not exist", name)
return false
end
end
spawnTowerFunction.OnServerInvoke = tower.Spawn
function tower.CheckSpawn(player, name)
local towerExists = ReplicatedStorage.Towers:FindFirstChild(name, true)
if towerExists then
if towerExists.Setting.Cost.Value <= player.Points.Value then
if player.PlacedTowers.Value < towerCapacity then
return true
else
warn("Player reached max limit")
end
else
warn("Player cannot afford")
end
else
warn("Tower does not exist")
end
return false
end
requestTowerFunction.OnServerInvoke = tower.CheckSpawn
return tower