Can I stop timer inside itself/stop after certain timer ticks?

Hi guys,

I am planning to use timers mechanics for Damage Over Time functionality. I am essentially going to have an array of Damage effects that stack on character, and for each of them I am planning to have a separate timer that ticks and deals damage to player. The problem is, I will want to stop the timer and destroy the damage effect after some time. The only viable solution I found for that is as following: every OnTick event fire of the player character I would get through the damage effects array and for each of them check, how long did the timer tick, and if it’s ticking long enough - stop it. It seems a little too slow and expensive for the code to run like this - I will have my OnTick go through array, and same time the timers for each DoT will be ticking by themselves.

Is there any way of actually clearing timer in its delegate function’s body, to which I set that timer? It would be great to actually let the timers handle their lifetime by themselves - when they tick long enough, they could just destroy themselves. I did not find a way to do that yet :frowning:

What you could do is have an array that holds a float value for each “Damage Effect”. This float would represent the timestamp for when this “Damage Effect” started. Then in the delegate function, you could do a check to see if x amount of time has passed.

void YourClass::ApplyDamageEffectBleed(float Duration){
    float RepeatTime = 0.5f;
    MyDamEffTimeArray[indexOfBleed] = ()->TimeSeconds + Duration;    
    GetWorldTimerManager().SetTimer(this, &YourClass::BleedTimerDelegate, RepeatTime, true);
}

void YourClass::BleedTimerDelegate(){

    // do the things

    if(()->TimeSeconds > MyDamEffTimeArray[indexOfBleed]){
        GetWorldTimerManager().ClearTimer(this, &YourClass::BleedTimerDelegate);
    }
}

What another function in place of ApplyDamageEffectBleed(float Duration) would be is to do something like this using function pointers… Ramas wiki on function pointers (link).

What you would do is have an array of the Times for each “Damage Effect” and then an array for the delegate functions… these two arrays would have the matching index for each “Damage Effect”. So the index of 1 in both arrays would be for “Bleed”, or whatever type.

Then, you would have a function like:

void YourClass::ApplyDamageEffect(int Index, float Duration){
    float RepeatTime = 0.5f;

     MyDamEffTimeArray[Index] = ()->TimeSeconds + Duration;

    // I'm not sure on syntax here....  it's either this 
    GetWorldTimerManager().SetTimer(this, * (DamEffFunctions[Index]), RepeatTime, true);
    //  or this (pretty sure this if you follow the wiki syntax)
    GetWorldTimerManager().SetTimer(this, (DamEffFunctions[Index]), RepeatTime, true);
}

Again, I’m not 100% sure on the syntax of UE4 function delegates but it would be a very clean implementation.

You could then define constants for each damage effect to simplify it for you when calling the ApplyDamageEffect function using the index for the time and delegate function:

#define DE_BLEED 0
#define DE_BLIND 1
#define DE_WHATEVA 2

Hopefully that helps =)

Edit I just realized… if you use the function delegate array, you would use the defined index value to check the time array.

You can use DeltaTime to apply Damage over Time, Tick is excuted on every frame DeltaTime is time between the frames, you can add DeltaTime on each tick and if it cross over specific time you apply damage. You can do even smoother version by applying damage on every frame and scaled it with DeltaTime

is right, using the Tick function and DeltaTime will give you smoother damage application over time. But if you are doing damage in MMO style where multiple conditions can be applied and do X amount of damage per second or whatever, the timers you currently have will work fine.

Thanks man, I would try the second way. With the first one, however - as far as I tested quite similar functionality, it would not be working, as I am sending the delegates to the same function. When I was doing so, the timer would reset, so instead of many timers I had just one (because timers are identified by the delegate functions, and there is only one of them in this model). Please correct me if I am wrong.

Thanks, that’s smart to interpolate the damage in the Tick function.