Hi, I’ve got a tower handler module for my tower defense game. Inside the tower handler there’s a tower.Attack() function that is responsible for, well, tower attacks. Everything inside it is wrapped in pcalls, yet there still seem to be errors.

function tower.Attack(newTower: Model, player: Player)
pcall(function()
local config = newTower:WaitForChild("Config")
local data = newTower:WaitForChild("TowerData")
local success, msg = pcall(function()
if data:GetAttribute("CanAttack") == false then return end
if data:GetAttribute("AttackCount") and config:GetAttribute("SpecialAttackMode") == "Separately" and data:GetAttribute("AttackCount") >= config.AttacksNeededForSpecial.Value then
local target = targetModule.FindTarget(newTower, config.Range.Value, config.TargetMode.Value)
if target and target.Attributes:GetAttribute("Health") > 0 then
if newTower.Animations:FindFirstChild("SpecialAttack") then
animateTowerEvent:FireAllClients(newTower, "SpecialAttack", target)
end
specialAttacks[config.SpecialName.Value](player, newTower, target)
data:SetAttribute("AttackCount", 0)
end
else
local amountOfShots = 1
if config:FindFirstChild("Burst") then amountOfShots = config.Burst.Value end
local target = targetModule.FindTarget(newTower, config.Range.Value, config.TargetMode.Value)
if target and target:FindFirstChild("Attributes") then
local attributes = target:FindFirstChild("Attributes")
if (not attributes) or (attributes:GetAttribute("Health") <= 0) then return end
local targetPos = attributes:GetAttribute("Position")
pcall(function()
if config:FindFirstChild("PrepTime") then
if not data:GetAttribute("Prepared") then
local targetCFrame = CFrame.lookAt(newTower.HumanoidRootPart.Position, Vector3.new(targetPos.X, newTower.HumanoidRootPart.Position.Y, targetPos.Z))
newTower.HumanoidRootPart.BodyGyro.CFrame = targetCFrame
animateTowerEvent:FireAllClients(newTower, "AttackPrep", target)
task.wait(config:FindFirstChild("PrepTime").Value)
data:SetAttribute("Prepared", true)
if not target then
target = targetModule.FindTarget(newTower, config.Range.Value, config.TargetMode.Value)
if not target then return end
end
end
end
data:SetAttribute("Shooting", true)
for i = 1, amountOfShots do
target = targetModule.FindTarget(newTower, config.Range.Value, config.TargetMode.Value)
if target and target:FindFirstChild("Attributes") and attributes:GetAttribute("Health") > 0 then
if data:GetAttribute("AttackCount") and config:GetAttribute("SpecialAttackMode") == "Together" and data:GetAttribute("AttackCount") >= config.AttacksNeededForSpecial.Value then
if newTower.Animations:FindFirstChild("SpecialAttack") then
animateTowerEvent:FireAllClients(newTower, "SpecialAttack", target)
end
specialAttacks[config.SpecialName.Value](player, newTower, target)
data:SetAttribute("AttackCount", 0)
end
attackFunctionsModule.Shoot(newTower, target, data, player, config, config:FindFirstChild("DistanceDamage"))
end
if amountOfShots > 1 then
task.wait(0.15)
end
end
end)
if config:FindFirstChild("Cooldown") then
task.wait(config.Cooldown.Value)
else
return
end
else
data:SetAttribute("Shooting", false)
if data:GetAttribute("Prepared") ~= nil then
data:SetAttribute("Prepared", false)
end
end
end
end)
if not success then warn(msg) end
task.wait()
if newTower and newTower.Parent then
while (newTower.Parent) and (data:GetAttribute("Stunned") or not data:GetAttribute("CanAttack")) do
task.wait()
end
tower.Attack(newTower, player)
end
end)
if newTower.Parent then
tower.Attack(newTower, player)
end
end
Here’s the function. The error comes from the second pcall - I don’t know why. Could tell me why and help come up with a solution?