I need help fixing a bug that disables towers from attacking after a certain period of being unattended (not upgraded), I followed Gnomecode’s series on making a td game.
I can’t find any videos or posts of anyone having problems with this. Please let me know if you followed his tutorials and encountered the same bug. My console also doesn’t have any outputs that follow the bug.
Please let me know if you know how to fix this. If you need me to give any screenshots or videos, let me know! I’m also getting better at scripting, so I hope I can be cooperative.
im not sure exactly what script is the problem, since console doesnt give any outputs. ill send the script i think the problem is in
local Players = game:GetService("Players")
local PhysicsService = game:GetService("PhysicsService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local events = ReplicatedStorage:WaitForChild("Events")
local animateTowerEvent = events:WaitForChild("AnimateTower")
local functions = ReplicatedStorage:WaitForChild("Functions")
local spawnTowerFunction = functions:WaitForChild("SpawnTower")
local requestTowerFunction = functions:WaitForChild("RequestTower")
local sellTowerFunction = functions:WaitForChild("SellTower")
local changeModeFunction = functions:WaitForChild("ChangeTowerMode")
local map = workspace.Ruins
local maxTowers = 10
local tower = {}
function tower.FindTarget(newTower, range, mode)
local bestTarget = nil
local bestWaypoint = nil
local bestDistance = nil
local bestHealth = nil
for i, mob in ipairs(workspace.Mobs:GetChildren()) do
local distanceToMob = (mob.HumanoidRootPart.Position - newTower.HumanoidRootPart.Position).Magnitude
local distanceToWaypoint = (mob.HumanoidRootPart.Position - map.Waypoints[mob.MovingTo.Value].Position).Magnitude
if distanceToMob <= range then
if mode == "Near" then
range = distanceToMob
bestTarget = mob
elseif mode == "First" then
if not bestWaypoint or mob.MovingTo.Value >= bestWaypoint then
if not bestWaypoint or mob.MovingTo.Value > bestWaypoint then
bestDistance = nil
end
bestWaypoint = mob.MovingTo.Value
if not bestDistance or distanceToWaypoint < bestDistance then
bestDistance = distanceToWaypoint
bestTarget = mob
end
end
elseif mode == "Last" then
if not bestWaypoint or mob.MovingTo.Value <= bestWaypoint then
bestWaypoint = mob.MovingTo.Value
if not bestDistance or distanceToWaypoint > bestDistance then
bestDistance = distanceToWaypoint
bestTarget = mob
end
end
elseif mode == "Strong" then
if not bestHealth or mob.Humanoid.Health > bestHealth then
bestHealth = mob.Humanoid.Health
bestTarget = mob
end
elseif mode == "Weak" then
if not bestHealth or mob.Humanoid.Health < bestHealth then
bestHealth = mob.Humanoid.Health
bestTarget = mob
end
end
end
end
return bestTarget
end
function tower.Attack(newTower, player)
local config = newTower.Config
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)
newTower.HumanoidRootPart.BodyGyro.CFrame = targetCFrame
animateTowerEvent:FireAllClients(newTower, "Attack", target)
target.Humanoid:TakeDamage(config.Damage.Value)
if target.Humanoid.Health <= 0 then
player.Kills.Value += 1
for i, players in ipairs(Players:GetPlayers()) do
players.Cash.Value += target.Humanoid.MaxHealth * 1.5
end
end
task.wait(config.Cooldown.Value)
end
task.wait(0.01)
if newTower and newTower.Parent then
tower.Attack(newTower, player)
end
end
function tower.ChangeMode(player, model)
if model and model:FindFirstChild("Config") then
local targetMode = model.Config.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 tower mode")
return false
end
end
changeModeFunction.OnServerInvoke = tower.ChangeMode
function tower.Sell(player, model)
if model and model:FindFirstChild("Config") then
if model.Config.Owner.Value == player.Name then
player.PlacedTowers.Value -= 1
player.Cash.Value += model.Config.Price.Value / 2
model:Destroy()
return true
end
end
warn("Unable to sell this tower")
return false
end
sellTowerFunction.OnServerInvoke = tower.Sell
function tower.Spawn(player, name, cframe, previous)
local allowedToSpawn = tower.CheckSpawn(player, name, previous)
if allowedToSpawn then
local newTower
local oldMode = nil
if previous then
oldMode = previous.Config.TargetMode.Value
previous:Destroy()
newTower = ReplicatedStorage.Towers.Upgrades[name]:Clone()
else
newTower = ReplicatedStorage.Towers[name]:Clone()
player.PlacedTowers.Value += 1
end
local ownerValue = Instance.new("StringValue")
ownerValue.Name = "Owner"
ownerValue.Value = player.Name
ownerValue.Parent = newTower.Config
local targetMode = Instance.new("StringValue")
targetMode.Name = "TargetMode"
targetMode.Value = oldMode or "First"
targetMode.Parent = newTower.Config
newTower.HumanoidRootPart.CFrame = cframe
newTower.Parent = workspace.Towers
newTower.HumanoidRootPart:SetNetworkOwner(nil)
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
for i, object in ipairs(newTower:GetDescendants()) do
if object:IsA("BasePart") then
PhysicsService:SetPartCollisionGroup(object, "Tower")
end
end
player.Cash.Value -= newTower.Config.Price.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
info.Wave.Changed:Connect(function()
if #workspace.Mobs:GetChildren() == 0 then
if info.Wave.Value == 6 then
wait(0.1)
for i, players in ipairs(Players:GetPlayers()) do
players.PlacedTowers.Value = 0
players.Cash.Value += 750
end
end
end
end)
info.Wave.Changed:Connect(function()
if #workspace.Mobs:GetChildren() == 0 then
if info.Wave.Value == 11 then
wait(0.1)
for i, players in ipairs(Players:GetPlayers()) do
players.PlacedTowers.Value = 0
players.Cash.Value += 1500
end
end
end
end)
info.Wave.Changed:Connect(function()
if #workspace.Mobs:GetChildren() == 0 then
if info.Wave.Value == 16 then
wait(0.1)
for i, players in ipairs(Players:GetPlayers()) do
players.PlacedTowers.Value = 0
players.Cash.Value += 3000
end
end
end
end)
function tower.CheckSpawn(player, name, previous)
local towerExists = ReplicatedStorage.Towers:FindFirstChild(name, true)
if towerExists then
if towerExists.Config.Price.Value <= player.Cash.Value then
if previous or player.PlacedTowers.Value < maxTowers then
return true
else
warn("Player has 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 ```