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

Changing waits to Timers in Spells.

Status
Not open for further replies.
Level 13
Joined
Jul 26, 2008
Messages
1,009
You can't use a Wait in a loop, I've known that for some time. What I have yet to learn is how to properly set up a timer to function instead of the wait. I remember going through a bunch of timer information, but I never drew a clear conclusion. Most tutorials explain how to make a timer countdown til the end of the map, or until the next wave of monsters or something.

I'd like to do spells that can be channeled with periodic effects until the channel is broken, or doing DoT effects through JASS and Triggers.

Any helpful information or tutorials that will teach me how to set up timers for spells would be great! GUI or JASS is fine, I understand both. Perhaps even Periodic Events or whatever would work.

The only thing with this is I do need it to be multi-player instancable.
 
Level 13
Joined
Mar 16, 2008
Messages
941
First of all, if you use timers, get TimerUtils from wc3c.net, a pretty neat system.
Timers are pretty easy.
It's to bad that the GUI timer function doesn't allow a callback.

JASS:
native TimerStart           takes timer whichTimer, real timeout, boolean periodic, code handlerFunc returns nothing

This function is the key to timers.
It start the timer, with a timout and an option if it's periodic.
That's the same like the GUI one, but in GUI you can't acces the part
JASS:
code handlerFunc
The function you isnert there will always be executed when the timer reaches 0 (even if it's periodic). That's the same like GUI "Timer-Expires" functions, but they suck :D

Another part you'll need, are HashTables. Okay, not always, depending on the spells.

Now, lets get an example (with hashtables):
JASS:
//This is vJass. It requires the JNGP (only this globals block)
//Just get it, it's usefull :P and will allow you even more.
globals
    hashtable MyHash
endglobals

function Damage takes nothing returns nothing
    local timer tim = GetExpiredTimer() //Timer in a callback, crashes if it's not a callback
    local unit caster = LoadUnitHandle(MyHash, GetHandleId(tim), 1)
    local unit target = LoadUnitHandle(MyHash, GetHandleId(tim), 2)
    local real damage = LoadReal(MyHash, GetHandleId(tim), 3)
    local real duration = LoadReal(MyHash, GetHandleId(tim), 4)
    
    call UnitDamageTarget(caster, target, damage, false, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
    
    if duration >= 4. then
        call ReleaseTimer(tim)
    else
        call SaveReal(MyHash, GetHandleId(tim), duration+0.5)
    endif
    
    set caster = null
    set target = null
endfunction
    
    
function RunMySpell takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local real damage = 10*GetUnitAbilityLevel(caster, 'A000')
    local timer tim = NewTimer() //TimerUtils
    
    call SaveUnitHandle(MyHash, GetHandleId(tim), 1, caster)
    call SaveUnitHandle(MyHash, GetHandleId(tim), 2, target)
    call SaveReal(MyHash, GetHandleId(tim), 3, damage)
    call SaveReal(MyHash, GetHandleId(tim), 4, 0)
    
    call TimerStart(tim, 0.5, true, function Damage)
    
    set caster = null
    set target = null
endfunction

function CheckMySpell takes nothing returns nothing
    return GetSpellAbilityId() == 'A000'
endfunction

//===========================================================================
function InitTrig_MySpell takes nothing returns nothing
    local trigger MyTrigg = CreateTrigger()
    call TriggerAddCondition(MyTrigg, Condition(function CheckMySpell))
    call TriggerAddAction(MyTrigg, function RunMySpell)
    
    set MyHash = InitHashtable()
endfunction
A part, the globals block, is vJass (as same as NewTimer()). If you don't want to use it, use a global Hashtable form the variable-creator and use "CreateTimer" and "DestroyTimer". However, destroying timers can cause bugs.)

Just attach your stuff to the timer.
If you have questions, then ask.
I hop you have enough Jass-Knowledge for this :)
(Although it's written in realy simple jass)
 
Level 13
Joined
Jul 26, 2008
Messages
1,009
That's great for a DoT, and I understand how all of it works. (Thanks to recently reading a hash table tutorial.) However, I'd like to be clear on if ReleaseTimer merely stops the timer from repeating, or if it does something else.

My next two questions are how do I do a timer for channeling, as you typically have to check to see if the spell has stopped channeling, and then stop the timer from firing off.

And how do you check for activatable and unactivatable and disable the timer if the activatable isn't going, and enable it if it is. Like say Immolation.

My biggest drawback is my lack of experience :\ JASS and vJASS are simple enough for me to understand, it's figuring out what function I need to use amongst a huge compilation of functions, and stringing them together to make lines of code. It's something that will come with asking questions, studying, memorizing and practicing over all.
 
Level 13
Joined
Mar 16, 2008
Messages
941
ReleaseTimer is like I mentioned (or not, I only mentioned NewTimer) a part of TimerUtils.
TimerUtils is a stack that creates new timers if the stack is empty.
If you release a timer it's paused and stored in the stack.

Then, for channeling. You can always check the current order of a unit. If it's the order of the spell, he's still channeling.
The orders can be seen in the object editor.
(Don't think that the name is always the order. Stormbolt for example has "thunderbolt").

Activable and unactivatable spells are annoying. The spell event triggers afaik on turning on and off, so either you use a boolean to keep track of it or it's like for auto-cast spells. I think you can use the event "A unit gets an order without a target" and check for the orders "immolation" and "unimmolation".

Just keep on trying, and get the JassNewGenPackage. It's for vJass (if you didn't get it already). It has a built in native list, although it doesn't involve the hashtable natives (at least not mine :p). JassCraft is another programm that's quite good and has a native list. I've added the hashtable natives to mine, it's rather easy (I think it's mentioned in the JassCraft thread on wc3c.net).
 
Level 13
Joined
Jul 26, 2008
Messages
1,009
I believe I added the hashtables. Had to run around, but it's up to date.

By the way an edit to that spell, the conditions should return a boolean. I recreated the spell and unfortunately it isn't running properly.

After running some debug tests, it doesn't seem to even reach the conditions trigger. :X I added a TriggerRegisterAnyUnitEventBJ and it worked, though using BJs isn't the best thing. Not sure why it wont work without the TriggerRegisterAnyUnitEventBJ. I've seen it do it without before :\
 
Last edited:
Level 8
Joined
Nov 20, 2008
Messages
445
You have to register events for triggers using either that BJ(that BJ is not that bad and can be used without any worries). Install JNGP then when working with Jass triggers theres a button called Function List(or smt like that) in where you can check every single function and what it takes and returns.

Another thing you might want to check is the vJass manual and learn to use structs. This way you wont need hashtables for everything and structs in general are the better way to go. They can be attached to timers so offer complete MUI support and can have whatever data you want, ranging from a unit to groups, timers, effects, sounds, integers, reals etc.
 
Level 13
Joined
Mar 16, 2008
Messages
941
Oh my god :D Yeah, I wrote it in JassCraft and completly forgot about the event^^ I'm used to just copy it from an old one, it's always the same (nearly).
And yes, the boolean should be returned from the condition.

You NEED this bj.
If you've seen it before, people just inserted the stuff the bj does by themselves.
This bj is okay to use, however, before 1.24b it leaked.
Now it's save to use.
 
Level 13
Joined
Jul 26, 2008
Messages
1,009
I'm just learning structs and libraries in vJASS, but will probably put it off to switch to learning how to terrain.

I usually use the Function List to find the proper natives to use. When typing out my code, the point after the paranthesis( begins to tell you what it takes and returns, so I usually rely on that.

Good to know it's a safe bj, I won't worry over using it now :D
 
Status
Not open for further replies.
Top