• 🏆 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!

Spells with delayed effect

Status
Not open for further replies.
Level 7
Joined
May 11, 2010
Messages
278
When triggering a spell with a delayed effect, what is the pros and cons of using timers vs the wait function?

Example:
Unit casts Taunt
Trigger adds an Aura to Unit

Wait 5 seconds and remove Aura
or
Start Timer as a one-shot timer that expires in 5 seconds
New trigger: When Timer expires, remove Aura

Wich one is preferable? And in wich cases might i want to use the other one?
 
Level 4
Joined
Jan 27, 2010
Messages
133
Normal wait still runs while game paused or someone lagging.

When I tested this in 2010 waits worked fine with pause, actually. It is only the "waiting for players" dialogue that doesn't handle well with wait.

You know, if you accept the leak of GameTimeWait (polled wait), it's actually much easier to make it MUI. Even better, if you import PolledWait2 as a custom script, you won't even have the leak...

JASS:
function PolledWait2 takes real duration returns nothing
    local real timeRemaining
    local real st=TimerGetElapsed(bj_gameStartedTimer)
    if st <= 0 then
        set bj_gameStartedTimer = CreateTimer()
        call TimerStart(bj_gameStartedTimer, 1000000, false, null)
    endif
    if (duration > 0) then
        loop
            set timeRemaining = duration - TimerGetElapsed( bj_gameStartedTimer) + st
            exitwhen timeRemaining <= 0
            if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) then
                call TriggerSleepAction(0.1 * timeRemaining)
            else
                call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
            endif
        endloop
    endif
endfunction

  • Taunt Spell
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Taunt
    • Actions
      • Unit - Add Command Aura to (Triggering unit)
      • Custom script: call PolledWait2( 5.0 )
      • Unit - Remove Command Aura from (Triggering unit)
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
When I tested this in 2010 waits worked fine with pause, actually. It is only the "waiting for players" dialogue that doesn't handle well with wait.

You probably misunderstood the outcome of the test. If you pause the game while a TSA is running and unpause, the TSA will become out of sync.

You know, if you accept the leak of GameTimeWait (polled wait), it's actually much easier to make it MUI.

...Except it leaks. PolledWait is terrible (expensive) in jass anyway.

Even better, if you import PolledWait2 as a custom script, you won't even have the leak...

JASS:
function PolledWait2 takes real duration returns nothing
    local real timeRemaining
    local real st=TimerGetElapsed(bj_gameStartedTimer)
    if st <= 0 then
        set bj_gameStartedTimer = CreateTimer()
        call TimerStart(bj_gameStartedTimer, 1000000, false, null)
    endif
    if (duration > 0) then
        loop
            set timeRemaining = duration - TimerGetElapsed( bj_gameStartedTimer) + st
            exitwhen timeRemaining <= 0
            if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) then
                call TriggerSleepAction(0.1 * timeRemaining)
            else
                call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
            endif
        endloop
    endif
endfunction

  • Taunt Spell
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Taunt
    • Actions
      • Unit - Add Command Aura to (Triggering unit)
      • Custom script: call PolledWait2( 5.0 )
      • Unit - Remove Command Aura from (Triggering unit)

Or you could just, you know, learn jass.
 
Level 4
Joined
Jan 27, 2010
Messages
133
You probably misunderstood the outcome of the test. If you pause the game while a TSA is running and unpause, the TSA will become out of sync.

Really? Please post a test map showing this, so I can see what I did wrong when testing.

You know, if you accept the leak of GameTimeWait (polled wait), it's actually much easier to make it MUI.
...Except it leaks. PolledWait is terrible (expensive) in jass anyway.

Yeah, that's what I said? If he can accept the leak, then it's fine. Also, PolledWait2 does not leak. Expensive is completely irrelevant here. Really is. There's no high frequency-looping, and there is only supposed to be 1 instance running at a time (he stated non MUI). Much better to look at how easy it is to code/trigger; since that will save time and reduce errors and complexity.
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
Really? Please post a test map showing this, so I can see what I did wrong when testing.

JASS:
scope init initializer i
    globals
        unit footie
        timer clock=CreateTimer()
        integer elapsed=0
    endglobals
    
    private function p takes nothing returns nothing
        set elapsed=elapsed+1
        call BJDebugMsg(I2S(elapsed))
    endfunction
    
    private function b takes nothing returns nothing
        call BJDebugMsg("function b")
        call TriggerSleepAction(5.)
        call KillUnit(footie)
        call BJDebugMsg("kill footie")
    endfunction
    
    private function a takes nothing returns nothing
        call BJDebugMsg("pause game")
        call PauseGame(true)
        call TriggerSleepAction(5.)
        call BJDebugMsg("unpause game")
        call PauseGame(false)
    endfunction
    
    private function i takes nothing returns nothing
        local trigger t=CreateTrigger()
        local trigger u=CreateTrigger()
        call TimerStart(clock,1.,true,function p)
        call TriggerRegisterTimerEvent(u,4.,false)
        call TriggerAddAction(u,function b)
        call TriggerRegisterTimerEvent(t,5.,false)
        call TriggerAddAction(t,function a)
        set footie=CreateUnit(Player(0),'hfoo',0.,0.,0.)
        set t=null
    endfunction
endscope

It's just a fundamental difference between TSA and Timers. TSA will keep running when the game is paused and timers will not.

Notice that when the game is paused, the timer stops counting up, but the unit dies anyway.

Yeah, that's what I said? If he can accept the leak, then it's fine. Also, PolledWait2 does not leak. Expensive is completely irrelevant here. Really is. There's no high frequency-looping, and there is only supposed to be 1 instance running at a time (he stated non MUI). Much better to look at how easy it is to code/trigger; since that will save time and reduce errors and complexity.

Just because he is not making something MUI with polledwait2, doesn't mean there should be a movement to propagate polledwait2 as a function - it's still expensive, and the functionality it provides is still frowned upon. Edit: Not to mention it will crash a thread if it's used anywhere but a trigger action.
 
Level 4
Joined
Jan 27, 2010
Messages
133
Ah, I see. I never tested PauseGame(bool); only Pause Game from the multiplayer menu. Thank you for the clarification.

Just because he is not making something MUI with polledwait2, doesn't mean there should be a movement to propagate polledwait2 as a function - it's still expensive, and the functionality it provides is still frowned upon. Edit: Not to mention it will crash a thread if it's used anywhere but a trigger action.

This seem to be quite a political post! "Movement", "propagate", "frowned upon"... I agree with you that for someone who uses JASS there is pretty much no reason to use PolledWait2. However, for a GUI user, I believe it might be the better option in this case.

Things against it:

  • Expensive - Prove that it matters (especially in this case), or stop using it as an argument.
  • Only Trigger Action - Yes. Did you notice the original post was made in "trigger language"? Last time I checked, GUI people did not add waits in boolexprs.
  • Imprecise - I won't deny it. It might be a slight bit off, like 0.2 seconds or so. In this case, that will SO not matter, since he's adding and removing an aura (and auras are MORE off).

Things for:

  • Coding Speed + Low Complexity + Clean code - Three lines in Trigger Action, 1 trigger.
  • GUI MUI - Using Get Triggering Unit
  • Not Clogging Globals - Perhaps this is just me being obsessive over structure and order... :p
 
Last edited:

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
Ah, I see. I never tested PauseGame(bool); only Pause Game from the multiplayer menu. Thank you for the clarification.

I might be wrong, but if I recall correctly, PauseGame(true) while on battle.net behaves differently than in single player mode - the difference in this case is that the unit would die immediately when PauseGame(false) is called. Test it out if you're genuinely curious.

This seem to be quite a political post! "Movement", "propagate", "frowned upon"... I agree with you that for someone who uses JASS there is pretty much no reason to use PolledWait2. However, for a GUI user, I believe it might be the better option in this case.

Things against it:

  • Expensive - Prove that it matters (especially in this case), or stop using it as an argument.
  • Only Trigger Action - Yes. Did you notice the original post was made in "trigger language"? Last time I checked, GUI people did not add waits in boolexprs.
  • Imprecise - I won't deny it. It might be a slight bit off, like 0.2 seconds or so. In this case, that will SO not matter, since he's adding and removing an aura (and auras are MORE off).

Now, why would I "propagate" for such a "frowned upon" function? :grin:

  • Coding Speed + Low Complexity + Clean code - Three lines in Trigger Action, 1 trigger.
  • GUI MUI - Using Get Triggering Unit
  • Not Clogging Globals - Perhaps this is just me being obsessive over structure and order... :p

I'm going to try to avoid countering your argument because I think you're missing my point.

The fundamental difference between you and I is that I don't aim to encourage "band-aid" like solutions for problems, because I want to teach users how to solve issues in ways that they will always be able to use, and will always have value for them regardless of how much their experience with the engine improves.

That's why PolledWait2 is a bad suggestion. Every time you use PolledWait2, there is guaranteed to be a better option.

Now let's ignore my suggestion to "learn jass and avoid PolledWait2". Let's pretend your post is sufficient for the issue (and it is - PolledWait2 will always be good enough for an aura). But let's pretend our student wants to create a sliding function where a casting unit slides forward 50 times in a loop. Do you know what PolledWait2 will do if you try to PolledWait2(1./30.)? I assume you know already - but that's what I'm trying to get at. Arm your student with knowledge that will be useful, not just the solution with the smallest number of lines.

You could use the argument that he doesn't need such a short wait, and you could use the argument that PolledWait2 will result in fewer "actions", but the fact is that you're teaching him bad practices.
 
Level 4
Joined
Jan 27, 2010
Messages
133
... I think you're missing my point.

The fundamental difference between you and I is that I don't aim to encourage "band-aid" like solutions for problems, because I want to teach users how to solve issues in ways that they will always be able to use, and will always have value for them regardless of how much their experience with the engine improves.

That's why PolledWait2 is a bad suggestion. Every time you use PolledWait2, there is guaranteed to be a better option.

I agree with your Aristotelean thought that we should try to maximize the development of Shoto's character and skill. However, I do not believe that we can force jasshelper, Zinc, and TimerUtils on somebody who we must assume does not know JASS. That is really the only good option; making globals and double triggers for each spell is not exactly a better option.

Arm your student with knowledge that will be useful, not just the solution with the smallest number of lines.

There is pretty much research concerning programming and complexity (or, lines of code). The more code, the more errors. Keeping code simple and structured is doing yourself a favor. I hightly recommend the book Code Complete if you are interested in computer science and programming practices.

You could use the argument that he doesn't need such a short wait, and you could use the argument that PolledWait2 will result in fewer "actions", but the fact is that you're teaching him bad practices.

No, I'm teaching Shoto a tool. I have been pretty specific in my last posts of when it is usable or not (and you have filled in whatever I missed). If Shoto needs rapid iterations, of course a timer is a better choice! If Shoto is trying to make a delayed spell effect in GUI then I sincerely believe that PolledWait2 is a better choice (because of the "code" structure advantage).
 
Last edited:

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
I agree with your Aristotelean thought that we should try to maximize the development of Shoto's character and skill. However, I do not believe that we can force jasshelper, Zinc, and TimerUtils on somebody who we must assume does not know JASS. That is really the only good option; making globals and double triggers for each spell is not exactly a better option.

I never suggested he use such things - in fact, I would never suggest someone learn zinc or timerutils. Nor did I suggest using globals/double triggers. All I said is he should learn jass (which would pave the way for learning to use timers effectively)

There is pretty much research concerning programming and complexity (or, lines of code). The more code, the more errors. Keeping code simple and structured is doing yourself a favor. I hightly recommend the book Code Complete if you are interested in computer science and programming practices.

There is a time and place for everything. Many desirable programming constructs and methodologies have a place in jass, but it's more often that "good" coupling, abstraction, and completeness get thrown out the window in favor of performance. That's because jass is a very slowly interpreted language.
 
Level 7
Joined
May 11, 2010
Messages
278
First of, excuse me for the (very) late reply.
Thanks for your comments. I find your discussion very interesting and I feel like I've learned at least something from reading it. It is true that I can't use Jass or other things like it. I thought I'd learn GUI first so I have a better understanding of how this shit works.
I'm going to take a look at some threads about MUI, timers and spells i've been pointed to by other members of Hive. Thanks for the help!
 
Status
Not open for further replies.
Top