Bug with my punching script

So basically I have a punching script, but for some reason if you punch the air about 2 times and you hit the npc on the 3rd time it fires 3 times, which is bad. Here’s my code (I have a crit hit system too)

-- DONT WORRY THE ANIMATIONS WILL BE BETTER BUT LATER
local players = game:GetService("Players")
local rc = game.ReplicatedStorage
local UIS = game:GetService("UserInputService")
local anims = rc:WaitForChild("Animations")
local player = players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:FindFirstChild("Humanoid")
local leftPunchAnim = anims:WaitForChild("LeftPunch")
local leftPunchTrack = humanoid:LoadAnimation(leftPunchAnim)
local rightPunchAnim = anims:WaitForChild("RightPunch")
local rightPunchTrack = humanoid:LoadAnimation(rightPunchAnim)
local attacking = false
local critAttacking = false
local doLeft = true
local doRight = false
local punchSound = script.Parent:FindFirstChild("Punch Sound Effect")
local critSound = script.Parent:FindFirstChild("DBZ Sound effect Strong Punch")
local numAttack = 0
UIS.InputBegan:Connect(function(input) -- Did the user click a key? If so, fire.
	if input.UserInputType == Enum.UserInputType.MouseButton1 then -- Was it a left click with mouse?
		if attacking == true then return end -- If the user is attacking, don't fire.
		if critAttacking == true then return end
		attacking = true
		task.delay(0.52, function() -- Will delay for 0.52 seconds before allowing user to attack again
			attacking = false
			doRight = not doRight
			doLeft = not doLeft
		end)
		local attacked = false 
		if doLeft == true and doRight == false then -- Left Arm's turn to punch
			leftPunchTrack:Play()
			character:WaitForChild("Left Arm").Touched:Connect(function(hit) -- Fires when left arm is touched.
				local humanoid = hit.Parent:FindFirstChild("Humanoid") or hit.Parent.Parent:FindFirstChild("Humanoid") or hit:FindFirstChild("Humanoid") 
				if humanoid then
					if attacked == true then return end
					attacked = true
					task.wait(0.52, function() -- Waits 0.52 seconds before allowing the user to deal damage.
						attacked = false -- You can now deal damage again!
					end)
					numAttack += 1
					print(numAttack)
					if numAttack == 4 then -- if it's the 4th hit, make it critical
						numAttack = 0
						critAttacking = true
						humanoid:TakeDamage(5)
						critSound:Play()
						task.delay(1.2, function()
							critAttacking = false
						end)
					else -- If it's not, make it a normal attack.
						humanoid:TakeDamage(3)
						punchSound:Play()
					end
				end
			end)
		else -- Right Arm's turn to punch
			rightPunchTrack:Play()
			character:WaitForChild("Right Arm").Touched:Connect(function(hit)
				local humanoid = hit.Parent:FindFirstChild("Humanoid") or hit.Parent.Parent:FindFirstChild("Humanoid") or hit:FindFirstChild("Humanoid") 
				if humanoid then
					if attacked == true then return end
					attacked = true
					task.wait(0.52, function()
						attacked = false
					end)
					numAttack += 1
					print(numAttack)
					if numAttack == 4 then
						numAttack = 0
						critAttacking = true
						humanoid:TakeDamage(5)
						critSound:Play()
						task.delay(1.2, function()
							critAttacking = false
						end)
					else
						humanoid:TakeDamage(3)
						punchSound:Play()
					end
				end
			end)
		end
	end
end)

I wish I could post a vid but I can’t.

Does anyone know how to fix this?

1 Like

try this:

-- DONT WORRY THE ANIMATIONS WILL BE BETTER BUT LATER
local players = game:GetService("Players")
local rc = game.ReplicatedStorage
local UIS = game:GetService("UserInputService")
local anims = rc:WaitForChild("Animations")
local player = players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:FindFirstChild("Humanoid")
local leftPunchAnim = anims:WaitForChild("LeftPunch")
local leftPunchTrack = humanoid:LoadAnimation(leftPunchAnim)
local rightPunchAnim = anims:WaitForChild("RightPunch")
local rightPunchTrack = humanoid:LoadAnimation(rightPunchAnim)
local attacking = false
local critAttacking = false
local doLeft = true
local doRight = false
local punchSound = script.Parent:FindFirstChild("Punch Sound Effect")
local critSound = script.Parent:FindFirstChild("DBZ Sound effect Strong Punch")
local numAttack = 0

UIS.InputBegan:Connect(function(input) -- Did the user click a key? If so, fire.
	if input.UserInputType == Enum.UserInputType.MouseButton1 then -- Was it a left click with mouse?
		if attacking == true then return end -- If the user is attacking, don't fire.
		if critAttacking == true then return end
		attacking = true
		local connect
		task.delay(0.52, function() -- Will delay for 0.52 seconds before allowing user to attack again
			if connect then
				connect:Disconnect()
			end
			attacking = false
			doRight = not doRight
			doLeft = not doLeft
		end)
		local attacked = false 
		if doLeft == true and doRight == false then -- Left Arm's turn to punch
			leftPunchTrack:Play()
			connect = character:WaitForChild("Left Arm").Touched:Connect(function(hit) -- Fires when left arm is touched.
				local humanoid = hit.Parent:FindFirstChild("Humanoid") or hit.Parent.Parent:FindFirstChild("Humanoid") or hit:FindFirstChild("Humanoid") 
				if humanoid then
					if attacked == true then return end
					attacked = true
					task.wait(0.52, function() -- Waits 0.52 seconds before allowing the user to deal damage.
						attacked = false -- You can now deal damage again!
					end)
					numAttack += 1
					print(numAttack)
					if numAttack == 4 then -- if it's the 4th hit, make it critical
						numAttack = 0
						critAttacking = true
						humanoid:TakeDamage(5)
						critSound:Play()
						task.delay(1.2, function()
							critAttacking = false
						end)
					else -- If it's not, make it a normal attack.
						humanoid:TakeDamage(3)
						punchSound:Play()
					end
					connect:Disconnect()
				end
			end)

		else -- Right Arm's turn to punch
			rightPunchTrack:Play()
			connect = character:WaitForChild("Right Arm").Touched:Connect(function(hit)
				local humanoid = hit.Parent:FindFirstChild("Humanoid") or hit.Parent.Parent:FindFirstChild("Humanoid") or hit:FindFirstChild("Humanoid") 
				if humanoid then
					if attacked == true then return end
					attacked = true
					task.wait(0.52, function()
						attacked = false
					end)
					numAttack += 1
					print(numAttack)
					if numAttack == 4 then
						numAttack = 0
						critAttacking = true
						humanoid:TakeDamage(5)
						critSound:Play()
						task.delay(1.2, function()
							critAttacking = false
						end)
					else
						humanoid:TakeDamage(3)
						punchSound:Play()
					end
					connect:Disconnect()
				end
			end)
		end
	end

i just disconnect the function when the punch stops or when it hits a player

1 Like

oh my god so many errors what is this

1 Like

this just can’t work there are so many errors it’s beyond repair

1 Like

i recommend just rewriting the script because im getting a head ache from reading some of it

2 Likes

Your using Touched events for the attack system. Maybe you need to use debounces?

1 Like

You need to disconnect the touch event at the end of the punch. Heres how your script logic is working right now.

Punch 1 : creates 1x touched connection
Punch2 : creates another touched connection for a total of 2 connections
Punch 3: creates a 3rd touched connection
Touched.Event Fired: All 3 connections to this event will run

Solution: At the end of each punch disconnect the touched event.
Is this in a local script? You should handle the damage on the server because I’m pretty sure it won’t replicate.
Also please rewrite the script, Its very difficult to read.

2 Likes