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