• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

How do I get the expiration timer of a unit?

Status
Not open for further replies.
Level 14
Joined
Apr 20, 2009
Messages
1,543
I want to display a debugmsg which displays the expiration timer of a unit.
Ideally continiously untill it expires.
Is it possible? And if so, how would I do this?

I know that using a TimerUtil can be an alternative.
But there are 2 reasons why I don't want to do this.

1. I have little to no experience with vJass, and TimerUtils are in vJass...
2. I just want to know if it is possible to get the expiration timer without using an alternative...
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
The expiration timer is no jass object. Which information shall these messages contain?

That is very disappointing to hear :(

I guess I would have to manually create a timer of 60 seconds which is being displayed continuously untill it expires...

I want to do this in Jass.

Could you perhaps give me an example with explenation on this?

I personally can't succeed in this, I really need some help :(
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
So what? Build a function that is your extended version of an expiration timer. You create a normal timer and the expiration timer for displays with the same duration. You assign the timer to the unit. Make another PauseExpirationTimer function that stops both timers. And well ask for the elapsed/remaining time of the timer that is assigned to the unit when you want it.

I do not know where you could possibly not succeed in this, so show your approaches.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
So what? Build a function that is your extended version of an expiration timer. You create a normal timer and the expiration timer for displays with the same duration. You assign the timer to the unit. Make another PauseExpirationTimer function that stops both timers. And well ask for the elapsed/remaining time of the timer that is assigned to the unit when you want it.

I do not know where you could possibly not succeed in this, so show your approaches.

How do I assign the timer to the unit? Remember I'm unfamillair with vJass :p

This was my approach:

JASS:
function Trig_Untitled_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    local real timeRemaining
        call TimerStart(t, 60, false, null)
        loop
            set timeRemaining = TimerGetRemaining(t)
            call DisplayTextToPlayer(Player(0),0,0,R2S(timeRemaining))
            exitwhen timeRemaining <= 0
        endloop
        call PauseTimer(t)
        call DestroyTimer(t)
        set t = null
endfunction

//===========================================================================
function InitTrig_Untitled takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterTimerEvent(t, 0.00, false)
    call TriggerAddAction( t, function Trig_Untitled_Actions )
    set t = null
endfunction

EDIT: I think I see what I did wrong here, I need to pass a code to TimerStart and inside that function display the remaining time right?
EDIT 2: Now that I think about it, when you pass a function to TimerStart then it will be executed when the timer is expired right?

EDIT 3:
How do I create an extended version of a expiration timer? I need some help to get started.

EDIT 4:
I guess I would have to create a real variable that gets increased every second and then is being displayed through a message?

EDIT 5:
If a timer needs to be paused to get the remaining time, then would I need to pause it every second and then resume it? Then what is the point of using TimerGetRemaining when you can display a real every second?

Can you maybe give me an example, I feel like such a noob at the moment >.>
 
Last edited:
Level 26
Joined
Aug 18, 2009
Messages
4,097
How do I assign the timer to the unit? Remember I'm unfamillair with vJass :p

This was my approach:

JASS:
function Trig_Untitled_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    local real timeRemaining
        call TimerStart(t, 60, false, null)
        loop
            set timeRemaining = TimerGetRemaining(t)
            call DisplayTextToPlayer(Player(0),0,0,R2S(timeRemaining))
            exitwhen timeRemaining <= 0
        endloop
        call PauseTimer(t)
        call DestroyTimer(t)
        set t = null
endfunction

//===========================================================================
function InitTrig_Untitled takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterTimerEvent(t, 0.00, false)
    call TriggerAddAction( t, function Trig_Untitled_Actions )
    set t = null
endfunction

EDIT: I think I see what I did wrong here, I need to pass a code to TimerStart and inside that function display the remaining time right?

EDIT 2: Now that I think about it, when you pass a function to TimerStart then it will be executed when the timer is expired right?

Positive. Could be used to clean up the timer and assigments for example.

The loop you wrote above has no interval --> how should the exitwhen condition ever be fulfilled when you order the game permanently to do stuff, freezing everything. This would only work if wc3 was multithreaded but you would practically get an infinite/indeterminated amount of iterations in that loop. Now, wc3 has an execution limit, so it does not freeze the game in an infinite loop but cancels the code.

You can either put a TriggerSleepAction inside the loop or create another timer that fires every second or so. TriggerSleepActions has a lot of negatives, so would advise the latter.

You did not make any assigments here. You can leave this of course in case there is only one timer but if you want to have the expiration timer of any unit, you need to know somehow which timer belongs to which unit.

Assignment methods are the basic things you look into when starting to learning triggering. There are multiple though. The most direct and independent way would probably be the hashtable.

You init the hashtable somewhere with InitHashtable and save it in a global variable. Then you can use Save<dataType> to store data under a set of keys, read it out again by Load<dataType>, just take a look at the API. To get a unique key you can use for the special unit, one usually takes the handle id of the unit with GetHandleId.

@Edit3: Better learn vJass to get familiar with structures.

@Edit5: Of course you can set a real every second and print it but the timer has the advantage that you can make clean itself up right way in the end and maybe do other stuff.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
This was my approach:

JASS:
function Trig_Untitled_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    local real timeRemaining
        call TimerStart(t, 60, false, null)
        loop
            set timeRemaining = TimerGetRemaining(t)
            call DisplayTextToPlayer(Player(0),0,0,R2S(timeRemaining))
            exitwhen timeRemaining <= 0
        endloop
        call PauseTimer(t)
        call DestroyTimer(t)
        set t = null
endfunction

//===========================================================================
function InitTrig_Untitled takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterTimerEvent(t, 0.00, false)
    call TriggerAddAction( t, function Trig_Untitled_Actions )
    set t = null
endfunction

EDIT: I think I see what I did wrong here, I need to pass a code to TimerStart and inside that function display the remaining time right?



Positive. Could be used to clean up the timer and assigments for example.

The loop you wrote above has no interval --> how should the exitwhen condition ever be fulfilled when you order the game permanently to do stuff, freezing everything. This would only work if wc3 was multithreaded but you would practically get an infinite/indeterminated amount of iterations in that loop. Now, wc3 has an execution limit, so it does not freeze the game in an infinite loop but cancels the code.

You can either put a TriggerSleepAction inside the loop or create another timer that fires every second or so. TriggerSleepActions has a lot of negatives, so would advise the latter.

You did not make any assigments here. You can leave this of course in case there is only one timer but if you want to have the expiration timer of any unit, you need to know somehow which timer belongs to which unit.

Assignment methods are the basic things you look into when starting to learning triggering. There are multiple though. The most direct and independent way would probably be the hashtable.

You init the hashtable somewhere with InitHashtable and save it in a global variable. Then you can use Save<dataType> to store data under a set of keys, read it out again by Load<dataType>, just take a look at the API. To get a unique key you can use for the special unit, one usually takes the handle id of the unit with GetHandleId.

@Edit3: Better learn vJass to get familiar with structures.

@Edit5: Of course you can set a real every second and print it but the timer has the advantage that you can make clean itself up right way in the end and maybe do other stuff.

I don't have to assign it because it is for a test with only 1 unit.
I think I'll create a periodic timer, thanks :)
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
I'm sorry for my double post, but I want you to notice that I have one more question.

Is there any way of making a trigger wait for a boolean condition to be true without using TriggerSleepAction?

If I'm using a loop that exits when the boolean is true then that would also mean that there is no interval in the loop right? Since the boolean can be false forever...

EDIT:
I've just checked the GUI action Wait for condition every ... and this shows the following jass script:

JASS:
function Trig_Untitled_Trigger_001_Func001001 takes nothing returns boolean
    return ( IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) == true )
endfunction

function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    loop
        exitwhen ( Trig_Untitled_Trigger_001_Func001001() )
        call TriggerSleepAction(RMaxBJ(bj_WAIT_FOR_COND_MIN_INTERVAL, 0.50))
    endloop
endfunction

Would this mean that when I add a TriggerSleepAction inside the loop it will have an interval?
Meaning that I can exit it when the boolean is true?

I know TriggerSleepAction is inacurate, but does it matter that much? It only needs to check if the boolean is true anyways...
I don't really care if it checks the boolean on a slightly inacurate interval since I need to perform some function calls after the boolean is true.
It doesn't nessecarily need to call them on the exact milisecond that the boolean becomes true.

also: if I use a interval of 0.50 seconds with TriggerSleepAction and the boolean becomes true after 60 seconds, then how can I calculate how far TriggerSleepAction is off?

EDIT: Nevermind, I solved the problem. This thread can be set to solved...
If you want to know how it turned out check this: http://www.hiveworkshop.com/forums/2083050-post42.html
 
Last edited:
Level 26
Joined
Aug 18, 2009
Messages
4,097
Is there any way of making a trigger wait for a boolean condition to be true without using TriggerSleepAction?

No, how should this work? This would require that the game detects any change to any variable/function involved in the selection. For example if you write IsUnitType(u, UNIT_TYPE_DEAD), the game would need to know that AddUnitType/RemoveUnitType and standard routines make a difference to the outcome or better yet lay events on the internal memory location. No, wc3 does not do that.

If I'm using a loop that exits when the boolean is true then that would also mean that there is no interval in the loop right? Since the boolean can be false forever...

The exit conditions would be false forever/until code halts because as I have already said above, wc3 is single-threaded, so nothing else runs before the current code has not finished executing, so there is no chance that the condition gets true from outside. Only if you put a TriggerSleepAction inside the loop, this Wait pauses the code and other triggers and stuff can be executed.

I know TriggerSleepAction is inacurate, but does it matter that much?

How should I know if it matters in your scenario?

also: if I use a interval of 0.50 seconds with TriggerSleepAction and the boolean becomes true after 60 seconds, then how can I calculate how far TriggerSleepAction is off?

By detecting the event itself when it comes to the boolean obtaining the true status. By not using such a bad construct but rather make the timer execute a function upon expiration that does the stuff you want when the remaining time hits 0.
 
Status
Not open for further replies.
Top