I have a problem where towers don’t want to attack enemies and it doesn’t show me any errors on the output
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local Debris = game:GetService("Debris")
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.Grassland
local maxTowers = 25
local tower = {}
function tower.Optimize(towerToOptimize) -- Optymalizuje wieże
local humanoid = towerToOptimize:FindFirstChild("Humanoid")
if towerToOptimize:FindFirstChild("HumanoidRootPart") then
towerToOptimize.HumanoidRootPart:SetNetworkOwner(nil)
elseif towerToOptimize.PrimaryPart ~= nil then
towerToOptimize.PrimaryPart:SetNetworkOwner(nil)
end
if not humanoid then return end
humanoid:SetStateEnabled(Enum.HumanoidStateType.Seated, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.Running, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.Climbing, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.Landed, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.Freefall, false)
end
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
if mob:FindFirstChild("HumanoidRootPart") and mob:FindFirstChild("MovingTo") then
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
if bestWaypoint then
bestDistance = nil
end
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
end
return bestTarget
end
function tower.FaceTarget(newTower, target, duration)
local targetVector = Vector3.new(target.PrimaryPart.Position.X, newTower.PrimaryPart.Position.Y, target.PrimaryPart.Position.Z)
local targetCFrame = CFrame.new(newTower.PrimaryPart.Position, targetVector)
local tweenInfo = TweenInfo.new(duration, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false, 0)
local faceTargetTween = TweenService:Create(newTower.PrimaryPart, tweenInfo, {CFrame = targetCFrame})
faceTargetTween:Play()
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
for i, plr in pairs(game.Players:GetChildren()) do
if target.Humanoid.Health < config.Damage.Value then
player.Gold.Value += target.Humanoid.MaxHealth
else
player.Gold.Value += config.Damage.Value
end
end
tower.FaceTarget(newTower, target, 0)
animateTowerEvent:FireAllClients(newTower, "Attack", target)
if newTower.Config.ProjValue.Value == 0 then
target.Humanoid:TakeDamage(config.Damage.Value)
end
wait()
if newTower.Config.ProjValue.Value == 1 then
local Projectile = ReplicatedStorage.Projectiles:FindFirstChild(config.Projectile.Value):Clone()
local offset = Vector3.new(math.random(-1, 1), 0, math.random(-1, 1))
Projectile.Parent = workspace
Projectile.CFrame = newTower.HumanoidRootPart.CFrame
local tweeninfo = TweenInfo.new(0.35)
local target2 = {Position = newTower.TargetPart.Position}
local tween2 = TweenService:Create(Projectile, tweeninfo, target2)
wait(0.01)
tween2:Play()
Debris:AddItem(Projectile, 0.35)
Projectile.Touched:Connect(function(hit)
if hit.Parent.Parent == workspace.Mobs then
if hit.Parent.Parent.Humanoid.Health > 0 then
hit.Parent.Humanoid:TakeDamage(config.Damage.Value)
player.Gold.Value += newTower.Config.Damage.Value
if hit.Parent.Humanoid.Health <= 0 then
player.Gold.Value += hit.Parent.Humanoid.Health
end
wait(.35)
Projectile:Destroy()
end
end
end)
end
if newTower.Config.ProjValue.Value >= 2 then
local Projectile = ReplicatedStorage.Projectiles:FindFirstChild(config.Projectile.Value):Clone()
local offset = Vector3.new(math.random(-1, 1), 0, math.random(-1, 1))
Projectile.Parent = workspace
Projectile.CFrame = newTower.HumanoidRootPart.CFrame
local tweeninfo = TweenInfo.new(0.5)
local target2 = {Position = newTower.TargetPart.Position + offset}
local tween2 = TweenService:Create(Projectile, tweeninfo, target2)
wait(0.01)
tween2:Play()
Debris:AddItem(Projectile, 0.35)
Projectile.Touched:Connect(function(hit)
if hit.Parent.Parent == workspace.Mobs then
if hit.Parent.Humanoid.Health > 0 then
hit.Parent.Humanoid:TakeDamage(config.Damage.Value)
player.Gold.Value += newTower.Config.Damage.Value
if hit.Parent.Humanoid.Health <= 0 then
player.Gold.Value += hit.Parent.Humanoid.Health
end
wait(.35)
Projectile:Destroy()
end
end
end)
end
if newTower.Config.ProjValue.Value >= 3 then
local Projectile = ReplicatedStorage.Projectiles:FindFirstChild(config.Projectile.Value):Clone()
local offset = Vector3.new(math.random(-1, 1), 0, math.random(-1, 1))
Projectile.Parent = workspace
Projectile.CFrame = newTower.HumanoidRootPart.CFrame
local tweeninfo = TweenInfo.new(0.35)
local target2 = {Position = newTower.TargetPart.Position + offset}
local tween2 = TweenService:Create(Projectile, tweeninfo, target2)
wait(0.01)
tween2:Play()
Debris:AddItem(Projectile, 0.35)
Projectile.Touched:Connect(function(hit)
if hit.Parent.Parent == workspace.Mobs then
if hit.Parent.Humanoid.Health > 0 then
hit.Parent.Humanoid:TakeDamage(config.Damage.Value)
player.Gold.Value += newTower.Config.Damage.Value
if hit.Parent.Humanoid.Health <= 0 then
player.Gold.Value += hit.Parent.Humanoid.Health
end
wait(.35)
Projectile:Destroy()
end
end
end)
end
if newTower.Config.ProjValue.Value >= 4 then
local Projectile = ReplicatedStorage.Projectiles:FindFirstChild(config.Projectile.Value):Clone()
local offset = Vector3.new(math.random(-1, 1), 0, math.random(-1, 1))
Projectile.Parent = workspace
Projectile.CFrame = newTower.HumanoidRootPart.CFrame
local tweeninfo = TweenInfo.new(0.35)
local target2 = {Position = newTower.TargetPart.Position + offset}
local tween2 = TweenService:Create(Projectile, tweeninfo, target2)
wait(0.01)
tween2:Play()
Debris:AddItem(Projectile, 0.35)
Projectile.Touched:Connect(function(hit)
if hit.Parent.Parent == workspace.Mobs then
if hit.Parent.Humanoid.Health > 0 then
hit.Parent.Humanoid:TakeDamage(config.Damage.Value)
player.Gold.Value += newTower.Config.Damage.Value
if hit.Parent.Humanoid.Health <= 0 then
player.Gold.Value += hit.Parent.Humanoid.Health
end
wait(.35)
Projectile:Destroy()
end
end
end)
end
if newTower.Config.ProjValue.Value >= 5 then
local Projectile = ReplicatedStorage.Projectiles:FindFirstChild(config.Projectile.Value):Clone()
local offset = Vector3.new(math.random(-1, 1), 0, math.random(-1, 1))
Projectile.Parent = workspace
Projectile.CFrame = newTower.HumanoidRootPart.CFrame
local tweeninfo = TweenInfo.new(0.35)
local target2 = {Position = newTower.TargetPart.Position + offset}
local tween2 = TweenService:Create(Projectile, tweeninfo, target2)
wait(0.01)
tween2:Play()
Debris:AddItem(Projectile, 0.35)
Projectile.Touched:Connect(function(hit)
if hit.Parent.Parent == workspace.Mobs then
if hit.Parent.Humanoid.Health > 0 then
hit.Parent.Humanoid:TakeDamage(config.Damage.Value)
player.Gold.Value += newTower.Config.Damage.Value
if hit.Parent.Humanoid.Health <= 0 then
player.Gold.Value += hit.Parent.Humanoid.Health
end
wait(.35)
Projectile:Destroy()
end
end
end)
end
if newTower.Config.ProjValue.Value >= 6 then
local Projectile = ReplicatedStorage.Projectiles:FindFirstChild(config.Projectile.Value):Clone()
local offset = Vector3.new(math.random(-1, 1), 0, math.random(-1, 1))
Projectile.Parent = workspace
Projectile.CFrame = newTower.HumanoidRootPart.CFrame
local tweeninfo = TweenInfo.new(0.35)
local target2 = {Position = newTower.TargetPart.Position + offset}
local tween2 = TweenService:Create(Projectile, tweeninfo, target2)
wait(0.01)
tween2:Play()
Debris:AddItem(Projectile, 0.35)
Projectile.Touched:Connect(function(hit)
if hit.Parent.Parent == workspace.Mobs then
if hit.Parent.Humanoid.Health > 0 then
hit.Parent.Humanoid:TakeDamage(config.Damage.Value)
player.Gold.Value += newTower.Config.Damage.Value
if hit.Parent.Humanoid.Health <= 0 then
player.Gold.Value += hit.Parent.Humanoid.Health
end
wait(.35)
Projectile:Destroy()
end
end
end)
end
if newTower.Config.ProjValue.Value >= 7 then
local Projectile = ReplicatedStorage.Projectiles:FindFirstChild(config.Projectile.Value):Clone()
local offset = Vector3.new(math.random(-1, 1), 0, math.random(-1, 1))
Projectile.Parent = workspace
Projectile.CFrame = newTower.HumanoidRootPart.CFrame
local tweeninfo = TweenInfo.new(0.35)
local target2 = {Position = newTower.TargetPart.Position + offset}
local tween2 = TweenService:Create(Projectile, tweeninfo, target2)
wait(0.01)
tween2:Play()
Debris:AddItem(Projectile, 0.35)
Projectile.Touched:Connect(function(hit)
if hit.Parent.Parent == workspace.Mobs then
if hit.Parent.Humanoid.Health > 0 then
hit.Parent.Humanoid:TakeDamage(config.Damage.Value)
player.Gold.Value += newTower.Config.Damage.Value
if hit.Parent.Humanoid.Health <= 0 then
player.Gold.Value += hit.Parent.Humanoid.Health
end
wait(.35)
Projectile:Destroy()
end
end
end)
end
if newTower.Config.ProjValue.Value >= 8 then
local Projectile = ReplicatedStorage.Projectiles:FindFirstChild(config.Projectile.Value):Clone()
local offset = Vector3.new(math.random(-1, 1), 0, math.random(-1, 1))
Projectile.Parent = workspace
Projectile.CFrame = newTower.HumanoidRootPart.CFrame
local tweeninfo = TweenInfo.new(0.35)
local target2 = {Position = newTower.TargetPart.Position + offset}
local tween2 = TweenService:Create(Projectile, tweeninfo, target2)
wait(0.01)
tween2:Play()
Debris:AddItem(Projectile, 0.35)
Projectile.Touched:Connect(function(hit)
if hit.Parent.Parent == workspace.Mobs then
if hit.Parent.Humanoid.Health > 0 then
hit.Parent.Humanoid:TakeDamage(config.Damage.Value)
player.Gold.Value += newTower.Config.Damage.Value
if hit.Parent.Humanoid.Health <= 0 then
player.Gold.Value += hit.Parent.Humanoid.Health
end
wait(.35)
Projectile:Destroy()
end
end
end)
end
task.wait(config.Cooldown.Value)
end
task.wait(0.1)
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.Gold.Value += model.Config.Price.Value
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
tower.Optimize(newTower)
for i, object in ipairs(newTower:GetDescendants()) do
if object:IsA("BasePart") then
PhysicsService:SetPartCollisionGroup(object, "Tower")
end
end
player.Gold.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
function tower.CheckSpawn(player, name, previous)
local towerExists = ReplicatedStorage.Towers:FindFirstChild(name, true)
if towerExists then
if towerExists.Config.Price.Value <= player.Gold.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("That tower does not exist")
end
return false
end
requestTowerFunction.OnServerInvoke = tower.CheckSpawn
return tower