Help with logic

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.

1 Like

You can use math like checking the position of the player and see if its on the position of the part +size or you can raycast downward

easy. Just do a touch event and make a

while value do

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.

1 Like

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 think I might have to use a coroutine.

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)

Thank you SOOOOOO much. It works, tysm for doing all that hard work. Happy Thanksgiving :turkey: !

1 Like

Change this:

if not success then
	table.remove(charactersTouching, table.find(charactersTouching, char))
end

To this:

local charIndex = table.find(charactersTouching, char)
	if charIndex then
		table.remove(charactersTouching, charIndex)
	end
end

As you did later on, it’s cleaner.
And this:

coroutine.resume(coroutine.create(function()
	damageCharacter(char)
end)

Is the same as this:

coroutine.wrap(function()
	damageCharacter(char)
end)()

And even this:

task.spawn(function()
	damageCharacter(char)
end)

This is a great script by the way, nice job.

1 Like