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

[JASS] Local timers

Status
Not open for further replies.
Level 6
Joined
Mar 15, 2005
Messages
112
What am I doning wrong? Trying to learn how to use local timers to simulate a periodic event. Planned to destroy the timer after the loop.

JASS:
function Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'a000' ) ) then
        return false
    endif
    return true
endfunction
function callback takes nothing returns nothing
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"1")
endfunction
function Actions takes nothing returns nothing
local unit array U
local integer array I
local timer T = CreateTimer()
set U[1] = GetTriggerUnit()
call TimerStart(T,0.75,true,function callback)
set I[1] = 0
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"1")
loop
exitwhen I[1] == 25
set I[1] = I[1] + 1
endloop

endfunction


//===========================================================================
function InitTrig_Timer takes nothing returns nothing
    set gg_trg_Timer = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Timer, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Timer, Condition( function Conditions ) )
    call TriggerAddAction( gg_trg_Timer, function Actions )
endfunction
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Your timer is destroyed in less then 0.75 seconds (more like in 0.000001 seconds) because you have nothing telling the loop to wait.

Since waits are crappy, you can use a global integer (or something) and every time the callback runs add 1 to it.
Then, again in the callback, you check if it's equal to your desired maximum.
You can also move handles between functions with Handle to Integer (known as H2I) bugged function, but if you do not need to, I suggest you not to.
 
Level 6
Joined
Mar 15, 2005
Messages
112
Hmm, kool I'll see if I can make this work. I'm trying to find an alternative to periodic events. So I can use locals. Was wondering.. can you use a local trigger with a periodic event. Can that local trigger refer to its parent trigger's local variables? If not can it refer to its parent's structs?

Anyways thx ghostwolf. I would +rep but I have to wait till tomorrow.

Edit:roleplay your right. A friend told me about that.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Well, you should move with different approaches for different types of codes.

For physics (knockbacks, real physics, and stuff like that), for example, you'd probably want to make a global array of structs (or multiple global arrays if you do not want to use structs for some reason) and every callback loop between them and act based on their info.

Here is a pseudo code for a knockback using this kind of code (there will probably be a hundred errors as I wrote it here and I didn't touch Jass for about half a year, but I don't care).
JASS:
scope Knockback

globals
    private timer t = CreateTimer()
    private integer activatedKnockbacks = 0 // the current working knockbacks
    private KnockbackInfo array KB
endglobals

struct KnockbackInfo
    unit u // the unit getting knockbacked
    real vx // velocity on the x axis
    real vy // velocity on the y axis
    integer t // time to knockback (not in seconds, but in callbacks)
endstruct

function Knockback_Callback takes nothing returns nothing
    local integer iterator = 0
    local KnockbackInfo kb
    loop
        exitwhen iterator > activatedKnockbacks
        set kb = KB[iterator]
        
        call SetUnitX(kb.u,GetUnitX(kb.u)+kb.vx)
        call SetUnitY(kb.u,GetUnitY(kb.u)+kb.vy)
        
        set kb.t = kb.t - 1
        if kb.t == 0 then
            kb.destroy() // destroy the unneeded struct
            set KB[iterator] = KB[iterator+1] 
           // by setting the current knockback data to the next one, 
           // you "forget" the reference of the current one
        endif

        set iterator = iterator + 1
    endloop
endfunction

function RegisterKnockback takes unit target, real angle, real speed, integer time returns nothing
    local KnockbackInfo kb = KnockbackInfo.create()
    local real radians = angle * bj_DEGTORAD
    set kb.u = target
    set kb.vx = speed * cos(radians) // x axis velocity
    set kb.vy = speed * sin(radians) // y axis velocity
    set kb.t = time * 25 // multiply by 25 because it runs 25 times per second
    
    if activatedKnockbacks == 0 then
        call TimerStart(t,0.04,true,function Knockback_Callback)
    endif

    set KB[activatedKnockbacks] = kb
    set activatedKnockbacks = activatedKnockbacks +1
endfunction

endscope

If you REALLY can't use globals for some reason then you'll need to go with the H2I function.
 
Last edited:
Status
Not open for further replies.
Top