Why doesn't my tool deal damage?

Hello! Today I made a damage script for a baseball bat. And it didn’t work on humanoids (players, npcs etc.) Here is the script:
r = game:service("RunService")

local damage = 15


local slash_damage = 15


sword = script.Parent.Handle
Tool = script.Parent


local SlashSound = Instance.new("Sound")
SlashSound.SoundId = ""
SlashSound.Parent = sword
SlashSound.Volume = .7


function blow(hit)
	local humanoid = hit.Parent:findFirstChild("Humanoid")
	local vCharacter = Tool.Parent
	local vPlayer = game.Players:playerFromCharacter(vCharacter)
	local hum = vCharacter:findFirstChild("Humanoid") -- non-nil if tool held by a character
	if humanoid~=nil and humanoid ~= hum and hum ~= nil then


		local right_arm = vCharacter:FindFirstChild("Right Arm")
		if (right_arm ~= nil) then
			local joint = right_arm:FindFirstChild("RightGrip")
			if (joint ~= nil and (joint.Part0 == sword or joint.Part1 == sword)) then
				tagHumanoid(humanoid, vPlayer)
				humanoid:TakeDamage(damage)
				wait(1)
				untagHumanoid(humanoid)
			end
		end


	end
end


function tagHumanoid(humanoid, player)
	local creator_tag = Instance.new("ObjectValue")
	creator_tag.Value = player
	creator_tag.Name = "creator"
	creator_tag.Parent = humanoid
end

function untagHumanoid(humanoid)
	if humanoid ~= nil then
		local tag = humanoid:findFirstChild("creator")
		if tag ~= nil then
			tag.Parent = nil
		end
	end
end


function attack()
	damage = slash_damage
	SlashSound:play()
	local anim = Instance.new("StringValue")
	anim.Name = "toolanim"
	anim.Value = "Slash"
	anim.Parent = Tool
end


function swordUp()
	Tool.GripForward = Vector3.new(-0.001, 0, 1)
	Tool.GripPos = Vector3.new(1, 0, 0.1)
	Tool.GripRight = Vector3.new(0, -1, 0)
	Tool.GripUp = Vector3.new(-1, 0, -0.001)
end

function swordOut()
	
	Tool.GripForward = Vector3.new(-0.001, 0, 1)
	Tool.GripPos = Vector3.new(1, 0, 0.1)
	Tool.GripRight = Vector3.new(0, -1, 0)
	Tool.GripUp = Vector3.new(-1, 0, -0.001)
end



Tool.Enabled = true

function onActivated()

	if not Tool.Enabled then
		return
	end

	Tool.Enabled = false

	local character = Tool.Parent;
	local humanoid = character.Humanoid
	if humanoid == nil then
		print("Humanoid not found")
		return 
	end

	

	attack()

	wait(.5)

	Tool.Enabled = true
end


function onEquipped()
	SlashSound:play()
end


script.Parent.Activated:connect(onActivated)
script.Parent.Equipped:connect(onEquipped)


connection = sword.Touched:connect(blow)

If this is a localscript, then it’s because the damage isn’t replicating to the server because of client-server network filtering.

5 Likes

@Blokav is 100% right. If you’re game has FilterningEnabled (which it should), then you need to do an action like damage, from the server. Here’s a place I’ve rigged with your code modified that shows you how to do it.

ToolDamage.rbxl (20.0 KB)

Alternatively, here are the steps to do it if you want to understand the fundamentals.

  1. Create a RemoteEvent in ReplicatedStorage (for the sake of example we will call it DamageEvent)

This is how your LocalScript will communicate with the Server. This is important, because when one player damages another player, that is a change that has to appear for everyone i.e. be done/facilitated by the server.


  1. Add this line to the top of your script where you defined your other variables
local DamageEvent = game:GetService("ReplicatedStorage"):WaitForChild("DamageEvent")

This is the variable that represents the RemoteEvent


  1. Create a script in ServerScriptService with these lines of code
local DamageEvent = game:GetService("ReplicatedStorage"):WaitForChild("DamageEvent") --// Remote Event to listen to

DamageEvent.OnServerEvent:Connect(function(Player, TargetHumanoid, DamageAmount)
	TargetHumanoid:TakeDamage(DamageAmount)
end)

This is what the server will do when the RemoteEvent is fired. By default, the Player instance of the client firing the RemoteEvent is always given as an argument of the function, although we don’t use it. When we fire the RemoteEvent, we will provide the Humanoid instance of the person who the damage will be dealt to and the damage amount


  1. Replace your original line of code
humanoid:TakeDamage(damage)

with

DamageEvent:FireServer(humanoid, damage)

This fires the RemoteEvent and provides the key arguments we set up the RemoteEvent to require - the target’s humanoid instance and the amount we want to damage them with


Your tool should now work properly!

(One last thing to note is that you may want to add some sort of damage debounce to your weapon. It’s very overpowered right now, as whenever an enemy touches the weapon they will be dealt 15 damage per touch (and what seems like one touch generally ends up being more than one - resulting in instant kills)! I would recommend adding these lines.

DamageDebounce = false

Add this somewhere near the top of your script, where you define your other variables then replace your blow function with the below code

function blow(hit)
	local humanoid = hit.Parent:findFirstChild("Humanoid")
	local vCharacter = Tool.Parent
	local vPlayer = game.Players:playerFromCharacter(vCharacter)
	local hum = vCharacter:findFirstChild("Humanoid") -- non-nil if tool held by a character
	if humanoid~=nil and humanoid ~= hum and hum ~= nil then


		local right_arm = vCharacter:FindFirstChild("Right Arm")
		if (right_arm ~= nil) then
			local joint = right_arm:FindFirstChild("RightGrip")
			if (joint ~= nil and (joint.Part0 == sword or joint.Part1 == sword)) then
				if DamageDebounce == false then
					DamageDebounce = true
					tagHumanoid(humanoid, vPlayer)
					DamageEvent:FireServer(humanoid, damage) --// Fire our RemoteEvent
					wait(1) --// This is key, as this is how much the script waits before allowing the player to damage another player again
					DamageDebounce = false
					untagHumanoid(humanoid)
				end
			end
		end
	end
end

Last but not least!

Make your functions local functions!

6 Likes