I need help with constant damaging bricks

I want to make a tool that spawns part and constantly damages any NPC that touches it.

But how roblox’s .touched work is not very good, it doesnt damage the NPC touching it constantly and it either just deals a bunch of damage or only dealing damage once. I need help with this!

code:

local tool = script.Parent
local damageAmount = 1 -- Adjust this to set the damage amount
local partTemplate = game.ReplicatedStorage.PartTemplate -- Replace with the path to your template part
local activePart = nil
local unequipConnection = nil
local UserInputService = game:GetService("UserInputService")

local holding = false

local function isNPC(character)
    -- Check if the character is an NPC by looking for a "Humanoid" and not a player's character
    return character and character:FindFirstChild("Humanoid") and not game.Players:GetPlayerFromCharacter(character)
end

tool.Activated:Connect(function()
    holding = true
    local player = game.Players:GetPlayerFromCharacter(tool.Parent)
    if not player then return end

    local character = player.Character
    local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
    if not humanoidRootPart then return end

    -- Calculate the spawn position in front of the character
    local spawnOffset = CFrame.new(0, 0, -7.5) -- Adjust the offset (-7.5) as needed
    local spawnPosition = humanoidRootPart.CFrame * spawnOffset

    -- Create the part at the calculated spawn position
    local part = partTemplate:Clone()
    part.CFrame = spawnPosition
    part.Parent = game.Workspace

    local function dealDamage(otherPart)
        local character = otherPart.Parent
        if isNPC(character) then
            local humanoid = character:FindFirstChild("Humanoid")
            if humanoid then
                humanoid:TakeDamage(damageAmount)
            end
        end
    end

    -- Add a Touched event to the part to deal damage
    part.Touched:Connect(dealDamage)

    -- Create a weld constraint between the part and HumanoidRootPart
    local weldConstraint = Instance.new("WeldConstraint")
    weldConstraint.Parent = part
    weldConstraint.Part0 = part
    weldConstraint.Part1 = humanoidRootPart

    -- Track the active part
    activePart = part
end)

tool.Deactivated:Connect(function()
    holding = false
    if activePart then
        activePart:Destroy()
    end
end)
1 Like

spam get touching parts with a while true and use that instead

it will always return parts touching, you can check for models parented with humanoids after

1 Like

How would I add a delay into it? Like a 0.5 second delay before the NPC takes another damage

1 Like

You can add a “debounce”. The general structure of a debounce:

local Debounce = nil
local function DoSomething()
    if Debounce then return end
    Debounce = true
    
    -- ...
    
    task.wait(...)
    Debounce = nil
end

So for your code:

local DamageDebounce = nil
local function dealDamage(otherPart)
    local character = otherPart.Parent
    if isNPC(character) then
        local humanoid = character:FindFirstChildWhichIsA("Humanoid")
        if humanoid then
            if DamageDebounce then return end
            DamageDebounce = true
            
            humanoid:TakeDamage(damageAmount)
            
            task.wait(0.5)
            DamageDebounce = nil
        end
    end
end

If you would like it to be more reliable, use GetTouchingParts like @Exozorcus suggested:

game:GetService("RunService").Heartbeat:Connect(function()
    if DamageDebounce then return end -- Save some processing power
    for i, v in ipairs(part:GetTouchingParts()) do
        dealDamage(v)
    end
end)

Almost a solution my friend, but it seems that the script only effects only 1 NPCs at a time

https://gyazo.com/d6c6510f0ebba0357251ecda9fceec82

Here’s an updated script I implemented btw : P

local tool = script.Parent
local damageAmount = 0.5
local partTemplate = game.ReplicatedStorage.PartTemplate
local activePart = nil
local unequipConnection = nil
local UserInputService = game:GetService("UserInputService")

local holding = false

local DamageDebounce = nil

local function isNPC(character)
	return character and character:FindFirstChild("Humanoid") and not game.Players:GetPlayerFromCharacter(character)
end

local function dealDamage(otherPart)
	local character = otherPart.Parent
	if isNPC(character) then
		local humanoid = character:FindFirstChildWhichIsA("Humanoid")
		if humanoid then
			if DamageDebounce then return end
			DamageDebounce = true

			humanoid:TakeDamage(damageAmount)

			task.wait(0.1)
			DamageDebounce = nil
		end
	end
end

tool.Activated:Connect(function()
    holding = true
    local player = game.Players:GetPlayerFromCharacter(tool.Parent)
    if not player then return end

    local character = player.Character
    local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
    if not humanoidRootPart then return end

    local spawnOffset = CFrame.new(0, 0, -7.5)
    local spawnPosition = humanoidRootPart.CFrame * spawnOffset

    local part = partTemplate:Clone()
    part.CFrame = spawnPosition
    part.Parent = game.Workspace

    part.Touched:Connect(dealDamage)

    local weldConstraint = Instance.new("WeldConstraint")
    weldConstraint.Parent = part
    weldConstraint.Part0 = part
    weldConstraint.Part1 = humanoidRootPart

    activePart = part
end)

tool.Deactivated:Connect(function()
    holding = false
    if activePart then
        activePart:Destroy()
    end
end)

game:GetService("RunService").Heartbeat:Connect(function()
	if DamageDebounce then return end
	if activePart ~= nil then
		for i, v in ipairs(activePart:GetTouchingParts()) do
			coroutine.wrap(dealDamage)(v)
		end
	end
end)

To set a debounce per NPC, the debounce should be a table. E.g:

if DamageDebounce[humanoid] then return end
DamageDebounce[humanoid] = true

Remove the “save processing” line.
Also put the task.wait and un-debounce in a coroutine.wrap.

TYSM! I’ve been looking for this FOREVER. Even back then (but I didnt know devforum existed lol)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.