Using A Single Timer For Two Countdowns

R

robproctor83

Guest
Hello,

I thought I knew how to do this, but after trying to implement it it's not working. I need a timer variable that countdowns for two events. One event that triggers when the timer reaches 0 and another event that triggers once every 2 seconds. I thought using "timer mod 2 == 0" would work, but it seems that once I apply delta timing to the timer the values I get out of mod are way crazy. Instead of getting 0 for example I get 0.000732481 or something like that. So, I'm not sure how I could go about doing this without another variable.... Which, I dont want to do if possible.
 

TsukaYuriko

☄️
Forum Staff
Moderator
Either remove delta timing from the equation, or add another variable. There's no way around one or the other, as you're destroying the mechanism you rely on (modulo always returning integers*) by introducing delta timing.

*and not even this is guaranteed due to floating point precision, or lack thereof. Use integers for the timer so that the epsilon will match to whole integers despite the imprecision rather than stacking imprecision from addition every step.
 
R

robproctor83

Guest
Ah ok, I was hoping there was some other way to go about doing it, but I guess it's not really possible with how I am doing things. Unfortunately I have to apply delta timing to the timer or else it's out of sync with the game, so no biggie I'll just setup another timer variable for the 2 second events.
 

chamaeleon

Member
You could introduce a new variable called "next_2_second" that keeps track of when the next interval action should be taken. Not very different than using two timer variables, but maybe it's less error prone to have one variable that you modify using delta time instead of one per thing you need to keep track of, and instead keep track the next threshold for each interval action.

Untested, and perhaps unexpected behavior if the delta time goes over 2 seconds..
Initialization code
Code:
my_timer = 100;
next_2_seconds = my_timer-2;
Step code
Code:
my_timer -= delta;
if (my_timer <= next_2_seconds) {
    next_2_seconds -= 2;
    // do 2 second interval stuff
}
if (my_timer <= 0) {
    // do final timeout stuff
}
 

curato

Member
probably be easier to just have a timer count down to an event and if the two are tied together, just set an alarm for every two seconds and if the timer is still running then do the event.
 
R

robproctor83

Guest
Thanks for the tips, but I ended up just adding a second timer. The main timer was for a status effect applied to an enemy, so the effect lasts for 10 seconds but every 2 seconds I need to apply damage to the enemy. The thing is, I have a couple dozen possible statuses and enemies can have multiple status effects at any given time. So, each status needs it's own 10 second timer and 2 second timer, which ends up being a lot of timers. I can't use normal alarms because of delta timing in my game, so I have a custom alarm system in play that I use instead. Now, I could just use my delta alarms, but I didn't want to pollute the enemies custom alarms with all of these status alarms so I kept them as separate variables.

Ultimately an enemy has a ds list of active status effects, and each ds list item is an array that contains the status condition index (that I use to grab which effects and scripts to run) and two timers (one for the 10 seconds timer and one for the 2 second timer). Also, the 10 and 2 are variables that change depending on which status condition is applied. Two more gotchas, attacks can apply multiple status conditions at once and if you hit an enemy with a fire attack and they are already on fire then rather than stack it should reset the main 10 second timer, but leave the 2 second timer where it's at. Anyways, I got it working like that now, but the code is a bit overwhelming. If anyone has a better idea for a system like this I'd love to hear.

Originally I had a local array, an array element for each possible status. Then, every step I was looping through every item in the array and checking things. I figured looping over and over when no active statuses are applied is probably not good, so I switched them to this ds_list system where I only store active statuses instead. I'm thinking this is better, but I still have to query this ds list every step and then loop over it multiple times. And because an attack can apply 1 or more statuses at once and not stack I have to loop over all the active statuses and then for each active status loop over each status in the attack that is being applied and check if it's already set, if so update otherwise add. It works, but I can't help but feel like there must be a better way. One more thing, the status effects apply a particle effect. I have a single particle system with a different particle type for each status. When an active status is found I add it to an array of possible particle types that can be drawn, then each emission of the particle system I randomly choose a particle type from that array. Oh, and above the enemy is an icon that shows active statuses as well... and the enemy gets a mixed shader that changes the color pallette depending on the active status. So there's a lot going on.
 
Top