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

[Solved] FirstOfGroup loops or ForGroup? And how to make a unit cast multiple spells instantly

Status
Not open for further replies.
Level 26
Joined
Aug 18, 2009
Messages
4,097
Have both their points.

JASS:
function Start takes integer a, integer b returns nothing
    loop
        set u = FirstOfGroup(g)
        exitwhen (u == null)
        call GroupRemoveUnit(g, u)

        //actions
    endloop
endfunction

JASS:
function Enum takes nothing returns nothing
    local integer a = A
    local integer b = B

    //actions
endfunction

function Start takes integer a, integer b, code c returns nothing
    set A = a
    set B = b

    call ForGroup(g, c)
endfunction

On first, you stay in the same function/thread, can therefore use local variables whereas with traditional enuming values would have to be transferred globally.

If you wanted to have dynamic code, meaning to deliver what to run as a parameter, the loop would require boolexpr/trigger/ExecuteFunc string, at least first retrieve them out of a code parameter, which you could directly use in second but there again, you can only use that unless you execute from the Enum-function.

ForGroup is protected against adding units in the Enum-loop, won't pick the same unit twice. However, you also cannot remove from the execution stack. ForGroup does not clear the group.

When units decay, they still leave a reference in the group. ForGroup does not run for these but FirstOfGroup-loop. FirstOfGroup will return a null then, which breaks the end mark.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Depending on the circumstances you use ForGroup or FirstOfGroup loops.

If it's once-off enumerating then you should just use a null filter and a FirstOfGroup loop. Anyone who says a filter is faster than a FirstOfGroup loop needs to prove me wrong by posting a 1.24 or later benchmark, because no logic says opening a new thread for each iteration is going to be faster. I think the original benchmarks were when we needed to have a "return true" dummy filter.

If you need to store the units then you use FirstOfGroup and maybe a non-null filter.
 
Level 7
Joined
Apr 27, 2011
Messages
272
JASS:
loop
    set target=FirstOfGroup(affected)
    exitwhen target==null
    call GroupRemoveUnit(affected,target)
    if(IsUnitEnemy(target,pl))then
        call SetUnitX(caster,GetUnitX(target))
        call SetUnitY(caster,GetUnitY(target))
        call IssueTargetOrder(caster,orderstr,target)
    endif
endloop
Any comments would be appreciated provided that they are constructive.
 
Level 7
Joined
Apr 27, 2011
Messages
272
Fixed some stuff and now it works. Here's the code again.
JASS:
loop
    set target=FirstOfGroup(affected)
    exitwhen target==null
    call GroupRemoveUnit(affected,target)
    if(IsUnitEnemy(target,pl))then
        call UnitAddAbility(caster,spellid)
        call SetUnitX(caster,GetUnitX(target))
        call SetUnitY(caster,GetUnitY(target))
        call IssueTargetOrder(caster,orderstr,target)
        call UnitRemoveAbility(caster,spellid)
    endif
endloop
Now i can dummy cast spells on multiple units w/ only one dummy caster :D
 
Level 7
Joined
Dec 3, 2006
Messages
339
What ability was it? Did it have an spell cast duration? Maybe the ability is also part of the reason it was able to cast completely instantly?

Also i think Diablo Builder did as close as i've seen to this already sorta with item scrolls.
 
Level 7
Joined
Apr 27, 2011
Messages
272
I tried it with three spells. Entangling Roots, Frost Nova and Frenzy (spells must be instant).

Results:

Unholy Frenzy and Frenzy: 16 out 16 units got affected
Entangling Roots: 12 out of 16 got affected.
Frost Nova:10 out 16 got affected.

i will try to find out later why this happens if i have free time.
 
Level 7
Joined
Apr 27, 2011
Messages
272
Here's my theory on how the trick works, a single instance of ability (being cast) will only accept one order at a time... so we need to remove it and add it again in order to have a fresh instance of the ability that will accommodate the incoming order to cast.

btw... i haven't made a decent testmap yet.
 
Status
Not open for further replies.
Top