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)
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)
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)