I’m trying to make a “damage part” that takes away 10 health of the player while (not when the player is off the part) standing on the part every 3 seconds.
Here is my base script(meaning the script I’m starting out):
local isLoopRunning = false
local isHumanPartTouching = false
function onTouched(hit)
local human = hit.Parent:findFirstChild("Humanoid")
if (human ~= nil) then
isHumanPartTouching = true
if isLoopRunning == false then
isLoopRunning = true
while isLoopRunning do
human.Health -= 10
wait(3)
end
isLoopRunning = false
else
print("Loop is already in progress")
end
end
end
script.Parent.Touched:Connect(onTouched)
How can I make this detect when the player walks off the part to break the part? Also to note, I tried using the TouchEnded even and what is happening is that when the character moves, it fires while a new part of my body begins touching it. I need it to detect when all parts are not touching the brick.
Set the “value” and set it false, make sure to put it under the touched function, and then when touched make the value true , and in that loop check every 3 second if that player exists and touching the part with :GetTouchingParts, if not make the value false in that loop.
You could make a recursive function that calls itself every 3 seconds. You also implemented the touching incorrectly. To make sure the character is still touching the part, you could create a table that holds all the characters touching the part. Then, remove the characters that stop touching the part.
local damagePart = script.Parent
--// this is the table containing the characters currently
--// touching the part
local charactersTouching = {}
function damageCharacter(char)
if table.find(charactersTouching, char) then
--// character is still touching the part
--// include a pcall just in case the character no longer exists
local success, err = pcall(function()
local humanoid = char:WaitForChild("Humanoid")
humanoid:TakeDamage(10)
wait(3)
damageCharacter(char)
end)
--// if pcall was not successful, remove the character from
--// the touching table
if not success then
table.remove(charactersTouching, table.find(charactersTouching, char))
end
else
--// character is not touching the part anymore
print(char.Name .. " is no longer touching the part")
end
end
function damagePartTouched(objectHit)
local char = objectHit.Parent
local player = game.Players:GetPlayerFromCharacter(char)
local charIndex = table.find(charactersTouching, char)
if player and not charIndex then
--// if the character belongs to a player and the character is not already
--// in the touching table, add the character to the touch table
table.insert(charactersTouching, char)
--// begin to damage character
damageCharacter(char)
end
end
function damagePartTouchEnded(objectHit)
local char = objectHit.Parent
local charIndex = table.find(charactersTouching, char)
if charIndex then
--// the character stopped touching the damage part
--// if the character is in the touching table, remove from the table
table.remove(charactersTouching, charIndex)
end
end
--// connections
damagePart.Touched:Connect(damagePartTouched)
damagePart.TouchEnded:Connect(damagePartTouchEnded)
Note that if the character is constantly stepping on and off of the part, the touch event will fire every time the player steps onto and off of the part. This method works best if there is an invisible part that’s non collidable and anchored, and the character can constantly stay touching the part.
Thank you! But 1 problem: what’s happening is that it works, but what happens is when I run thru it, it’s thinking I’m touching it multiple times and I am taking damage for each time. How do I fix that?
I added a cooldown to the function. Try using this:
local damagePart = script.Parent
--// this is the table containing the character currently
--// touching the part
local charactersTouching = {}
function damageCharacter(char)
if table.find(charactersTouching, char) then
--// character is still touching the part
--// include a pcall just in case the character no longer exists
local success, err = pcall(function()
local charLastDamagedTime = char:GetAttribute("LastDamagedTime")
if charLastDamagedTime == nil or tick() - charLastDamagedTime >= 3 then
char:SetAttribute("LastDamagedTime", tick())
local humanoid = char:WaitForChild("Humanoid")
humanoid:TakeDamage(10)
wait(3)
coroutine.resume(coroutine.create(function()
damageCharacter(char)
end))
else
print("not enough time passed to damage the character")
end
end)
--// if pcall was not successful, remove the character from
--// the touching table
if not success then
table.remove(charactersTouching, table.find(charactersTouching, char))
end
else
--// character is not touching the part anymore
print(char.Name .. " is no longer touching the part")
end
end
function damagePartTouched(objectHit)
local char = objectHit.Parent
local player = game.Players:GetPlayerFromCharacter(char)
local charIndex = table.find(charactersTouching, char)
if player and not charIndex then
--// if the character belongs to a player and the character is not already
--// in the touching table, add the character to the touch table
table.insert(charactersTouching, char)
--// begin to damage character
damageCharacter(char)
end
end
function damagePartTouchEnded(objectHit)
local char = objectHit.Parent
local charIndex = table.find(charactersTouching, char)
if charIndex then
--// the character stopped touching the damage part
--// if the character is in the touching table, remove from the table
table.remove(charactersTouching, charIndex)
end
end
--// connections
damagePart.Touched:Connect(damagePartTouched)
damagePart.TouchEnded:Connect(damagePartTouchEnded)