[RESET TIMER] help with my function

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By quizzcode

Hey there !
I’m working on a tower defense game.
One my my tower apply a “burn” effect (Damage over a few seconds after hit)

I made a function that starts when the projectile hit the enemy, and it’s working wonderful.
Custom damage, custom time, only one “debuff” at a time.
It does everything i need it to do but ONE thing :
Restart itself when hit while already having it started

I have been stuck on this for most of the day yesterday… So today i give up.
Could you help me out ?

Here is my function :

if effect_type == 1:#Debuff type 1 = damage over time
	#If hhe ALREADY affected by this debuff ?
	if statuts_1 == 0: #he is not
		var total_damage = effect_amount / effect_time #how much dmg per tick.
		for i in range(effect_time): #effect time is in "second" 10s = 10 yield 1s.
			statuts_1 = 1 #say that it's now affected.
			yield(get_tree().create_timer(1), "timeout") #our fake timer
			if i == effect_time-1: # i = end of timer. this is last tick
				statuts_1 = 0 #not affected
				print("THE END")  #done.
				#Apply dmg
				break
			else:
				print(total_damage) ### apply dmg
				#apply dmg
				
	else:
		
		print("already burning")

Im really happy with the way it works. I just can’t figure out how to “restart” the process.
Should i implement a timer node ? But then if i have a “poison” debuff i’d need one timer per debuff right ?

:bust_in_silhouette: Reply From: Poobslag

So – the design you’ve chosen is to have this method run continuously and never terminate until the player is done being burned. You can probably find a way to make this design work using something called the “Method Object Refactoring” but, I wouldn’t recommend it

A more traditional way to handle logic like this would be something like this:

func apply_burn() -> void:
  $BurnTimer.start()

func on_BurnTimer_timeout() -> void:
  effect_time -= 1
  if effect_time <= 0:
    $BurnTimer.stop()
    print("THE END")  #done.
    # apply dmg

You only really need two small pieces of code; one to say, “Start this timer,” and the other to say, “Here’s what should happen once a second.” Godot will handle all of the other things you wrote – the idea of ‘the timer is running’ or ‘the timer is not running’, the idea of waiting a second, the idea of tracking the amount of milliseconds which have elapsed. The state variable you created is also encapsulated within the timer; you can just check if the timer is running. Godot does all of this, you do not need to code it.

With that said, you might be able to have a short-term band-aid fix by just doing something like effect_time += 5, right? Then if it’s already in the loop, it’ll stay in the loop longer?

hey !
Thx for your reply. I see how the timer function is cleaner.
You explained it well.

Regarding the effect +=5 would only make it longer 5s.
So if the same tower hits the target. 5 times. thats 25s of poising.
I’d want the poison to simply “restart from 0” either by canceling the previous one and starting a new one or by updating the time ?

quizzcode | 2020-05-19 23:50