Weapon deals way more damage than supposed to

Hello, everyone! I’m trying to make a combat system for specific weapons and I found that my weapon, instead of doing 20 damage per hit, deals well over 100+. Any way to stop that?
Hit Function

local function onTouch(partOther)

	local humanOther = partOther.Parent:FindFirstChild("Humanoid")

	if not humanOther then return end

	if humanOther.Parent == Tool then return end
	
	humanOther:TakeDamage(20)
end

and Mouse Clicked function:

Tool.Equipped:Connect(function(Mouse)
	Mouse.Button1Down:Connect(function()
		if db == false then
			db = true
			animtrack2:Play()
			animtrack2.Stopped:wait()
			animtrack:Play()
			wait(0.7)
			shakeCamera(0.6)
			local Connection
			Connection = Tool:WaitForChild("Hammer").Touched:Connect(onTouch)
			wait()
			Connection:Disconnect()
			db = false
		end
	end)
end)

Video showing the bug:


EDIT: Also, it seems kinda delayed which it wasn’t earlier, before I modified the code again

Add a print("Hit") statement in to your onTouch function then test. In the Output window, you will probably see the Hit printing multiple times as the Touch fires repeatedly.
You would need to add a cooldown/debounce to the weapon to stop the Touch repeatedly firing.

You need to add a local variable to check if the weapon already damaged.

Only allow the humanoid to be damaged when the damage variable is false.

When it damaged make sure to se it to true.

This avoids damaging multiple times

Can’t seem to make it work, a little help?

Tool.Equipped:Connect(function(Mouse)
	Mouse.Button1Down:Connect(function()
		if db == false then
			db = true
			animtrack2:Play()
			animtrack2.Stopped:wait()
			animtrack:Play()
			wait(0.6)
			shakeCamera(0.6)
			local Connection
			if damagedb == false then
				Connection = Tool:WaitForChild("Hammer").Touched:Connect(onTouch)
                wait()
				Connection:Disconnect()
				damagedb = true
			end
			db = false
			damagedb = false
		end
	end)
end)

Have you tried like this?

local Connection
if damagedb == false then
     damagedb = true
     Connection = Tool:WaitForChild("Hammer").Touched:Connect(onTouch)
     wait()
     Connection:Disconnect()
     end
db = false
damagedb = false

So the debounce is before the touch event btw

still can’t manage to make it deal less damage.

Tool.Equipped:Connect(function(Mouse)
	Mouse.Button1Down:Connect(function()
		if db == false then
			db = true
			animtrack2:Play()
			animtrack2.Stopped:wait()
			animtrack:Play()
			wait(0.6)
			shakeCamera(0.6)
			local Connection
			if damagedb == false then
				damagedb = true
				Connection = Tool:WaitForChild("Hammer").Touched:Connect(onTouch)
				wait()
				Connection:Disconnect()
			end
			db = false
			damagedb = false
		end
	end)
end)

the Exact code I wrote

You’re using a .Touched event, meaning it could be hitting multiple times, and because of the damage it is dealing, it is applying it over and over again, like @BadDad2004 says;

You should follow his advice.

Because you’re only running it when it is used, get the function it’s connecting to and make the variable and check for it instead.

how do I add a debounce for the damage?

Edit: Also, it hits like 10 times if positioned correctly

Tool function;

local function onTouch(partOther)

	local humanOther = partOther.Parent:FindFirstChild("Humanoid")

	if not humanOther then return end

	if humanOther.Parent == Tool then return end
	
        if damagedb then return end

	humanOther:TakeDamage(20)
end

You forgot to edit the function, it’s only checking to fire it when its actually used, the touched is still being connected and firing multiple times in a short ammount of time.

The connection you set up that detects touches can fire multiple times; disconnecting it right after connecting it doesn’t guarantee that it’ll fire once. Sometimes it won’t fire at all, because you’re assuming it’ll hit something in the time that you wait before disconnecting it.

What you should be doing is setting up another variable that prevents additional damage from the same attack from being dealt, as well as a separate event listener:

local db = false
local canDmg = true

local hammer = Tool:WaitForChild("Hammer")

Tool.Equipped:Connect(function(Mouse)
	Mouse.Button1Down:Connect(function()
		if db == false then
			db = true
            canDmg = true
			animtrack2:Play()
			animtrack2.Stopped:wait()
			animtrack:Play()
			wait(0.7)
			shakeCamera(0.6)
			db = false
            canDmg = false
		end
	end)
end)

hammer.Touched:Connect(function(hit)
     if (not canDmg) then return end
     canDmg = false
     onTouch(hit)
end)

doesn’t seem to work… I also tried a print() after


	if (not canDmg) then return end
	canDmg = false
	onTouch(hit)

Output doesn’t print anything

if I probably did something wrong, here’s the full code.

local player = game.Players.LocalPlayer
local Tool = script.Parent --make sure this is a Tool object
local db = false
local blade = Tool:WaitForChild("Damage")

local function shakeCamera(length)

	local startTime = tick()

	while true do

		if tick() - startTime >= length then break end

		local x = math.random(-100, 100) / 1000
		local y = math.random(-100, 100) / 1000
		local z = math.random(-100, 100) / 1000

		script.Parent.Parent.Humanoid.CameraOffset = Vector3.new(x, y, z)
		workspace.CurrentCamera.CFrame *= CFrame.Angles(x / 100, y / 100, z / 100)

		wait()
	end

	script.Parent.Parent.Humanoid.CameraOffset = Vector3.new(0, 0, 0)
end

local function onTouch(partOther)

	local humanOther = partOther.Parent:FindFirstChild("Humanoid")

	if not humanOther then return end

	if humanOther.Parent == Tool then return end

	if canDmg then return end

	humanOther:TakeDamage(20)
end

repeat wait(1) until player.Character

local character = player.Character
local humanoid = character:WaitForChild("Humanoid")

local animation2 = Instance.new("Animation")
animation2.Name = "Hold"
animation2.Parent = script.Parent

local animation = Instance.new("Animation")
animation.Name = "Slash"
animation.Parent = script.Parent

animation.AnimationId = "http://www.roblox.com/asset/?id=" .. "8425622968"
local animtrack = humanoid:LoadAnimation(animation)

animation2.AnimationId = "http://www.roblox.com/asset/?id=" .. "8425116224"
local animtrack2 = humanoid:LoadAnimation(animation2)


Tool.Equipped:Connect(function(Mouse)
	Mouse.Button1Down:Connect(function()
		if db == false then
			db = true
			canDmg = true
			animtrack2:Play()
			animtrack2.Stopped:wait()
			animtrack:Play()
			wait(0.7)
			shakeCamera(0.6)
			db = false
			canDmg = false
		end
	end)
end)

blade.Touched:Connect(function(hit)
	if (not canDmg) then return end
	canDmg = false
	onTouch(hit)
end)

Tool.Unequipped:Connect(function(Mouse)
	animtrack:Stop()
	animtrack2:Stop()
end)

Inside of the onTouch function, you put this:

if canDmg then return end

That’ll prevent the hammer from doing damage when it’s supposed to do damage; change it to this:

if not canDmg then return end

Besides, putting it in the function is redundant, as you already have it here:

blade.Touched:Connect(function(hit)
	if (not canDmg) then return end
	canDmg = false
	onTouch(hit)
end)

You also need to add the canDmg variable to the top of the script so the function can access it:

local player = game.Players.LocalPlayer
local Tool = script.Parent --make sure this is a Tool object
local db = false
local canDmg = true
local blade = Tool:WaitForChild("Damage")

The whole script should look like this:

local player = game.Players.LocalPlayer
local Tool = script.Parent --make sure this is a Tool object
local db = false
local canDmg = true
local blade = Tool:WaitForChild("Damage")

local function shakeCamera(length)

	local startTime = tick()

	while true do

		if tick() - startTime >= length then break end

		local x = math.random(-100, 100) / 1000
		local y = math.random(-100, 100) / 1000
		local z = math.random(-100, 100) / 1000

		script.Parent.Parent.Humanoid.CameraOffset = Vector3.new(x, y, z)
		workspace.CurrentCamera.CFrame *= CFrame.Angles(x / 100, y / 100, z / 100)

		wait()
	end

	script.Parent.Parent.Humanoid.CameraOffset = Vector3.new(0, 0, 0)
end

local function onTouch(partOther)

	local humanOther = partOther.Parent:FindFirstChild("Humanoid")

	if not humanOther then return end

	if humanOther.Parent == Tool then return end

	humanOther:TakeDamage(20)
end

repeat wait(1) until player.Character

local character = player.Character
local humanoid = character:WaitForChild("Humanoid")

local animation2 = Instance.new("Animation")
animation2.Name = "Hold"
animation2.Parent = script.Parent

local animation = Instance.new("Animation")
animation.Name = "Slash"
animation.Parent = script.Parent

animation.AnimationId = "http://www.roblox.com/asset/?id=" .. "8425622968"
local animtrack = humanoid:LoadAnimation(animation)

animation2.AnimationId = "http://www.roblox.com/asset/?id=" .. "8425116224"
local animtrack2 = humanoid:LoadAnimation(animation2)


Tool.Equipped:Connect(function(Mouse)
	Mouse.Button1Down:Connect(function()
		if db == false then
			db = true
			canDmg = true
			animtrack2:Play()
			animtrack2.Stopped:wait()
			animtrack:Play()
			wait(0.7)
			shakeCamera(0.6)
			db = false
			canDmg = false
		end
	end)
end)

blade.Touched:Connect(function(hit)
	if (not canDmg) then return end
	canDmg = false
	onTouch(hit)
end)

Tool.Unequipped:Connect(function()
	animtrack:Stop()
	animtrack2:Stop()
end)

You also put “Mouse” as a parameter in the Unequipped event listener that was attached to the Tool variable. The Equipped event is the only one of the two that has the Mouse parameter.

Thank you so much, but in order to HIT a target, the “blade” has to be touching the target before the animation, and if the animation plays, my character can’t damage the target