Script Does Extra Damage When Not Supposed to and Shoots too Many Enemies at Once

This script I am making for a tower defense game I am making for practice is not working right. It does too much damage; it is supposed to do one damage each shot but it only does so for the first shot it fires. After this, it does extra damage each time it fires, for example, it does 2 damage when it is supposed to do one. It also shoots multiple targets at once after the first shot which is not supposed to happen. I was reluctant to talk about this since I already posted a problem in this game I was having days ago but it has been several hours in total that I have been working on this and I am not sure how to fix this.

local militia = script.Parent
local maxDistance = 40
local RS = game:GetService("RunService")
local debounce = false
local sound = Instance.new("Sound", militia)

RS.Stepped:Connect(function()
	local nearestTarget = nil
	if debounce == false then
		if #workspace.SpawnedEnemies:GetChildren() == 0 then
			return
		else
		debounce = true
		for i, Target in ipairs(workspace.SpawnedEnemies:GetChildren()) do
			local distance = (militia.HumanoidRootPart.Position - Target.HumanoidRootPart.Position).Magnitude
			if distance <= maxDistance then
					nearestTarget = Target
				local findhealth = nearestTarget:FindFirstChild("Health")
					if findhealth then
						local findHumanoidRootPart = nearestTarget:FindFirstChild("HumanoidRootPart")
						if not findHumanoidRootPart then
							return
						else
							militia.HumanoidRootPart.CFrame = CFrame.lookAt(militia.HumanoidRootPart.Position, findHumanoidRootPart.Position)
						sound.SoundId = "9070225429"
						sound:Play()
						findhealth.Value -= 1
						wait(2)
							debounce = false
						end
					end
				end
			end
		end
	end
end)

2 Likes

I commented all the lines I changed. If it doesn’t work right or throws an error, let me know.

Edit: Moved debounce = false line

local militia = script.Parent
local maxDistance = 40
local RS = game:GetService("RunService")
local debounce = false
local sound = Instance.new("Sound", militia)

RS.Stepped:Connect(function()
	local nearestTarget = nil
	local nearestTargetDistance = math.huge -- Added this so you can compare the distance of each SpawnedEnemy you loop through
	if debounce == false then
		if #workspace.SpawnedEnemies:GetChildren() == 0 then
			return
		else
			debounce = true
			for i, Target in ipairs(workspace.SpawnedEnemies:GetChildren()) do
				local distance = (militia.HumanoidRootPart.Position - Target.HumanoidRootPart.Position).Magnitude
				if distance <= maxDistance and distance < nearestTargetDistance then -- Added a second check for this to check if Target distance is less than previously checked nearestTarget distance
					nearestTargetDistance = distance -- Set nearestTargetDistance to the closest distance so it can be used to compare the next Targets distance in the loop
					nearestTarget = Target
				end
			end --Added 2 "ends" here to close this loop that gets the nearestTarget
			local findhealth = nearestTarget:FindFirstChild("Health")
			if findhealth then
				local findHumanoidRootPart = nearestTarget:FindFirstChild("HumanoidRootPart")
				if findHumanoidRootPart then
					militia.HumanoidRootPart.CFrame = CFrame.lookAt(militia.HumanoidRootPart.Position, findHumanoidRootPart.Position)
					sound.SoundId = "9070225429"
					sound:Play()
					findhealth.Value -= 1
					wait(2)
				end
			end
			debounce = false -- Moved debounce to here, previously it was possible where debounce never gets set back to false if a condition isn't met, causing the script to never run again since debounce is true forever
		end -- Removed 2 "ends" here and moved them to close the loop mentioned up there ^
	end
end)
2 Likes
local militia = script.Parent
local maxDistance = 40
local RS = game:GetService("RunService")
local debounce = false
local sound = Instance.new("Sound", militia)

RS.Stepped:Connect(function()
	if debounce == false then
		if #workspace.SpawnedEnemies:GetChildren() == 0 then return end
		local MilHRP = militia:FindFirstChild("HumanoidRootPart")
		if not MilHRP then return end
		debounce = true
		local BestTarget = nil
		for i, Target in ipairs(workspace.SpawnedEnemies:GetChildren()) do
			local TargHRP = Target:FindFirstChild("HumanoidRootPart")
			if not TargetHRP then continue end
			local TargHealth = Target:FindFirstChild("Health")
			if not TargHealth then continue end
			local distance = (MilHRP.Position - TargetHRP.Position).Magnitude
			if distance > maxDistance then continue end
			if BestTarget == nil then
				BestTarget = {{TargHRP, TargHealth}, distance}
				continue
			else
				if BestTarget[2] > distance then
					BestTarget = {{TargHRP, TargHealth}, distance}
				end
			end
		end
		if BestTarget then
			local TargHRP = BestTarget[1][1]
			local TargHealth = BestTarget[1][2]
			MilHRP.CFrame = CFrame.lookAt(MilHRP.Position, TargHrp.Position)
			sound.SoundId = "9070225429"
			sound:Play()
			TargHealth.Value -= 1
			wait(2)
		end
		debounce = false
	end
end)
1 Like

Thank you, this helped me. I was having trouble with this.

Thank you, this helped me. I was having a lot of trouble with this for a simple mistake.

1 Like