Towers don't want to attack

I have a problem where towers don’t want to attack enemies and it doesn’t show me any errors on the output
image

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