HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Problem with loops

03-13-2004, 06:59 PM#1
Grasthik
I'm creating a couple spells that I am trying to simplify the code by using loops (instead of having it do it 10 times...). I have looked up other's loops and used those for examples. I used Blizzard's "For each Integer A" as an example. I just can seem to figure out the problem.

Oh, and I tried to put the "exitwhen" at the beginning and the end.

Code:
function Trig_NovaShower3_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A004' ) ) then
        return false
    endif
    return true
endfunction

function Trig_NovaShower3_Actions takes nothing returns nothing
    local location NovaPoint
    local unit NovaUnit
    local integer NovaLoop = 0
    local integer NovaLoop2 = 4
    local location NovaSpellTarget
    set NovaSpellTarget = GetSpellTargetLoc()
    loop
       set NovaPoint = PolarProjectionBJ(NovaSpellTarget, GetRandomReal(0, 250.00), GetRandomDirectionDeg())
       call AddSpecialEffectLocBJ( NovaPoint, "Abilities\\Spells\\Human\\Blizzard\\BlizzardTarget.mdl" )
       call TriggerSleepAction( 0.80 )
       call CreateNUnitsAtLoc( 1, 'h001', GetOwningPlayer(GetTriggerUnit()), NovaPoint, bj_UNIT_FACING )
       set NovaUnit = GetLastCreatedUnit()
       call TriggerSleepAction( 1.00 )
       call RemoveUnit( NovaUnit )
       call ConditionalTriggerExecute( gg_trg_NovaDamage3 )
       set NovaLoop = NovaLoop + 1
       exitwhen NovaLoop > NovaLoop2
     endloop
     call RemoveLocation( NovaSpellTarget )
     call RemoveLocation( NovaPoint )
     set udg_NovaPoint = NovaPoint
     set udg_NovaUnit = GetTriggerUnit()
endfunction

//===========================================================================
function InitTrig_NovaShower3 takes nothing returns nothing
    set gg_trg_NovaShower3 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_NovaShower3, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_NovaShower3, Condition( function Trig_NovaShower3_Conditions ) )
    call TriggerAddAction( gg_trg_NovaShower3, function Trig_NovaShower3_Actions )
endfunction
03-13-2004, 08:55 PM#2
Vidstige
You could at least have told us how the problem appear... like does anything at all happen?
If the trigger actualle get started, it seems like the loop should run 5 times... if it doesn't crash.

Does the code compile at all?
Are you sure the trigger gets executed?
Are you sure the trigger doesn't crash?
Have you tried inserting debugging outputs?
03-13-2004, 09:03 PM#3
Grasthik
Does the code compile at all?
Yes

Are you sure the trigger gets executed?
Yes, the graphics (created by this trigger) show up

Are you sure the trigger doesn't crash?
It runs in an infinate loop...

Have you tried inserting debugging outputs?
Nope. Have no clue what these are heh.


Edit: Wierd...this one works now...all I did was move the global variables that appear after the loop into the loop so that they would be set for the trigger that is run after the fact

Here is the other one giving me fits:

Code:
function Trig_BlackHole_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction

function Trig_BlackHole_Func002001003 takes nothing returns boolean
    return ( IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(udg_BlackHoleUnit)) == true )
endfunction

function Trig_BlackHole_Func003A takes nothing returns nothing
    call SetUnitPositionLoc( GetEnumUnit(), PolarProjectionBJ(udg_BlackHolePoint, ( DistanceBetweenPoints(GetUnitLoc(udg_BlackHoleUnit), GetUnitLoc(GetEnumUnit())) - 100.00 ), AngleBetweenPoints(GetUnitLoc(udg_BlackHoleUnit), GetUnitLoc(GetEnumUnit()))) )
    call TriggerSleepAction( 0.50 )
endfunction

function Trig_BlackHole_Actions takes nothing returns nothing
    local group BlackHoleGroup
    local location BlackHolePoint
    local integer BlackHoleLoop = 0
    local integer BlackHoleLoop2 = 9
    call CreateNUnitsAtLoc( 1, 'h003', GetOwningPlayer(GetTriggerUnit()), GetSpellTargetLoc(), bj_UNIT_FACING )
    set udg_BlackHoleUnit = GetLastCreatedUnit()
    set BlackHolePoint = GetSpellTargetLoc()
    set udg_BlackHolePoint = GetSpellTargetLoc()
    call GroupAddGroup( GetUnitsInRangeOfLocMatching(1400.00, BlackHolePoint, Condition(function Trig_BlackHole_Func002001003)), BlackHoleGroup )
    loop
       call ForGroup( BlackHoleGroup, function Trig_BlackHole_Func003A )
       set BlackHoleLoop = BlackHoleLoop + 1
       exitwhen BlackHoleLoop > BlackHoleLoop2
    endloop
    call RemoveUnit( udg_BlackHoleUnit )
endfunction

//===========================================================================
function InitTrig_BlackHole takes nothing returns nothing
    set gg_trg_BlackHole = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_BlackHole, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_BlackHole, Condition( function Trig_BlackHole_Conditions ) )
    call TriggerAddAction( gg_trg_BlackHole, function Trig_BlackHole_Actions )
endfunction

This one just doesn't seem to work at all. The unit is never removed, but is created. I'm not sure whats going on with this one.
03-14-2004, 12:37 AM#4
Narwanza
Just a couple of JASS things that will help improve this. Here is an easier way to create a unit and set a variable eual to it.

Code:
    local unit u = null
    set u =  CreateUnitAtLoc(Player(0), 'hfoo', udg_myLocationVariable,bj_UNIT_FACING)
    call ExplodeUnitBJ(u)

Explode is more memory efficient that remove, and that sets a unit variable and creates unit in same stroke. It will only create 1 unit, but that seems it is all you need. I can't really see any problems in that code, are you sure the trigger that you call is good? Also remember that all handle variables should be set to null at the end of a function. You can find a huge list of handles at the beginning of the common.j. Also remember to use the call DestroyGroup() to get rid of used local groups.
03-14-2004, 02:00 AM#5
Grasthik
Ahh..thanks for the tips. I'm adding those in :). I'm still kinda newbie at JASS, getting better though. I added in the DestroyGroup and the efficient way of creating a unit...here's the code now:

Code:
function Trig_BlackHole_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction

function Trig_BlackHole_Func002001003 takes nothing returns boolean
    return ( IsPlayerEnemy(GetOwningPlayer(GetFilterUnit()), GetOwningPlayer(udg_BlackHoleUnit)) == true )
endfunction

function Trig_BlackHole_Func003A takes nothing returns nothing
    call SetUnitPositionLoc( GetEnumUnit(), PolarProjectionBJ(udg_BlackHolePoint, ( DistanceBetweenPoints(GetUnitLoc(udg_BlackHoleUnit), GetUnitLoc(GetEnumUnit())) - 100.00 ), AngleBetweenPoints(GetUnitLoc(udg_BlackHoleUnit), GetUnitLoc(GetEnumUnit()))) )
    call TriggerSleepAction( 0.50 )
endfunction

function Trig_BlackHole_Actions takes nothing returns nothing
    local group BlackHoleGroup
    local location BlackHolePoint
    local integer BlackHoleLoop = 0
    local integer BlackHoleLoop2 = 9
    set udg_BlackHoleUnit = call CreateUnitAtLoc( GetOwningPlayer(GetTriggerUnit()),'h003', GetSpellTargetLoc(), bj_UNIT_FACING )
    set BlackHolePoint = GetSpellTargetLoc()
    set udg_BlackHolePoint = GetSpellTargetLoc()
    call GroupAddGroup( GetUnitsInRangeOfLocAll(1400.00, BlackHolePoint), BlackHoleGroup )
    loop
       call ForGroup( BlackHoleGroup, function Trig_BlackHole_Func003A )
       set BlackHoleLoop = BlackHoleLoop + 1
       exitwhen BlackHoleLoop > BlackHoleLoop2
    endloop
    call ExplodeUnitBJ( udg_BlackHoleUnit )
    call DestroyGroup( BlackHoleGroup )
endfunction

//===========================================================================
function InitTrig_BlackHole takes nothing returns nothing
    set gg_trg_BlackHole = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_BlackHole, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_BlackHole, Condition( function Trig_BlackHole_Conditions ) )
    call TriggerAddAction( gg_trg_BlackHole, function Trig_BlackHole_Actions )
endfunction

Also, I'm not sure what you mean by headers?
And the "Trigger" that is called was created above that function. It's actually calling a function :).

Edit: Doesn't Compile....the set u = CreateUnitAtLoc thing isn't compling?
Edit2: Could it be cause it is a global instead of a local?
03-14-2004, 03:55 AM#6
Grasthik
Fixed My Own Problem...
Thanks for your help though :). It seems that you can't use 2 Loops within 1 Function or something to that degree. I had to seperate it into 3 Different Triggers. It may seem excessive, but atleast it works.

Here is the Finished Code:

Code:
function Trig_BlackHole_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction

function Trig_BlackHole_Actions takes nothing returns nothing
    local group BlackHoleGroup
    local location BlackHolePoint
    local integer BlackHoleLoop = 0
    local integer BlackHoleLoop2 = 29
    call CreateUnitAtLoc( GetOwningPlayer(GetTriggerUnit()),'h003', GetSpellTargetLoc(), bj_UNIT_FACING )
    set udg_BlackHoleUnit = GetLastCreatedUnit()
    set BlackHolePoint = GetSpellTargetLoc()
    set udg_BlackHolePoint = GetSpellTargetLoc()
    call GroupAddGroup( GetUnitsInRangeOfLocAll(1400.00, BlackHolePoint), udg_BlackHoleGroup )
    loop
       call ConditionalTriggerExecute( gg_trg_BlackHole2 )
       call TriggerSleepAction( 0.20 )
       set BlackHoleLoop = BlackHoleLoop + 1
       exitwhen BlackHoleLoop > BlackHoleLoop2
    endloop
    call ConditionalTriggerExecute( gg_trg_BlackHole3 )
    call DestroyGroup( BlackHoleGroup )
endfunction

//===========================================================================
function InitTrig_BlackHole takes nothing returns nothing
    set gg_trg_BlackHole = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_BlackHole, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_BlackHole, Condition( function Trig_BlackHole_Conditions ) )
    call TriggerAddAction( gg_trg_BlackHole, function Trig_BlackHole_Actions )
endfunction

Code:
BlackHole2
    Events
    Conditions
    Actions
        Unit Group - Pick every unit in BlackHoleGroup and do (Actions)
            Loop - Actions
                Unit - Move (Picked unit) instantly to (BlackHolePoint offset by ((Distance between BlackHolePoint and (Position of (Picked unit))) - 50.00) towards (Angle from BlackHolePoint to (Position of (Picked unit))) degrees)

Code:
BlackHole3
    Events
    Conditions
    Actions
        Unit - Remove BlackHoleUnit from the game

I had to create the last trigger because for some reason that unit wasn't being removed after the duration of the loop. So I went ahead and seperated it from the original trigger. Also, I found no need in converting the last 2 triggers into JASS. GUI seemed to have everything covered.
03-14-2004, 04:07 AM#7
Narwanza
The reason your unit was not removed in the function is because you used GetLastCreatedUnit() with a CreateUnitAtLoc() funciton. For some gay reason it doesn't work. GetLastCreatedUnit() only works with the CreateNUnitsAtLoc() function. So what you have to do is define a local unit and set it to null originally.
Code:
    local unit u = null
Then do the thing I showed you before.
Code:
    set u = Create......
Now you can remove the unit u from the game and do whatever you want to to it. Don't worry, I get criticizm from weaaddar and Cubasis40 all the time for not having optimized functions. We all need criticizm to get better.

Oh, and if you want to call another function in the same trigger just do:
call MyFuncName
This way you don't have to have separate triggers. Then you can pass variables between functions eliminating the need for global variables at all.
03-14-2004, 03:41 PM#8
Grasthik
I didn't think you could use locals between 2 Functions even in the same code?

Edit: Updated Code (Didn't add 2nd Trigger to first because I still do not know if locals work in between functions)

Code:
function Trig_BlackHole_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction

function Trig_BlackHole_Actions takes nothing returns nothing
    local group BlackHoleGroup = null
    local unit BlackHoleUnit = null
    local integer BlackHoleLoop = 0
    local integer BlackHoleLoop2 = 29
    set BlackHoleUnit = CreateUnitAtLoc( GetOwningPlayer(GetTriggerUnit()),'h003', GetSpellTargetLoc(), bj_UNIT_FACING )
    set udg_BlackHolePoint = GetSpellTargetLoc()
    call GroupAddGroup( GetUnitsInRangeOfLocAll(1400.00, udg_BlackHolePoint), udg_BlackHoleGroup )
    loop
       call ConditionalTriggerExecute( gg_trg_BlackHole2 )
       call TriggerSleepAction( 0.20 )
       set BlackHoleLoop = BlackHoleLoop + 1
       exitwhen BlackHoleLoop > BlackHoleLoop2
    endloop
    call DestroyGroup( BlackHoleGroup )
    call ExplodeUnitBJ( BlackHoleUnit )
endfunction

//===========================================================================
function InitTrig_BlackHole takes nothing returns nothing
    set gg_trg_BlackHole = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_BlackHole, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_BlackHole, Condition( function Trig_BlackHole_Conditions ) )
    call TriggerAddAction( gg_trg_BlackHole, function Trig_BlackHole_Actions )
endfunction

Another Question, is null necessary to use? I added it in just in case.

Edit2:
I'm getting an "Expected expression" for the set local = call create....

Edit3:
NM...found the problem and edited it in. I was using "set local = call create" instead of just "set local = create"
03-14-2004, 04:05 PM#9
Cubasis
Quote:
Originally Posted by Grasthik
I didn't think you could use locals between 2 Functions even in the same code?

Edit: Updated Code (Didn't add 2nd Trigger to first because I still do not know if locals work in between functions)

Another Question, is null necessary to use? I added it in just in case.

Edit2:
I'm getting an "Expected expression" for the set local = call create....

Edit3:
NM...found the problem and edited it in. I was using "set local = call create" instead of just "set local = create"

Hey,

Did you notice the "takes nothing returns nothing" thing in the function header (the top-most line in the function). Well, there you can allow your function to be "passed" values/whatever. That's how you allow locals to work between many functions, that is. If you want to use your unit-local in another function, you make that function "takes unit u" (you can add more stuff by adding a comma and other stuff, like: "takes unit u, integer i, string s" or whatever). These things become local variables in your new function, so you would then use them just like normal local variables. The name of these don't matter either.

So then if you wanna call another function which takes a unit. Then you just:

call MyFunction( u ) //where u is a unit-variable or sumtin.

I hope you understand this, as this is a important part of function-oriented languages. The return part of the header also allows you to specify a return-value, if you want to return something. F.ex., CreateUnitAtLoc "returns" a unit, that's why you can do this: set u = CreateUnitAtLoc( .... )


Nulling (de-referencing) stuff is only useful at the bottom of your function, and only for "local" handle-type variables (like locations and groups (units too, but they are not all that critical to de-reference), not integers, strings or reals).


And as you noticed, you don't write "set # = call ..."

Cubasis
03-14-2004, 04:26 PM#10
Grasthik
Quote:
I hope you understand this

Completely. I am new to coding languages, but I can just about read all that I have come across. I just need to learn how to write :).

So, at the END of the function I need to dereference variables? What if they are destroyed? I always heard it was good practice to Destroy groups/locations. (I had forgotten about groups).

Edit: Added Updated Code, But It isn't compiling right. It is telling me that I need to call a function (call function_BlackHole2_Actions line). I don't see anything wrong with it?

Code:
function Trig_BlackHole_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction

function Trig_BlackHole2_Func001A takes group BlackHoleGroup, location BlackHolePoint returns nothing
    call SetUnitPositionLoc( GetEnumUnit(), PolarProjectionBJ(BlackHolePoint, ( DistanceBetweenPoints(BlackHolePoint, GetUnitLoc(GetEnumUnit())) - 50.00 ), AngleBetweenPoints(BlackHolePoint, GetUnitLoc(GetEnumUnit()))) )
endfunction

function Trig_BlackHole2_Actions takes group BlackHoleGroup, location BlackHolePoint returns nothing
    call ForGroup( BlackHoleGroup, function Trig_BlackHole2_Func001A )
endfunction

function Trig_BlackHole_Actions takes nothing returns nothing
    local group BlackHoleGroup = null
    local unit BlackHoleUnit = null
    local location BlackHolePoint
    local integer BlackHoleLoop = 0
    local integer BlackHoleLoop2 = 29
    set BlackHoleUnit = CreateUnitAtLoc( GetOwningPlayer(GetTriggerUnit()),'h003', GetSpellTargetLoc(), bj_UNIT_FACING )
    set BlackHolePoint = GetSpellTargetLoc()
    call GroupAddGroup( GetUnitsInRangeOfLocAll(1400.00, BlackHolePoint), BlackHoleGroup )
    loop
       call function Trig_BlackHole2_Actions( BlackHoleGroup, BlackHolePoint )
       call TriggerSleepAction( 0.20 )
       set BlackHoleLoop = BlackHoleLoop + 1
       exitwhen BlackHoleLoop > BlackHoleLoop2
    endloop
    call DestroyGroup( BlackHoleGroup )
    call ExplodeUnitBJ( BlackHoleUnit )
    call RemoveLocation( BlackHolePoint )
endfunction

//===========================================================================
function InitTrig_BlackHole takes nothing returns nothing
    set gg_trg_BlackHole = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_BlackHole, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_BlackHole, Condition( function Trig_BlackHole_Conditions ) )
    call TriggerAddAction( gg_trg_BlackHole, function Trig_BlackHole_Actions )
    call TriggerAddAction( gg_trg_BlackHole, function Trig_BlackHole2_Actions )
    call TriggerAddAction( gg_trg_BlackHole, function Trig_BlackHole2_Func001A )
endfunction

Edit2: With the new local location I had forgotten to destroy it. Added in.
03-14-2004, 07:08 PM#11
Narwanza
Oh, you don't need the function. Just do:
Code:
    call Trig_BlackHole2_Actions(BlackHoleGroup, BlackHolePoint)
Yikes, you are calling a funciton that all it does is call a function? Kind of pointless I would think. Also, you have parameters taken on your ForGroup function, that will give you compile errors. There are a few things that require the takes nothing returns nothing signautre, such as action funcitons, condition functions, and ForGroup funcitons. There are others, but those are the major ones. I think the only way you are going to be able to use locals and still do what you want is to loop inside of you loop. Here is an example.

Code:
function Trig_BlackHole_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction

function Trig_BlackHole_Actions takes nothing returns nothing
    local group BlackHoleGroup = CreateGroup()
    local unit BlackHoleUnit = null
    local location BlackHolePoint
    local integer array BlackHoleLoop
    local unit tempunit = null
    local location temploc = null
    set BlackHolePoint = GetSpellTargetLoc()
    set BlackHoleUnit = CreateUnitAtLoc( GetOwningPlayer(GetSpellAbilityUnit()),'h003', BlackHolePoint, bj_UNIT_FACING )
    call GroupAddGroup( GetUnitsInRangeOfLocAll(1400.00, BlackHolePoint), BlackHoleGroup )
    set BlackHoleLoop[1] = 0
    set BlackHoleLoop[2] = 29
    loop
       exitwhen BlackHoleLoop[1] >= BlackHoleLoop[2]
       loop
       	   set tempunit = FirstOfGroup(BlackHoleGroup)
           exitwhen tempunit == null
           set temploc = GetUnitLoc(tempunit)
           call SetUnitPositionLoc( tempunit, PolarProjectionBJ(BlackHolePoint, ( DistanceBetweenPoints(BlackHolePoint, temploc) - 50.00 ), AngleBetweenPoints(BlackHolePoint, temploc)) )
           call GroupRemoveUnit(BlackHoleGroup,tempunit)
           call RemoveLocation(temploc)
       endloop
       call TriggerSleepAction( 0.20 )
       set BlackHoleLoop[1] = BlackHoleLoop[1] + 1
    endloop
    call DestroyGroup( BlackHoleGroup )
    call ExplodeUnitBJ( BlackHoleUnit )
    call RemoveLocation( BlackHolePoint )
    call RemoveLocation(temploc)
    set BlackHoleGroup = null
    set BlackHoleUnit = null
    set BlackHolePoint = null
    set temploc = null
    set tempunit = null
endfunction

//==================================================  =========================
function InitTrig_BlackHole takes nothing returns nothing
    set gg_trg_BlackHole = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_BlackHole, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_BlackHole, Condition( function Trig_BlackHole_Conditions ) )
    call TriggerAddAction( gg_trg_BlackHole, function Trig_BlackHole_Actions )
endfunction

There, that is much better now. If it still has problems ask me.
03-14-2004, 07:46 PM#12
Grasthik
Couple of questions/comments. It all checks out fine, but as I am trying to learn to do this so that I don't have to constantly bug everyone, I am going to try and understand what you did.

Question: Why use arrays? It seems to me you are using one more line creating an array than just using 2 different variables?

Comment: The reason for the TriggerSleepAction(0.20) was so that they had a "moving" effect. I just moved the TriggerSleepAction up into the 2nd Loop.

Question: So even though I am destroying groups and removing locs, I still need to set them to null?

Question: I didn't know that there was a "FirstofGroup" pointer. I have a pretty good idea of what it is but can you enlighten me on the subject?

Thanks for you help again.

Edit:
Question: After making corrections, it seems like the 2nd loop is just redundant-

Code:
    loop
       exitwhen BlackHoleLoop[1] >= BlackHoleLoop[2]
       loop
       	   set tempunit = FirstOfGroup(BlackHoleGroup)
           exitwhen tempunit == null
           set temploc = GetUnitLoc(tempunit)
           call SetUnitPositionLoc( tempunit, PolarProjectionBJ(BlackHolePoint, ( DistanceBetweenPoints(BlackHolePoint, temploc) - 50.00 ), AngleBetweenPoints(BlackHolePoint, temploc)) )
           call GroupRemoveUnit(BlackHoleGroup,tempunit)
           call RemoveLocation(temploc)
           call TriggerSleepAction( 0.20 )
       endloop
       set BlackHoleLoop[1] = BlackHoleLoop[1] + 1
    endloop
-should I take it out?

One more: You set your "exitwhen"s at the beginning of the loop and made them >=. Is that for some reason more sound programming than mine?

Edit2: I just reread that code and now I understand it. It choses single units, moves them, runs through the loop until it has no more units in that group. But after that wouldn't there be no more units within BlackHoleGroup? You never restate the group and thus the loop would only work 1 time correct?

Here is what I updated it to:
Code:
function Trig_BlackHole3_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction

function Trig_BlackHole3_Actions takes nothing returns nothing
    local group BlackHoleGroup = CreateGroup()
    local unit BlackHoleUnit = null
    local location BlackHolePoint
    local integer array BlackHoleLoop
    local unit tempunit = null
    local location temploc = null
    set BlackHolePoint = GetSpellTargetLoc()
    set BlackHoleUnit = CreateUnitAtLoc( GetOwningPlayer(GetSpellAbilityUnit()),'h003', BlackHolePoint, bj_UNIT_FACING )
    call GroupAddGroup( GetUnitsInRangeOfLocAll(1400.00, BlackHolePoint), BlackHoleGroup )
    set BlackHoleLoop[1] = 0
    set BlackHoleLoop[2] = 29
    loop
       exitwhen BlackHoleLoop[1] >= BlackHoleLoop[2]
       call GroupAddGroup( GetUnitsInRangeOfLocAll(1400.00, BlackHolePoint), BlackHoleGroup )
       loop
           set tempunit = FirstOfGroup(BlackHoleGroup)
           exitwhen tempunit == null
           set temploc = GetUnitLoc(tempunit)
           call SetUnitPositionLoc( tempunit, PolarProjectionBJ(BlackHolePoint, ( DistanceBetweenPoints(BlackHolePoint, temploc) - 50.00 ), AngleBetweenPoints(BlackHolePoint, temploc)) )
           call GroupRemoveUnit(BlackHoleGroup,tempunit)
           call RemoveLocation(temploc)
       endloop
       call TriggerSleepAction( 0.20 )
       set BlackHoleLoop[1] = BlackHoleLoop[1] + 1
    endloop
    call DestroyGroup( BlackHoleGroup )
    call ExplodeUnitBJ( BlackHoleUnit )
    call RemoveLocation( BlackHolePoint )
    call RemoveLocation(temploc)
    set BlackHoleGroup = null
    set BlackHoleUnit = null
    set BlackHolePoint = null
    set temploc = null
    set tempunit = null
endfunction

//==================================================    =========================
function InitTrig_BlackHole3 takes nothing returns nothing
    set gg_trg_BlackHole = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_BlackHole, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_BlackHole, Condition( function Trig_BlackHole3_Conditions ) )
    call TriggerAddAction( gg_trg_BlackHole, function Trig_BlackHole3_Actions )
endfunction

Edit3: Bah..more questions: Why do you need to create a group?
03-14-2004, 08:18 PM#13
Narwanza
Quote:
Question: Why use arrays? It seems to me you are using one more line creating an array than just using 2 different variables?
I was going to use 4 integer variables when I first started editing it and it is just easier to have 1 array than 4 variables. I ended up only using the two that you had earlier, but that is why they are arrays. No real point except just easier to read.

Quote:
Question: So even though I am destroying groups and removing locs, I still need to set them to null?
This is a sticky subject in my mind. Cubasis maintains that local variables only need be dereferenced at the end of a funciton, but I would argue that they need to be dereferenced before a new value is assigned to them. I dereferenced all handles at the end of your function, but I don't think it would be necessary to dereference them in a loop.

Quote:
Question: I didn't know that there was a "FirstofGroup" pointer. I have a pretty good idea of what it is but can you enlighten me on the subject?
FirstOfGroup works kind of like GroupPickRandomUnit, except that it is faster. It always points to the same unit in a group so therefore it doesn't have to compute a random pointer. If you called FirstOfGroup 50000 times it would always return same unit wheras GroupPickRandomUnit would do different units. For the purpose we had here it was definitly more efficient to use FirstOfGroup.

Quote:
Edit3: Bah..more questions: Why do you need to create a group?
In this case it wasn't necessary since you were using the GroupAddGroup function, but it is good to always get in the habit of creating groups when defined as local variables. If you don't "Create the group" you can't set it equal to anything because it doesn't exist.

And finally about the group thing. Create another local variable group and set it equal to Units within 1400 of blah, blah, blah. Then add that group to the black hole group. This will stop it from creating usless temp groups that waste memory. Then destroy the group at end of funciton and derefernce it.
03-14-2004, 08:30 PM#14
Grasthik
Ok, thanks :). Here is the updated code:

Code:
function Trig_BlackHole3_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A005' ) ) then
        return false
    endif
    return true
endfunction

function Trig_BlackHole3_Actions takes nothing returns nothing
    local group BlackHoleGroup = CreateGroup()
    local group BlackHoleGroup2 = CreateGroup()
    local unit BlackHoleUnit = null
    local location BlackHolePoint
    local integer array BlackHoleLoop
    local unit tempunit = null
    local location temploc = null
    set BlackHolePoint = GetSpellTargetLoc()
    set BlackHoleUnit = CreateUnitAtLoc( GetOwningPlayer(GetSpellAbilityUnit()),'h003', BlackHolePoint, bj_UNIT_FACING )
    call GroupAddGroup( GetUnitsInRangeOfLocAll(1400.00, BlackHolePoint), BlackHoleGroup2 )
    set BlackHoleLoop[1] = 0
    set BlackHoleLoop[2] = 29
    loop
       exitwhen BlackHoleLoop[1] >= BlackHoleLoop[2]
       call GroupAddGroup( BlackHoleGroup2, BlackHoleGroup )
       loop
           set tempunit = FirstOfGroup(BlackHoleGroup)
           exitwhen tempunit == null
           set temploc = GetUnitLoc(tempunit)
           call SetUnitPositionLoc( tempunit, PolarProjectionBJ(BlackHolePoint, ( DistanceBetweenPoints(BlackHolePoint, temploc) - 50.00 ), AngleBetweenPoints(BlackHolePoint, temploc)) )
           call GroupRemoveUnit(BlackHoleGroup,tempunit)
           call RemoveLocation(temploc)
       endloop
       call TriggerSleepAction( 0.20 )
       set BlackHoleLoop[1] = BlackHoleLoop[1] + 1
    endloop
    call DestroyGroup( BlackHoleGroup )
    call DestroyGroup( BlackHoleGroup2 )
    call ExplodeUnitBJ( BlackHoleUnit )
    call RemoveLocation( BlackHolePoint )
    call RemoveLocation(temploc)
    set BlackHoleGroup = null
    set BlackHoleGroup2 = null
    set BlackHoleUnit = null
    set BlackHolePoint = null
    set temploc = null
    set tempunit = null
endfunction

//==================================================    =========================
function InitTrig_BlackHole3 takes nothing returns nothing
    set gg_trg_BlackHole3 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_BlackHole3, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_BlackHole3, Condition( function Trig_BlackHole3_Conditions ) )
    call TriggerAddAction( gg_trg_BlackHole3, function Trig_BlackHole3_Actions )
endfunction

Edit: Had to edit the Initialization of the trigger, I forgot to change them from BlackHole to BlackHole3
03-14-2004, 09:21 PM#15
Narwanza
Looks wonderful, the only thing that might leak is the first GroupAddGroup. It definitly wouldn't leak if you just did:

set BlackHoleGoup2 = units within 1400

As it is now it may leak a temporary group made to add to the group variable. Other than that it looks awsome. Oh, just a little sidenote, you can't wait any less that .25 seconds using TriggerSleepAction(.*). You can enter in .001 and it will still compile, but it won't go any faster than .25. To get faster than .25 you have to use periodic timers and some tricky stuff. Or TriggerSleepAction(0) seems to be faster, but inconsistent. Probably not really crucial to this function, but good to know for future use.