Simple Sword Problem

I was just finished making a simple sword by following a YouTube tutorial.However, I realized that in the end result, the damage is dealt immediately when anything comes in contact with the sword. I want to change it so that it only deals damage when the player clicks to swing the sword. I tried parenting another script to this one and then adjusting the disabled property of the parent script. Here is what the main script looks like:

script.Parent.Touched:Connect(function(hit)
	if hit.Parent:FindFirstChild("Humanoid") then
		hit.Parent.Humanoid:TakeDamage(30)
		script.Disabled = true
		wait(0.25)
		script.Disabled = false
		
	end
end)

How should I do it so that it only calls the function when the player clicks instead of when the sword touches something?

1 Like

Make a value that stores whether the sword is hitting or not. Like this:

local tool --change this to the tool
local blade --change this to the blade of the sword/damage part
local attacking = false
local hitdebounce = false

tool.Activated:Connect(function()
	spawn(function()--so this doesn't delay any other part of the script
		attacking = true
		tool.Disabled = true
		wait(0.25)
		attacking = false
		tool.Disabled = false
	end)
end)

blade.Touched:Connect(function(hit)
	if attacking and not hitdebounce then
		spawn(function() --again so it doesnt delay other parts of the script
			hitdebounce = true
			local humanoid = hit.Parent:FindFirstChild("Humanoid")
			if humanoid then
				humanoid:TakeDamage(30)
			end
			wait(0.25)
			hitdebounce = false
		end)
	end
end)
4 Likes

Not too sure, but I think that the following should work:

Attach a .Activated function to the sword, then when the player clicks, do :GetTouchingParts() on the tool, check if the part is a descendant of a character (You can also check if the character is a character of a player, and make it so you can only damage players.) , and then damage it. You can use :TakeDamage() to do damage but without ignoring a ForceField, or just lower the player’s health, ignoring ForceFields.

1 Like

I tried the code you gave me, but nothing happens when I swing. Heres my output:
image

1 Like

image

Fix this and try again

3 Likes

spawn is unnecessary in this case, as the function you pass to :Connect will already run on another thread, when the event gets fired; this means it won’t interfere with other parts of the script, as they run on a different thread.

Otherwise, the code you posted looks fine outside of that small typo that others have already pointed out.

3 Likes

I fixed the code and it started working! However, after the first click, the sword goes back to immediately dealing damage when it touches something. How would I fix this?

I’d avoid recommending others to use spawn. Not only is it unnecessary, but it’s also bad practice.

Here is an article that talks about why it’s bad.
Why Spawn Is Evil

If you need to create a new thread then use coroutine.wrap() instead.

local Tool = script.Parent
local Blade = Tool.Handle
local SwingTime = 0.55


local _Touched={}
local Swinging = false
Tool.Activated:Connect(function()
	if not Swinging then
		Swinging = true
		wait(SwingTime)
		Swinging = false
		_Touched = {}
	end
end)


Blade.Touched:Connect(function(hit)
	if Swinging and not table.find(_Touched, hit.Parent) then
		table.insert(_Touched, hit.Parent)
		local Humanoid = hit.Parent:FindFirstChild("Humanoid")
		if Humanoid ~= nil then
			Humanoid:TakeDamage(20)
		end
	end
end)
1 Like

you would have to disconnect it