• Check out the results of the Techtree Contest #19!
  • Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!

[JASS] Loop isn't looping?

Status
Not open for further replies.
Level 3
Joined
Jan 24, 2015
Messages
26
I have a script where, after casting an ability a unit should continuously spray fire in front of them until they either die or ( this isn't implemented yet ) the ability times out. However,

JASS:
function Trig_Ignis_Fatuus_JASS_Conditions takes nothing returns boolean
    local unit caster = GetSpellAbilityUnit()
    local player owner = GetOwningPlayer(caster)
    local unit dummy
    local integer ability_level = GetUnitAbilityLevel(caster, 'A01R')
    if(GetSpellAbilityId() == 'A01R') then
        loop
            exitwhen GetUnitState(caster, UNIT_STATE_LIFE) <= 0.0  
            set dummy = CreateUnit(owner, 'h003', GetUnitX(caster), GetUnitY(caster), GetUnitFacing(caster))
            call UnitApplyTimedLife(dummy, 'BTFL', 0.5)
            call UnitAddAbility(dummy, 'A01S')
            call SetUnitAbilityLevel(dummy, 'A01S', ability_level)
            call IssuePointOrder(dummy, "breathoffire", GetUnitX(dummy) + (1.0 * Sin(GetUnitFacing(dummy) * bj_DEGTORAD)), GetUnitY(dummy) + (1.0 * Sin(GetUnitFacing(dummy) * bj_DEGTORAD)))
            call PolledWait(0.2)
        endloop
    endif
    return false
    set caster = null
    set owner = null
    set dummy = null
endfunction

this excerpt of code works perfectly fine, except it only loops once; only one dummy unit is created and it only casts the breath of fire variant once. Can I not use PolledWaits inside of loops? I can remove the exitwhen condition and it will still only loop once, so I'm not entirely sure what else the cause could be.
 
The BJ "PolledWait" leaks a handle index due to a JASS bug. You either need to call a custom implementation of "PolledWait" which nulls the local declared local timer or resort to some other method for timing.

Your mathematics look incorrect? Surely the X axis should be computed with "Cos" instead of "Sin"? I mean usually X is "Cos" and Y is "Sin" based on their mathematical meanings and phases such as "SOHCAHTOA".
 
Does seem like PolledWait can't be called in a loop, unfortunately. Any way to handle this otherwise?

Also, thanks for the catch, Dr Super Good. Guess I accidentally forgot to change it when I pasted the y part, heh.
 
I'd appreciate if someone could give me a more sophisticated answer, then, because I don't really have any experience with working with timers nor much experience with JASS, so I'm not entirely sure how to structure something like this.

If it helps, I found myself basing the exitwhen around the caster having a specific buff ( B00E ) since messing around made it apparent that basing the dummy spell on a self-only Roar seems more appropriate than Channel.
 
Trig_Ignis_Fatuus_JASS_Conditions
You cannot use TriggerSleepAction inside trigger conditions. Only inside timer callbacks and trigger actions. Calling TriggerSleepAction inside trigger conditions results in a thread crash.

PolledWait works by calling TriggerSleepAction as we all know from how it is implemented.

JASS:
function PolledWait takes real duration returns nothing
    local timer t
    local real  timeRemaining
    if (duration > 0) then
        set t = CreateTimer()
        call TimerStart(t, duration, false, null)
        loop
            set timeRemaining = TimerGetRemaining(t)
            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
        call DestroyTimer(t)
    endif
endfunction

If you want to use it, you need to call this custom implementation instead to prevent a handle index leak.

JASS:
function PolledWaitFix takes real duration returns nothing
    local timer t
    local real  timeRemaining
    if (duration > 0) then
        set t = CreateTimer()
        call TimerStart(t, duration, false, null)
        loop
            set timeRemaining = TimerGetRemaining(t)
            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
        call DestroyTimer(t)
        set t = null
    endif
endfunction
 
Status
Not open for further replies.
Back
Top