Burning effect isn't dealing it's attended damage

I’ve built a status effect system that listens for whenever a value is added under a folder inside a player’s character, then it applies the appropriate function for the effect, currently there’s only one (which is burning), but it breaks… somewhat, (doesn’t deal all it’s damage).

Essentially, it goes a little something like this:
If the effect last for a short a bit like 1 second, it will deal all the damage it needed, BUT if it last long like 5 seconds, it wouldn’t deal all the damage it needed, it rather grazes the actual amount.

I’ve already tried recoding this multiple times, I’m close to giving up on this part of my small project, so I decided to get some outside help.

local RemainingCycles = Effect.Value / 0.2
local First = Effect.Value
local Second = 0

while Effect.Value > 0 and RemainingCycles > 0 do
	Second = Effect.Value
	if First < Second then
		First = Effect.Value
		RemainingCycles = Effect.Value / 0.2
	end
	local DeltaTime = game:GetService("RunService").Heartbeat:Wait()
	Effect.Value = math.max(Effect.Value - DeltaTime, 0)
	delay(0,function() --
		if not Debounce then
			Debounce = true
			wait(0.2)
			Character.Humanoid:TakeDamage(1)
			Debounce = false
			RemainingCycles = RemainingCycles - 1
			if Character.Humanoid.Health <= 0 then
				--to do later
			end
		end
	end)
end

A.K.A. I need help recreating this piece of code so it can deal it’s attended damage.

(If you need any more information about this, feel free to ask me.)

2 Likes

Havent read the whole thing yet but what’s the point of using a delay with 0 seconds?

It’s just make sure it the player takes damage without pausing the entire script.
(And also because so if the effect timer refreshes, it won’t pause the entire script.)

That’s not what delay is supposed to be used for. If you want the thread to continue at the same time as your function, then use coroutines.

You can also use spawn(), but don’t use spawn because it has a built in wait() into it, and wait() is notorious for being unreliable.

Tried your suggestion, it didn’t even worked, the only that it kept bringing up was: attempt to call nil value.

(Oh and btw here’s the new code if anyone asks.)

local DamageAAA = coroutine.create(function()
	if not Debounce then
		Debounce = true
		wait(0.2)
		Character.Humanoid:TakeDamage(1)
		Debounce = false
		--RemainingCycles = RemainingCycles - 1
		if Character.Humanoid.Health <= 0 then
			--to do later
		end
	end
end)

while Effect.Value > 0 do
--	Second = Effect.Value
--	if First < Second then
--		First = Effect.Value
--		RemainingCycles = Effect.Value / 0.2
--	end
	local DeltaTime = game:GetService("RunService").Heartbeat:Wait()
	Effect.Value = math.max(Effect.Value - DeltaTime, 0)
	coroutine.resume(DamageAAA)
end

It’s not that it didn’t work, you’re probably just not doing it right.

Really the most useful and easiest to use coroutine function is coroutine.wrap()

local newfunction  = coroutine.wrap(function() 
		if not Debounce then
			Debounce = true
			wait(0.2)
			Character.Humanoid:TakeDamage(1)
			Debounce = false
			RemainingCycles = RemainingCycles - 1
			if Character.Humanoid.Health <= 0 then
				--to do later
			end
		end
	end)

newfunction()

That’s a way to properly run code while not interrupting the rest of the thread (multithreading)

Already tried that beforehand, now it says: cannot resume dead coroutine, along with attempt to call nil value. Should I try to call it somewhere else outside of the loop?

(Also if you’re gonna ask where I called it, it was in the original place of coroutine.resume(DamageAAA), inside the loop.)

I’m replying to mark this post as solved since I’ve already figured it out by myself an couple days ago. I’ve fixed it by incorporating the delay function into the while loop itself, and replacing the wait(0.2) with an timer loop.

(Also here’s the fixed script for reference.)

while Effect.Value > 0 do
	local TICKS = 0.2
	local ENDEARLY = false
	while TICKS > 0 do
		local DeltaTime = game:GetService("RunService").Heartbeat:Wait()
		TICKS = math.max(TICKS - DeltaTime, 0)
		if Effect.Value <= 0 then --something ended the status effect early
			ENDEARLY = true
			break
		end
	end
	Effect.Value = Effect.Value - 0.2
	Character.Humanoid:TakeDamage(1)
	if Character.Humanoid.Health <= 0 then --landed the last hit?
		print(Character.Name .. " has died from fire status effect!")
		--to do later
		break
	end
	if ENDEARLY then break end
end
2 Likes

Glad you got it fixed!
30chars

2 Likes