HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

CreateUnit not working (sometimes)

08-23-2009, 07:02 PM#1
Vulcano
In this trigger (and in an other vJASS trigger) CreateUnit is sometimes not working, it sets bj_LastCreatedUnit to null and doesn't place the unit. I posted this 2 weeks ago on HiveWorkshop but none answering :s.

Trigger:
Forked Banish
Collapse Events
Unit - A unit Starts the effect of an ability
Collapse Conditions
(Ability being cast) Equal to Chain Banish (|cffdc143cUltimate|r)
Collapse Actions
Set tempPoint = (Position of (Triggering unit))
Set point1 = (Position of (Target unit of ability being cast))
Set tempInt = 0
-------- - --------
-------- Cast Banish on target --------
Unit - Create 1 caster 5 sec for (Owner of (Triggering unit)) at tempPoint facing Default building facing degrees
Unit - Add Chain Banish (dummy) to (Last created unit)
Unit - Order (Last created unit) to Orc Far Seer - Chain Lightning (Target unit of ability being cast)
Unit - Create 1 caster 5 sec for (Owner of (Triggering unit)) at tempPoint facing Default building facing degrees
Unit - Add Banish to (Last created unit)
Unit - Order (Last created unit) to Human Blood Mage - Banish (Target unit of ability being cast)
-------- - --------
-------- Cast Banish on random targets around target --------
Set tempGroup = (Units within 400.00 of point1 matching (((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True))
Unit Group - Remove (Target unit of ability being cast) from tempGroup
Collapse Unit Group - Pick every unit in tempGroup and do (Actions)
Collapse Loop - Actions
Set tempInt = (tempInt + 1)
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
7 Greater than tempInt
Collapse Then - Actions
Unit - Create 1 caster 5 sec for (Owner of (Casting unit)) at tempPoint facing Default building facing degrees
If ((Last created unit) Equal to No unit) then do (Game - Display to (All players) the text: bla) else do (Do nothing)
Unit - Add Chain Banish (dummy) to (Last created unit)
Unit - Order (Last created unit) to Orc Far Seer - Chain Lightning (Picked unit)
Unit - Create 1 caster 5 sec for (Owner of (Triggering unit)) at tempPoint facing Default building facing degrees
Unit - Add Banish to (Last created unit)
Unit - Order (Last created unit) to Human Blood Mage - Banish (Picked unit)
Else - Actions
Custom script: call DestroyGroup(udg_tempGroup)
Custom script: call RemoveLocation( udg_tempPoint )
Custom script: call RemoveLocation( udg_point1 )

I get 6 times bla when i cast spell, the other units are created.

EDIT:This vJASS spell isn't working either, same problem but nown using CreateUnit:
Collapse JASS:
scope ChainBanish initializer Init
    globals
        private constant integer SPELLID = 'A01O'
        private constant integer BANISHID = 'A00P'
        private constant integer TARGETS = 7
        private constant integer DUMMY = 'h009'
        private constant real PERIOD = 1.40
        private constant real BOUNCERANGE = 700.00
    endglobals
    
    //=============================================================================
    
    globals
        private boolexpr be
    endglobals    
    
    private function isUnitAlly takes nothing returns boolean
        return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit()))
    endfunction
    
    private struct Chain
        unit array targets[TARGETS]
        integer index
        
        static method create takes unit u1 returns Chain
            local Chain chain = Chain.allocate()
            set chain.targets[0] = u1
            set chain.index = 0
            return chain
        endmethod
                
        method Banish2 takes nothing returns nothing
            local unit dummy = CreateUnit( GetOwningPlayer(GetTriggerUnit()), DUMMY, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), bj_UNIT_FACING)
            call UnitAddAbility(dummy, BANISHID)
            call IssueTargetOrder(dummy, "banish", .targets[.index])            
            set dummy = null
        endmethod
        
        method SetNextUnit takes nothing returns boolean
            local group units = CreateGroup()
            local integer i = 0
            
            if .index == (TARGETS - 1) then
                call DestroyGroup(units)
                set units = null
                return false
            endif
            
            call GroupEnumUnitsInRange(units, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), BOUNCERANGE, be)
            set .index = .index + 1
            loop
                exitwhen i == .index
                if .targets[i] == FirstOfGroup(units) then
                    call GroupRemoveUnit( units, FirstOfGroup(units))
                    set i = -1
                endif
                set i = i + 1                
            endloop
            set .targets[.index] = FirstOfGroup(units)                        
            
            call DestroyGroup(units)
            set units = null            
                        
            if .targets[.index] != null then
                return true
            else
                return false
            endif
        endmethod
    endstruct
    
    private function Banish takes nothing returns nothing
        local Chain chain = GetTimerData(GetExpiredTimer())
        local unit dummy = null
        if chain.SetNextUnit() != true then            
            call chain.destroy()
            call ReleaseTimer(GetExpiredTimer())            
        else
            set dummy = CreateUnit( GetOwningPlayer(GetTriggerUnit()), DUMMY, GetUnitX(chain.targets[chain.index - 1]),  GetUnitY(chain.targets[chain.index - 1]), bj_UNIT_FACING)
            debug if dummy == null then
                debug call BJDebugMsg("CL unit not created")
            debug endif
            call UnitAddAbility(dummy, SPELLID)
            call IssueTargetOrder(dummy, "chainlightning", chain.targets[chain.index])
            set dummy = CreateUnit( GetOwningPlayer(GetTriggerUnit()), DUMMY, GetUnitX(chain.targets[chain.index]), GetUnitY(chain.targets[chain.index]), bj_UNIT_FACING)
            debug if dummy == null then
                debug call BJDebugMsg("Banish unit not created")
            debug endif
            call UnitAddAbility(dummy, BANISHID)
            call IssueTargetOrder(dummy, "banish", chain.targets[chain.index])            
            set dummy = null
        endif           
    endfunction
    
    private function Actions takes nothing returns nothing
        local Chain chain = Chain.create(GetSpellTargetUnit())
        local timer t = NewTimer()
        call chain.Banish2()
        call SetTimerData( t, chain)
        call TimerStart( t, PERIOD, true, function Banish)
        set t = null
    endfunction
    
    private function Conditions takes nothing returns boolean
        return IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) and (GetSpellAbilityId() == SPELLID)
    endfunction

    private function Init takes nothing returns nothing
        local trigger gg_trg_Chain_Banish = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_Chain_Banish, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( gg_trg_Chain_Banish, Condition( function Conditions ) )
        call TriggerAddAction( gg_trg_Chain_Banish, function Actions )
        
        set be = Condition(function isUnitAlly)
    endfunction
endscope

I get the debug messages from the Banish function each interval
08-23-2009, 07:50 PM#2
Komaqtion
Well... Maybe it is only the BJ CreateNUnitsAtLoc that's buggy ? :S
As I don't believe the the native CreateUnit bugs this way, right ? :o
08-24-2009, 05:44 PM#3
Vulcano
@Komaqtion: see EDIT first post

BTW: Can't that VERY irritating 600 seconds between posts be removed?
08-24-2009, 05:47 PM#4
Rising_Dusk
Quote:
Originally Posted by Vulcano
BTW: Can't that VERY irritating 600 seconds between posts be removed?
Yes, be registered at the website for longer than a few months. This simply prevents spam attacks from users with 0 rep and who haven't been registered for very long.
08-25-2009, 10:19 AM#5
TheWye
Anyway, why to you use "Owner of Triggering Unit" at some lines and "Owner of Casting Unit" at the others?

EDIT: and try to put a temporary unit variable in the GUI code to refer to the Casting unit. I have this weird experience when I was a GUI user where the code fail to refer to the "Casting Unit" when I refer to it too many times in a trigger. Try to put the casting unit in a variable first. Maybe that will help.
08-25-2009, 12:46 PM#6
0zyx0
Are you sure the type of the dummy unit you are trying to create exists? And do you have any events running when a unit enters the map? If that's the case, try disabling those, to find the source of the problem.
08-25-2009, 05:03 PM#7
Vulcano
@TheWye: It works! when i first read your post i thought: "a noob who uses waits" but casting units indeed bugs when using it multiple times.

EDIT:
-Now going to see if i have same problem in vJASS spell.
-Target unit of ability being cast also has same problem btw (target unit wasn't banished(sometimes :p))
-Here is working code in case someone wants this "extremely fantastic" spell.

Trigger:
Forked Banish
Collapse Events
Unit - A unit Starts the effect of an ability
Collapse Conditions
(Ability being cast) Equal to Chain Banish (|cffdc143cUltimate|r)
Collapse Actions
Set tempUnit = (Triggering unit)
Set tempUnit2 = (Target unit of ability being cast)
Set tempPoint = (Position of tempUnit)
Set point1 = (Position of tempUnit2)
Set tempInt = 0
-------- - --------
-------- Cast Banish on target --------
Unit - Create 1 caster 5 sec for (Owner of tempUnit) at tempPoint facing Default building facing degrees
Unit - Add Chain Banish (dummy) to (Last created unit)
Unit - Order (Last created unit) to Orc Far Seer - Chain Lightning tempUnit2
Unit - Create 1 caster 5 sec for (Owner of tempUnit) at tempPoint facing Default building facing degrees
If ((Last created unit) Equal to No unit) then do (Game - Display to (All players) the text: BeforeLoop) else do (Do nothing)
Unit - Add Banish to (Last created unit)
Unit - Order (Last created unit) to Human Blood Mage - Banish tempUnit2
-------- - --------
-------- Cast Banish on random targets around target --------
Set tempGroup = (Units within 400.00 of point1 matching (((Matching unit) belongs to an enemy of (Owner of tempUnit)) Equal to True))
Unit Group - Remove (Target unit of ability being cast) from tempGroup
Collapse Unit Group - Pick every unit in tempGroup and do (Actions)
Collapse Loop - Actions
Set tempInt = (tempInt + 1)
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
7 Greater than tempInt
Collapse Then - Actions
Unit - Create 1 caster 5 sec for (Owner of tempUnit) at tempPoint facing Default building facing degrees
If ((Last created unit) Equal to No unit) then do (Game - Display to (All players) the text: bla) else do (Do nothing)
Unit - Add Chain Banish (dummy) to (Last created unit)
Unit - Order (Last created unit) to Orc Far Seer - Chain Lightning (Picked unit)
Unit - Create 1 caster 5 sec for (Owner of tempUnit) at tempPoint facing Default building facing degrees
Unit - Add Banish to (Last created unit)
Unit - Order (Last created unit) to Human Blood Mage - Banish (Picked unit)
Else - Actions
Custom script: call DestroyGroup(udg_tempGroup)
Custom script: call RemoveLocation( udg_tempPoint )
Custom script: call RemoveLocation( udg_point1 )

-Edit2: I had same problem in the vJASS spell, so GetTriggerUnit can also bug
-Edit3: All dummies are now created in the vJASS spell but it's not working completely:
-The spell only works once. After that it only banishes and casts lightning on the first target of the spell or hitting units that aren't hit yet by a previous cast.

Maybe something wrong with the boolexpr?
Here is the trigger:
Collapse JASS:
scope ChainBanish initializer Init
    globals
        private constant integer SPELLID = 'A01O'
        private constant integer BANISHID = 'A00P'
        private constant integer LIGHTNINGID = 'A01Q'
        private constant integer TARGETS = 7
        private constant integer DUMMY = 'h009'
        private constant real PERIOD = 0.50
        private constant real BOUNCERANGE = 700.00
    endglobals
    
    //=============================================================================
    
    globals
        private boolexpr be
        private constant integer TARGETSPLUSONE = TARGETS + 1
    endglobals    
    
    private function isUnitAlly takes nothing returns boolean
        return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit()))
    endfunction
    
    private struct Chain
        unit array targets[TARGETSPLUSONE]
        integer index
        
        static method create takes unit u1, unit u2 returns Chain
            local Chain chain = Chain.allocate()
            set chain.targets[0] = u1
            set chain.targets[1] = u2
            set chain.index = 1
            return chain
        endmethod
                
        method BanishAndLightning takes nothing returns nothing
            local unit dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), bj_UNIT_FACING)
            debug call BJDebugMsg("BanishAndLightning")            
            call UnitAddAbility(dummy, BANISHID)
            call IssueTargetOrder(dummy, "banish", .targets[.index])            
            
            set dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index - 1]),  GetUnitY(.targets[.index - 1]), bj_UNIT_FACING)
            call UnitAddAbility(dummy, LIGHTNINGID)
            call IssueTargetOrder(dummy, "chainlightning", .targets[.index])
            
            set dummy = null
        endmethod
        
        method SetNextUnit takes nothing returns boolean
            local group units = CreateGroup()
            local integer i = 0
            
            if .index == (TARGETS) then
                call DestroyGroup(units)
                set units = null
                debug call BJDebugMsg("targets full")
                return false
            endif
            
            call GroupEnumUnitsInRange(units, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), BOUNCERANGE, be)
            set .index = .index + 1
            loop
                exitwhen i == .index
                if .targets[i] == FirstOfGroup(units) then
                    call GroupRemoveUnit( units, FirstOfGroup(units))
                    set i = -1
                endif
                set i = i + 1                
            endloop
            set .targets[.index] = FirstOfGroup(units)                        
            
            call DestroyGroup(units)
            set units = null            
                        
            if .targets[.index] != null then
                debug call BJDebugMsg("unit found")
                debug call AddSpecialEffectTarget( "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl", .targets[.index], "origin")
                return true
            else
                debug call BJDebugMsg("unit not found")
                return false
            endif
        endmethod
    endstruct
    
    private function Loop takes nothing returns nothing
        local Chain chain = GetTimerData(GetExpiredTimer())
        local unit dummy = null
        
        if chain.SetNextUnit() != true then            
            call chain.destroy()
            call ReleaseTimer(GetExpiredTimer())            
        else
            call chain.BanishAndLightning()
        endif           
    endfunction
    
    private function Actions takes nothing returns nothing
        local Chain chain = Chain.create(GetTriggerUnit(), GetSpellTargetUnit())
        local timer t = NewTimer()
        call chain.BanishAndLightning()
        call SetTimerData( t, chain)
        call TimerStart( t, PERIOD, true, function Loop)
        set t = null
    endfunction
    
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELLID
    endfunction

    private function Init takes nothing returns nothing
        local trigger gg_trg_Chain_Banish = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_Chain_Banish, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( gg_trg_Chain_Banish, Condition( function Conditions ) )
        call TriggerAddAction( gg_trg_Chain_Banish, function Actions )
        
        set be = Condition(function isUnitAlly)
    endfunction
endscope
08-25-2009, 07:39 PM#8
TheWye
Muahaha, that will teach you not to mess with GUI-wielding Grandpa here :p

Anyway, what's the local unit dummy for here?
Collapse JASS:
    private function Loop takes nothing returns nothing
        local Chain chain = GetTimerData(GetExpiredTimer())
        local unit dummy = null
        
        if chain.SetNextUnit() != true then            
            call chain.destroy()
            call ReleaseTimer(GetExpiredTimer())            
        else
            call chain.BanishAndLightning()
        endif           
    endfunction

and you don't kill the dummy units after you create them here??
Collapse JASS:
method BanishAndLightning takes nothing returns nothing
            local unit dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), bj_UNIT_FACING)
            debug call BJDebugMsg("BanishAndLightning")            
            call UnitAddAbility(dummy, BANISHID)
            call IssueTargetOrder(dummy, "banish", .targets[.index])            
            
            set dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index - 1]),  GetUnitY(.targets[.index - 1]), bj_UNIT_FACING)
            call UnitAddAbility(dummy, LIGHTNINGID)
            call IssueTargetOrder(dummy, "chainlightning", .targets[.index])
            
            set dummy = null
        endmethod

EDIT:
Quote:
The spell only works once. After that it only banishes and casts lightning on the first target of the spell or hitting units that aren't hit yet by a previous cast.

Try nulling the .targets array everytime you destroy the struct. Structs that are destroyed doesn't automatically null its values, so the previous units are still referred to by the .targets variable from the struct that was created at the first cast.
08-25-2009, 08:14 PM#9
Zerzax
Don't worry about nulling your TimerUtils timers - they are never destroyed, so the handle index doesn't need to be recycled. You might want to consider making your units group a global (or static) group and modifying your boolexpr such that it never admits units into the group - only parses through them and makes the appropriate adjustments if it meets the conditions. In that way, you could probably also avoid the GetTriggerUnit() call within the boolexpr by using a temp global that you set the casting unit to. It would also cut out the FirstOfGroup loop and speed things up a bit. That might not solve the CreateUnit problem but may help anyway.
08-27-2009, 05:52 AM#10
Vulcano
It's still not working, still same problem. I nulled the array onDestroy.

Collapse JASS:
scope ChainBanish initializer Init
    globals
        private constant integer SPELLID = 'A01O'
        private constant integer BANISHID = 'A00P'
        private constant integer LIGHTNINGID = 'A01Q'
        private constant integer TARGETS = 7
        private constant integer DUMMY = 'h009'
        private constant real PERIOD = 0.50
        private constant real BOUNCERANGE = 700.00
    endglobals
    
    //=============================================================================
    
    globals
        private boolexpr be
        private constant integer TARGETSPLUSONE = TARGETS + 1
    endglobals    
    
    private function isUnitEnemy takes nothing returns boolean
        return IsUnitEnemy(GetEnumUnit(), GetOwningPlayer(GetTriggerUnit()))
    endfunction
    
    private struct Chain
        unit array targets[TARGETSPLUSONE]
        integer index
        
        static method create takes unit u1, unit u2 returns Chain
            local Chain chain = Chain.allocate()
            set chain.targets[0] = u1
            set chain.targets[1] = u2
            set chain.index = 1
            return chain
        endmethod
        
        method onDestroy takes nothing returns nothing
            local integer index = 0
            loop
                exitwhen index > TARGETS
                set .targets[index] = null
                set index = index + 1
            endloop
        endmethod
                
        method BanishAndLightning takes nothing returns nothing
            local unit dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), bj_UNIT_FACING)
            debug call BJDebugMsg("BanishAndLightning")            
            call UnitAddAbility(dummy, BANISHID)
            call IssueTargetOrder(dummy, "banish", .targets[.index])            
            
            set dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index - 1]),  GetUnitY(.targets[.index - 1]), bj_UNIT_FACING)
            call UnitAddAbility(dummy, LIGHTNINGID)
            call IssueTargetOrder(dummy, "chainlightning", .targets[.index])
            
            set dummy = null
        endmethod
        
        method SetNextUnit takes nothing returns boolean
            local group units = NewGroup()
            local integer i = 0
            
            if .index == (TARGETS) then
                call ReleaseGroup(units)
                debug call BJDebugMsg("targets full")
                return false
            endif
            
            call GroupEnumUnitsInRange(units, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), BOUNCERANGE, be)
            set .index = .index + 1
            loop
                exitwhen i == .index
                if .targets[i] == FirstOfGroup(units) then
                    call GroupRemoveUnit( units, FirstOfGroup(units))
                    set i = -1
                endif
                set i = i + 1                
            endloop
            set .targets[.index] = FirstOfGroup(units)                        
            
            call ReleaseGroup(units)         
                        
            if .targets[.index] != null then
                debug call BJDebugMsg("unit found")
                return true
            else
                debug call BJDebugMsg("unit not found")
                return false
            endif
        endmethod
    endstruct
    
    private function Loop takes nothing returns nothing
        local Chain chain = GetTimerData(GetExpiredTimer())
        
        if chain.SetNextUnit() != true then            
            call ReleaseTimer(GetExpiredTimer())     
            call chain.destroy()                   
        else
            call chain.BanishAndLightning()
        endif           
    endfunction
    
    private function Actions takes nothing returns nothing
        local Chain chain = Chain.create(GetTriggerUnit(), GetSpellTargetUnit())
        local timer t = NewTimer()
        call chain.BanishAndLightning()
        call SetTimerData( t, chain)
        call TimerStart( t, PERIOD, true, function Loop)
    endfunction
    
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELLID
    endfunction

    private function Init takes nothing returns nothing
        local trigger gg_trg_Chain_Banish = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_Chain_Banish, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( gg_trg_Chain_Banish, Condition( function Conditions ) )
        call TriggerAddAction( gg_trg_Chain_Banish, function Actions )
        
        set be = Condition(function isUnitEnemy)
    endfunction
endscope

@TheWye:
-I forgot to remove the line with the local dummy
-My dummies have negative regen

@Zerzax:
-The CreateUnit problem is solved.
-Could you explain a bit more what you mean with a global group? I don't understand it.
08-27-2009, 06:59 AM#11
TheWye
Hurmm... what did I miss here.. I'm not using TimerUtils or GroupUtils (or whatever it is called) so I'm not sure about this....
Does
Code:
call ReleaseGroup(units)
remove all the units inside the group?

EDIT: even if it doesn't it still wouldn't fix your problem would it..?..??
hmmm...

EDIT2: so I assume that this
Collapse JASS:
if .targets[.index] != null then
    debug call BJDebugMsg("unit found")
    return true
else
    debug call BJDebugMsg("unit not found")
    return false
endif

always returns false after the first cast?

EDIT3:
what if you add a tempUnit variable here:
Collapse JASS:
            call GroupEnumUnitsInRange(units, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), BOUNCERANGE, be)
            set .index = .index + 1
            loop
                exitwhen i == .index
                set tempUnit= FirstOfGroup(units)
                if .targets[i] == tempUnit then
                    call GroupRemoveUnit( units, tempUnit )
                    set i = -1
                endif
                set i = i + 1                
            endloop
            set .targets[.index] = FirstOfGroup(units) 

Do you think it will help? (your code is quite confusing to me :p)

Anyway, if I were you, I would do this part this way instead:
Collapse JASS:
            call GroupEnumUnitsInRange(units, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), BOUNCERANGE, be)
            set .index = .index + 1
            loop
                exitwhen i == .index
                call GroupRemoveUnit( units, .targets[i])
                set i = i + 1                
            endloop
            set .targets[.index] = FirstOfGroup(units) 
08-27-2009, 02:40 PM#12
Zerzax
I didn't look at the code closely enough, so I don't know if this will apply exactly. Ooh, and I guess group recycling is fine as well. But you can try doing this:

Collapse JASS:
struct

    static group enumGroup //  now you have a global group that never gets destroyed.
    static boolexpr be // or a global, doesnt matter
    static integer tempCount = 0 // set this to 0 before using GroupEnumUnits()
    static player tempOwner = null // set this before using GroupEnumUnits()
    static Chain temp // same as above

    static method filter takes nothing returns boolean
        local unit enum = GetFilterUnit()
        
        if IsUnitEnemy(enum, .tempOwner) and .tempCount <= TARGETS then
            set .tempCount = .tempCount + 1
            if .tempCount == .temp.index then
                set enum == .temp.targets[.temp.index]  
            endif
        endif            
        return false
    endmethod

endstruct


I'm pretty unfamiliar with the idea behind this but I hope this helps anyway, no more firstofGroup or trigger natives
08-28-2009, 05:36 PM#13
Vulcano
The GetTriggerUnit in the boolexpr was bugging too. I think GetBlablaUnit only works in the function that is called by the trigger.

The only thing i changed was storing the owner of the caster in a variable and using the variable inside the condition func.

Final code (ignoring additional optimising):
Collapse JASS:
scope ChainBanish initializer Init
    globals
        private constant integer SPELLID = 'A01O'
        private constant integer BANISHID = 'A00P'
        private constant integer LIGHTNINGID = 'A01Q'
        private constant integer TARGETS = 7
        private constant integer DUMMY = 'h009'
        private constant real PERIOD = 0.50
        private constant real BOUNCERANGE = 700.00
    endglobals
    
    //=============================================================================
    
    globals
        private boolexpr be
        private constant integer TARGETSPLUSONE = TARGETS + 1
        private player tempPlayer
    endglobals    
    
    private function isUnitEnemy takes nothing returns boolean
        return IsUnitEnemy(GetFilterUnit(), tempPlayer)
    endfunction
    
    private struct Chain
        unit array targets[TARGETSPLUSONE]
        integer index
        
        static method create takes unit u1, unit u2 returns Chain
            local Chain chain = Chain.allocate()
            set chain.targets[0] = u1
            set chain.targets[1] = u2
            set chain.index = 1
            return chain
        endmethod       
        
        method onDestroy takes nothing returns nothing
            local integer index = 0
            loop
                exitwhen index > TARGETS
                set .targets[index] = null
                set index = index + 1
            endloop
        endmethod
                
        method BanishAndLightning takes nothing returns nothing
            local unit dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), bj_UNIT_FACING)
            debug call BJDebugMsg("BanishAndLightning")            
            call UnitAddAbility(dummy, BANISHID)
            call IssueTargetOrder(dummy, "banish", .targets[.index])            
            
            set dummy = CreateUnit( GetOwningPlayer(.targets[0]), DUMMY, GetUnitX(.targets[.index - 1]),  GetUnitY(.targets[.index - 1]), bj_UNIT_FACING)
            call UnitAddAbility(dummy, LIGHTNINGID)
            call IssueTargetOrder(dummy, "chainlightning", .targets[.index])
            
            set dummy = null
        endmethod
        
        method SetNextUnit takes nothing returns boolean
            local group units = NewGroup()
            local integer i = 0
            
            if .index == (TARGETS) then
                call ReleaseGroup(units)
                debug call BJDebugMsg("targets full")
                return false
            endif
            
            set tempPlayer = GetOwningPlayer(.targets[0])
            call GroupEnumUnitsInRange(units, GetUnitX(.targets[.index]), GetUnitY(.targets[.index]), BOUNCERANGE, be)
                        
            set .index = .index + 1
            loop
                exitwhen i == .index
                call GroupRemoveUnit( units, .targets[i])
                set i = i + 1                
            endloop
            set .targets[.index] = FirstOfGroup(units)                        
            
            call ReleaseGroup(units)         
                        
            if .targets[.index] != null then
                debug call BJDebugMsg("unit found")
                return true
            else
                debug call BJDebugMsg("unit not found")
                return false
            endif
        endmethod
    endstruct
    
    private function Loop takes nothing returns nothing
        local Chain chain = GetTimerData(GetExpiredTimer())
        
        if chain.SetNextUnit() != true then            
            call ReleaseTimer(GetExpiredTimer())     
            call chain.destroy()                   
        else
            call chain.BanishAndLightning()
        endif           
    endfunction
    
    private function Actions takes nothing returns nothing
        local Chain chain = Chain.create(GetTriggerUnit(), GetSpellTargetUnit())
        local timer t = NewTimer()
        call chain.BanishAndLightning()
        call SetTimerData( t, chain)
        call TimerStart( t, PERIOD, true, function Loop)
    endfunction
    
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELLID
    endfunction

    private function Init takes nothing returns nothing
        local trigger gg_trg_Chain_Banish = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_Chain_Banish, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( gg_trg_Chain_Banish, Condition( function Conditions ) )
        call TriggerAddAction( gg_trg_Chain_Banish, function Actions )
        
        set be = Condition(function isUnitEnemy)
    endfunction
endscope

When i can i will give you both some more rep :), finally solved this one month old problem.
08-29-2009, 12:43 AM#14
Zerzax
I'm glad it works :D
08-29-2009, 08:59 AM#15
TheWye
Ahhh I see. Good for you then!! And I learn something from this as well :)