1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. The 15th Mini-Mapping Contest came to an end. The Secrets of Warcraft 3 are soon to be revealed! Come and vote in the public poll for your favorite maps.
    Dismiss Notice
  4. The 12th incarnation of the Music Contest is LIVE! The theme is Synthwave. Knight Rider needs a song to listen to on his journey. You should definitely have some fun with this theme!
    Dismiss Notice
  5. Join other hivers in a friendly concept-art contest. The contestants have to create a genie coming out of its container. We wish you the best of luck!
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Group Control

Submitted by Xonok
This bundle is marked as approved. It works and satisfies the submission rules.
Ever wondered if it would be somehow possible to command more than 12 units at a time?
Well, now it's possible.

This resource actually contains of 2 resources + requirements.
The first resource is Group Control, which provides a standardized way to have groups of minions.
The other is GroupOrder, which makes each unit share commands to its minions when possible and enabled.

The testmap also contains Bribe's unit indexer, although any other unit indexer would work too.

How to import:
1. Make sure "Create unknown variables" is enabled in world editor settings.
2. Copy all triggers to your map.
3. Make sure that the variables in GCConfig point to the right abilities.
Now it should work.

How to use:
1. Select the commander and only the commander.
2. Recruit units with the accordingly named ability.
3. Turn on formations to make units remember their current positions relative to commander.
4. Give orders to the commander and each unit will try to perform the same orders.
5. Turn unit moving on/off to move the commander separately from units.

Some notes:
All point orders are given in relative coordinates. If the commander casts something 500 to the right from him, then each unit will try to cast the same thing to the 500 right from his own position.
All target orders are simply shared. Works well for clumping and also for focusing on one enemy at a time.
Targetless orders are also shared.
If a commander is given a command that the units can't perform, then they will simply ignore it. The commander will still perform it though.
Creating formations is too automatic at the moment. I believe someone might want units to move as a mass for some time and then immediately switch to a formation. Currently this can not be done.
Giving the defend command to commander will make all units stop, but not the commander itself. This is an issue with the game itself. (How to fix?)

It is highly likely that this system makes my previous system, CommanderSystem, pointless. However, technically this system here is much different, so simply updating CommanderSystem wouldn't be right.

Feedback is encouraged, as I wish to make this resource better.
Credits can be given if you deem it right, but it is not absolutely necessary.

Code:
Code (vJASS):
//
//              Group Control
//                by Xonok
//
//          Provides an API for making each unit have a group of owned units.
//          Owned units can be added/removed with functions
//          Dead units are removed automatically, their groups emptied.
//          

library GroupControl initializer InitTri_GroupControl
    //+ System globals. Don't use elsewhere
    globals
        private trigger DismissTrig = CreateTrigger()
        private trigger RecruitTrig = CreateTrigger()
        private trigger FormationTrig = CreateTrigger()
        private trigger SelectTrig = CreateTrigger()
        private trigger DeselectTrig = CreateTrigger()
        private trigger OrderTrig = CreateTrigger()
        private trigger OrderSwapTrig = CreateTrigger()
        private trigger UnitDieTrig = CreateTrigger()
        private unit u
        private unit caster
        private unit owner
        private player p
        private integer ID
        private integer ID2
        real array FormationX
        real array FormationY
        private string s
    endglobals
    //-
   
    //+ Public functions. Use them however you wish
    function ShowOwnageMarker takes unit u, boolean b returns nothing
        set s = ""
        set ID = GetUnitUserData(u)
        if udg_OwnageMarker[ID] != null then
            call DestroyEffect(udg_OwnageMarker[ID])
            set udg_OwnageMarker[ID] = null
        endif
        if b then
            if GetLocalPlayer() == GetOwningPlayer(u) then
                set s = "Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl"
            endif
            set udg_OwnageMarker[ID] = AddSpecialEffectTarget(s,u,"overhead")
        endif
        set s = ""
    endfunction
    function DismissUnit takes unit u returns nothing
        set ID = GetUnitUserData(u)
        set owner = udg_UnitOwner[ID]
        set ID2 = GetUnitUserData(owner)
        call GroupRemoveUnit(udg_OwnedUnits[ID2],u)
        set udg_UnitOwner[ID] = null
        call DestroyEffect(udg_OwnageMarker[ID])
        set udg_OwnageMarker[ID] = null
        set udg_OwnedUnitCount[ID2] = udg_OwnedUnitCount[ID2] - 1
    endfunction
    function RecruitUnit takes unit u, unit commander returns nothing
        set ID = GetUnitUserData(u)
        set ID2 = GetUnitUserData(commander)
        if udg_UnitOwner[ID] == null then
            if udg_OwnedUnits[ID2] == null then
                set udg_OwnedUnits[ID2] = CreateGroup()
            endif
            call GroupAddUnit(udg_OwnedUnits[ID2],u)
            set udg_UnitOwner[ID] = commander
            if IsUnitSelected(commander,GetOwningPlayer(commander)) then
                call ShowOwnageMarker(u,true)
                //set udg_OwnageMarker[ID] = AddSpecialEffectTarget("Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl",u,"overhead")
            endif
            set udg_OwnedUnitCount[ID2] = udg_OwnedUnitCount[ID2] + 1
        endif
    endfunction
    //-
   
    //+ System functions. Don't use elsewhere
    private function Dismiss takes nothing returns boolean
        if GetSpellAbilityId() == udg_DismissAbil then
            set u = GetSpellTargetUnit()
            call DismissUnit(u)
        endif
        return false
    endfunction
    private function Recruit takes nothing returns boolean
        if GetSpellAbilityId() == udg_RecruitAbil then
            set u = GetSpellTargetUnit()
            set caster = GetTriggerUnit()
            call RecruitUnit(u,caster)
        endif
        return false
    endfunction
    private function SaveCoords takes nothing returns nothing
        set u = GetEnumUnit()
        set ID2 = GetUnitUserData(u)
        set FormationX[ID2] = GetUnitX(u) - GetUnitX(owner)
        set FormationY[ID2] = GetUnitY(u) - GetUnitY(owner)
    endfunction
    private function Formation takes nothing returns boolean
        if GetSpellAbilityId() == udg_FormationOFFAbil then
            set owner = GetTriggerUnit()
            set ID = GetUnitUserData(owner)
            call ForGroup(udg_OwnedUnits[ID],function SaveCoords)
        elseif GetSpellAbilityId() == udg_FormationONAbil then
        endif
        return false
    endfunction
    private function GroupSelect takes nothing returns nothing
        call ShowOwnageMarker(GetEnumUnit(),true)
    endfunction
    private function GroupDeselect takes nothing returns nothing
        call ShowOwnageMarker(GetEnumUnit(),false)
    endfunction
    private function Select takes nothing returns boolean
        set u = GetTriggerUnit()
        if GetTriggerPlayer() == GetOwningPlayer(u) then
            set ID = GetUnitUserData(u)
            call ForGroup(udg_OwnedUnits[ID],function GroupSelect)
            //call ShowOwnageMarker(u,true)
        endif
        return false
    endfunction
    private function Deselect takes nothing returns boolean
        set u = GetTriggerUnit()
        if GetTriggerPlayer() == GetOwningPlayer(u) then
            set ID = GetUnitUserData(u)
            call ForGroup(udg_OwnedUnits[ID],function GroupDeselect)
            //call ShowOwnageMarker(u,false)
        endif
        return false
    endfunction
    private function CommanderDeath takes nothing returns nothing
        call DismissUnit(GetEnumUnit())
    endfunction
    private function UnitDie takes nothing returns boolean
        set u = GetTriggerUnit()
        set ID = GetUnitUserData(u)
        if udg_UnitOwner[ID] != null then
            set owner = udg_UnitOwner[ID]
            set ID2 = GetUnitUserData(owner)
            call GroupRemoveUnit(udg_OwnedUnits[ID2],u)
            set udg_OwnedUnitCount[ID2] = udg_OwnedUnitCount[ID2] - 1
            set udg_UnitOwner[ID] = null
            call DestroyEffect(udg_OwnageMarker[ID])
            set udg_OwnageMarker[ID] = null
        endif
        if udg_OwnedUnitCount[ID] > 0 then
            set owner = u
            set ID2 = ID
            call ForGroup(udg_OwnedUnits[ID2],function CommanderDeath)
        endif
        return false
    endfunction
    //-
   
    //++
    function InitTri_GroupControl takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen i > 15
            call TriggerRegisterPlayerUnitEvent(DismissTrig,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            call TriggerRegisterPlayerUnitEvent(RecruitTrig,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            call TriggerRegisterPlayerUnitEvent(FormationTrig,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            call TriggerRegisterPlayerUnitEvent(SelectTrig,Player(i), EVENT_PLAYER_UNIT_SELECTED, null)
            call TriggerRegisterPlayerUnitEvent(DeselectTrig,Player(i),EVENT_PLAYER_UNIT_DESELECTED, null)
            call TriggerRegisterPlayerUnitEvent(UnitDieTrig,Player(i),EVENT_PLAYER_UNIT_DEATH, null)
            set i = i + 1
        endloop
        call TriggerAddCondition(DismissTrig,Filter(function Dismiss))
        call TriggerAddCondition(RecruitTrig,Filter(function Recruit))
        call TriggerAddCondition(FormationTrig,Filter(function Formation))
        call TriggerAddCondition(SelectTrig,Filter(function Select))
        call TriggerAddCondition(DeselectTrig,Filter(function Deselect))
        call TriggerAddCondition(UnitDieTrig,Filter(function UnitDie))
    endfunction
endlibrary

Code (vJASS):
//
//              GroupOrder
//               by Xonok
//
//          This system provides the functionality to give orders to groups,
//          through simple functions.
//          This system requires GroupControl,
//          in order to access udg_OwnedUnits[]
//
//          GroupOrderTarget(group,order,target) -> nothing
//          |
//          Issues an order to all units in the group.
//          The order can target any widget(unit,tree,etc).
//        
//          GroupOrderPoint(group,order,x,y) -> nothing
//          |
//          Issues an order to all units in the group.
//          The provided coordinates are treated as absolute.
//
//          GroupOrderOffset(group,order,x,y) -> nothing
//          |
//          Issues an order to all units in the group.
//          The provided coordinates are treated as relative to the unit.
//
//          GroupOrder(group,order) -> nothing
//          |
//          Issues an untargeted order to all units in the group
//          
//          Invalid orders don't do anything (courtesy of blizzard)
//

library GroupOrder initializer InitTri_GroupOrder requires GroupControl
    globals
        private integer ID
        private integer ID2
        private real x
        private real y
        private real x2
        private real y2
        private real x3
        private real y3
        private real RefX
        private real RefY
        private unit caster
        private unit u
        private integer order
        private widget target
    endglobals
   
    //+ System functions. Not for using elsewhere
    private function TargetGroupOrder takes nothing returns nothing
        call IssueTargetOrderById(GetEnumUnit(),order,target)
    endfunction
    private function PointGroupOrder takes nothing returns nothing
        set u = GetEnumUnit()
        call IssuePointOrderById(u,order,x,y)
    endfunction
    private function OffsetGroupOrder takes nothing returns nothing
        set u = GetEnumUnit()
        call IssuePointOrderById(u,order,GetUnitX(u)+x,GetUnitY(u)+y)
    endfunction
    private function FormationGroupOrder takes nothing returns nothing
        set u = GetEnumUnit()
        set ID2 = GetUnitUserData(u)
        call IssuePointOrderById(u,order,x+FormationX[ID2],y+FormationY[ID2])
    endfunction
    private function OrderGroup takes nothing returns nothing
        call IssueImmediateOrderById(GetEnumUnit(),order)
    endfunction
    //-
   
    //+ Public functions. Use however you wish
    function GroupOrderTarget takes group g,integer order2,widget target2 returns nothing
        set order = order2
        set target = target2
        call ForGroup(g,function TargetGroupOrder)
    endfunction
    function GroupOrderPoint takes group g,integer order2,real x1,real y1 returns nothing
        set order = order2
        set x = x1
        set y = y1
        call ForGroup(g,function PointGroupOrder)
    endfunction
    function GroupOrderOffset takes group g, integer order2,real x1,real y1 returns nothing
        set order = order2
        set x = x1
        set y = y1
        call ForGroup(g,function OffsetGroupOrder)
    endfunction
    function GroupOrderFormation takes group g,integer order2,real x1,real y1 returns nothing
        set order = order2
        set x = x1
        set y = y1
        call ForGroup(g,function FormationGroupOrder)
    endfunction
    function GroupOrder takes group g, integer order2 returns nothing
        set order = order2
        call ForGroup(g,function OrderGroup)
    endfunction
    //-
   
    //+ System function. Must stay down here, as it references public functions.
    private function Order takes nothing returns boolean
        if GetUnitAbilityLevel(GetTriggerUnit(),udg_OrderONAbil) > 0 then
            set caster = GetTriggerUnit()
            set order = GetIssuedOrderId()
            set ID = GetUnitUserData(caster)
            if GetOrderTarget() != null then
                set target = GetOrderTarget()
                call GroupOrderTarget(udg_OwnedUnits[ID],order,target)
            elseif GetOrderPointX() != null then
                set x2 = GetUnitX(caster)
                set y2 = GetUnitY(caster)
                set x3 = GetOrderPointX()
                set y3 = GetOrderPointY()
                if GetUnitAbilityLevel(caster,udg_FormationONAbil) > 0 then
                    call GroupOrderFormation(udg_OwnedUnits[ID],order,x3,y3)
                else
                    call GroupOrderOffset(udg_OwnedUnits[ID],order,x3-x2,y3-y2)
                endif
            else
                call GroupOrder(udg_OwnedUnits[ID],order)
            endif
        endif
        return false
    endfunction

    //++
    function InitTri_GroupOrder takes nothing returns nothing
        local integer i = 0
        set gg_trg_GroupOrder = CreateTrigger(  )
        loop
            exitwhen i > 15
            call TriggerRegisterPlayerUnitEvent(gg_trg_GroupOrder,Player(i),EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER,null)
            call TriggerRegisterPlayerUnitEvent(gg_trg_GroupOrder,Player(i),EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER,null)
            call TriggerRegisterPlayerUnitEvent(gg_trg_GroupOrder,Player(i),EVENT_PLAYER_UNIT_ISSUED_ORDER,null)
            set i = i + 1
        endloop
        call TriggerAddCondition( gg_trg_GroupOrder, function Order )
    endfunction
endlibrary


Configuration can be done in GUI:
  • GCConf
    • Events
      • Time - Elapsed game time is 2.30 seconds
    • Conditions
    • Actions
      • Set DismissAbil = Dismiss Unit
      • Set FormationONAbil = Formation:ON
      • Set FormationOFFAbil = Formation:OFF
      • Set OrderOFFAbil = Orders:OFF
      • Set OrderONAbil = Orders:ON
      • Set RecruitAbil = Recruit Unit
      • -------- You can delete everything after this point once the system is imported. --------
      • -------- It is only here to make sure that all required variables get created. --------
      • Set OwnageMarker[0] = (Last created special effect)
      • Set OwnedUnitCount[0] = 0
      • Set OwnedUnits[0] = (Last created unit group)
      • Set UnitOwner[0] = No unit

Recommended way of turning group orders and formations on/off for specific commanders:
  • OrderSwap
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • -------- Example on how you can possibly enable/disable group orders --------
        • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Ability being cast) Equal to (==) OrderOFFAbil
          • Then - Actions
            • Unit - Remove OrderOFFAbil from (Triggering unit)
            • Unit - Add OrderONAbil to (Triggering unit)
            • Special Effect - Create a special effect attached to the origin of (Triggering unit) using Abilities\Spells\NightElf\BattleRoar\RoarCaster.mdl
            • Special Effect - Destroy (Last created special effect)
          • Else - Actions
            • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • (Ability being cast) Equal to (==) OrderONAbil
              • Then - Actions
                • Unit - Remove OrderONAbil from (Triggering unit)
                • Unit - Add OrderOFFAbil to (Triggering unit)
                • Special Effect - Create a special effect attached to the origin of (Triggering unit) using Abilities\Spells\NightElf\Taunt\TauntCaster.mdl
                • Special Effect - Destroy (Last created special effect)
              • Else - Actions
                • -------- Same with formations --------
                  • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Ability being cast) Equal to (==) FormationOFFAbil
                    • Then - Actions
                      • Unit - Remove FormationOFFAbil from (Triggering unit)
                      • Unit - Add FormationONAbil to (Triggering unit)
                    • Else - Actions
                      • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Ability being cast) Equal to (==) FormationONAbil
                        • Then - Actions
                          • Unit - Remove FormationONAbil from (Triggering unit)
                          • Unit - Add FormationOFFAbil to (Triggering unit)
                        • Else - Actions
Contents

Group Control v1.04 (Map)

Reviews
Moderator
12:22, 6th Dec 2013 Maker: A nice system though it takes a lot of space in command card. You could consider a spell book version and automatic formations
  1. Xonok

    Xonok

    Joined:
    Mar 27, 2012
    Messages:
    3,042
    Resources:
    8
    Spells:
    3
    Tutorials:
    5
    Resources:
    8
    Not really. Although I should clean it up quite a lot.
    However, first I should add features, as that is always a messy thing to do for me.
     
  2. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    So then, why was this approved when it is mandatory (except for a few rare cases) that you include the code in the post. Was the moderator high?
     
  3. Xonok

    Xonok

    Joined:
    Mar 27, 2012
    Messages:
    3,042
    Resources:
    8
    Spells:
    3
    Tutorials:
    5
    Resources:
    8
    Apparently that wasn't a problem. In any case, adding the code to first post is nothing hard.
     
  4. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,631
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
  5. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,193
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
  6. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Unless there were special circumstances, I don't personally know of any resource that has been approved without putting the code in the main post. Moderators have always said to put the code into the main post as well =)

    There are ofc reasons behind this. A user w/o wc3 on their computer can't view the code.
     
  7. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,631
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    What does that have to do with anything? Just because you don't remember something doesn't mean that the rules have changed.

    Also do I really need to bring up your UnitIndexer thread again? Your code isn't in the main post, yet you're bitching at the OP for not having his.

    You're either trolling or just plain stupid.
     
  8. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,193
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    No.

    Approved by Magtheridon96
    Approved by hvo-busterkomo
    Approved by Bribe
    Approved by Deuterium
    Approved by TriggerHappy
    Approved by Diablo-dk
    Approved by Eccho
    Approved by Dr Super Good
    Approved by Hanky
    Approved by The Reborn Devil
    Approved by PurplePoot
     
  9. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    my bad then, I'm thinking of JASS section rules :eek:

    plus, in a lot of the resources that I've seen commented on in the Spells section, people have, I suppose, asked for the author to put the code into the main post. I suppose that wasn't a requirement then, but requests from users ^)^.
     
  10. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,855
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    so you are the one breaking the rules at the end after all
     
  11. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,193
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    You are correct :)
     
  12. ToastAddict1057

    ToastAddict1057

    Joined:
    Oct 2, 2015
    Messages:
    78
    Resources:
    0
    Resources:
    0
    Its broken...when i'm gonna copy the triggers to my place it breaks :ogre_frown:
     
  13. Xonok

    Xonok

    Joined:
    Mar 27, 2012
    Messages:
    3,042
    Resources:
    8
    Spells:
    3
    Tutorials:
    5
    Resources:
    8
    It requires the JNGP editor.
     
  14. ToastAddict1057

    ToastAddict1057

    Joined:
    Oct 2, 2015
    Messages:
    78
    Resources:
    0
    Resources:
    0
    Thank you! it worked now!
     
  15. Clanzion

    Clanzion

    Joined:
    Jul 4, 2016
    Messages:
    384
    Resources:
    0
    Resources:
    0
    Just in case anyone is using in the future in recent patches and notice that units for players above 15 isn't working, you need to in the trigger GroupOrder and GroupControl, in the last function, you need to either increase the loop to 26, or switch the first group of calls with the TriggerRegisterAnyUnitEventBJ.

    I didn't know why it wasn't working for me at first until I changed it.
     
    Last edited: Mar 13, 2019
  16. Pyrogasm

    Pyrogasm

    Joined:
    Feb 27, 2007
    Messages:
    2,518
    Resources:
    0
    Resources:
    0
    For ease of copying:
    Code (vJASS):
        function InitTri_GroupControl takes nothing returns nothing
            local integer i = 0
            loop
                exitwhen i > 26 //changed to support 24p maps
                call TriggerRegisterPlayerUnitEvent(DismissTrig,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
                call TriggerRegisterPlayerUnitEvent(RecruitTrig,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
                call TriggerRegisterPlayerUnitEvent(FormationTrig,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
                call TriggerRegisterPlayerUnitEvent(SelectTrig,Player(i), EVENT_PLAYER_UNIT_SELECTED, null)
                call TriggerRegisterPlayerUnitEvent(DeselectTrig,Player(i),EVENT_PLAYER_UNIT_DESELECTED, null)
                call TriggerRegisterPlayerUnitEvent(UnitDieTrig,Player(i),EVENT_PLAYER_UNIT_DEATH, null)
                set i = i + 1
            endloop
            call TriggerAddCondition(DismissTrig,Filter(function Dismiss))
            call TriggerAddCondition(RecruitTrig,Filter(function Recruit))
            call TriggerAddCondition(FormationTrig,Filter(function Formation))
            call TriggerAddCondition(SelectTrig,Filter(function Select))
            call TriggerAddCondition(DeselectTrig,Filter(function Deselect))
            call TriggerAddCondition(UnitDieTrig,Filter(function UnitDie))
        endfunction